123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- using Jint.Runtime.Debugger;
- namespace Jint.Tests.Runtime.Debugger
- {
- public class StepFlowTests
- {
- private List<Node> CollectStepNodes(string script)
- {
- var engine = new Engine(options => options
- .DebugMode()
- .InitialStepMode(StepMode.Into));
- var nodes = new List<Node>();
- engine.Debugger.Step += (sender, info) =>
- {
- nodes.Add(info.CurrentNode);
- return StepMode.Into;
- };
- engine.Execute(script);
- return nodes;
- }
- [Fact]
- public void StepsThroughWhileLoop()
- {
- var script = @"
- let x = 0;
- while (x < 2)
- {
- x++;
- }
- ";
- var nodes = CollectStepNodes(script);
- Assert.Collection(nodes,
- node => Assert.IsType<VariableDeclaration>(node), // let x = 0;
- node => Assert.IsType<WhileStatement>(node), // while ...
- node => Assert.IsType<BinaryExpression>(node), // x < 2
- node => Assert.IsType<ExpressionStatement>(node), // x++;
- node => Assert.IsType<BinaryExpression>(node), // x < 2
- node => Assert.IsType<ExpressionStatement>(node), // x++;
- node => Assert.IsType<BinaryExpression>(node) // x < 2 (false)
- );
- }
- [Fact]
- public void StepsThroughDoWhileLoop()
- {
- var script = @"
- let x = 0;
- do
- {
- x++;
- }
- while (x < 2)
- ";
- var nodes = CollectStepNodes(script);
- Assert.Collection(nodes,
- node => Assert.IsType<VariableDeclaration>(node), // let x = 0;
- node => Assert.IsType<DoWhileStatement>(node), // do ...
- node => Assert.IsType<ExpressionStatement>(node), // x++;
- node => Assert.IsType<BinaryExpression>(node), // x < 2
- node => Assert.IsType<ExpressionStatement>(node), // x++;
- node => Assert.IsType<BinaryExpression>(node) // x < 2 (false)
- );
- }
- [Fact]
- public void StepsThroughForLoop()
- {
- var script = @"
- for (let x = 0; x < 2; x++)
- {
- 'dummy';
- }
- ";
- var nodes = CollectStepNodes(script);
- Assert.Collection(nodes,
- node => Assert.IsType<ForStatement>(node), // for ...
- node => Assert.IsType<VariableDeclaration>(node), // let x = 0
- node => Assert.IsType<BinaryExpression>(node), // x < 2
- node => Assert.True(node.IsLiteral("dummy")), // 'dummy';
- node => Assert.IsType<UpdateExpression>(node), // x++;
- node => Assert.IsType<BinaryExpression>(node), // x < 2
- node => Assert.True(node.IsLiteral("dummy")), // 'dummy';
- node => Assert.IsType<UpdateExpression>(node), // x++;
- node => Assert.IsType<BinaryExpression>(node) // x < 2 (false)
- );
- }
- [Fact]
- public void StepsThroughForOfLoop()
- {
- var script = @"
- const arr = [1, 2];
- for (const item of arr)
- {
- 'dummy';
- }
- ";
- var nodes = CollectStepNodes(script);
- Assert.Collection(nodes,
- node => Assert.IsType<VariableDeclaration>(node), // let arr = [1, 2];
- node => Assert.IsType<ForOfStatement>(node), // for ...
- node => Assert.IsType<VariableDeclaration>(node), // item
- node => Assert.True(node.IsLiteral("dummy")), // 'dummy';
- node => Assert.IsType<VariableDeclaration>(node), // item
- node => Assert.True(node.IsLiteral("dummy")) // 'dummy';
- );
- }
- [Fact]
- public void StepsThroughForInLoop()
- {
- var script = @"
- const obj = { x: 1, y: 2 };
- for (const key in obj)
- {
- 'dummy';
- }
- ";
- var nodes = CollectStepNodes(script);
- Assert.Collection(nodes,
- node => Assert.IsType<VariableDeclaration>(node), // let obj = { x: 1, y: 2 };
- node => Assert.IsType<ForInStatement>(node), // for ...
- node => Assert.IsType<VariableDeclaration>(node), // key
- node => Assert.IsType<ExpressionStatement>(node), // 'dummy';
- node => Assert.IsType<VariableDeclaration>(node), // key
- node => Assert.IsType<ExpressionStatement>(node) // 'dummy';
- );
- }
- [Fact]
- public void StepsThroughConstructor()
- {
- var script = @"
- class Test
- {
- constructor()
- {
- 'in constructor';
- }
- }
- new Test();
- 'after construction';
- ";
- var nodes = CollectStepNodes(script);
- Assert.Collection(nodes,
- node => Assert.IsType<ClassDeclaration>(node), // class Test
- node => Assert.IsType<ExpressionStatement>(node), // new Test();
- node => Assert.True(node.IsLiteral("in constructor")), // 'in constructor()'
- node => Assert.Null(node), // return point
- node => Assert.True(node.IsLiteral("after construction"))
- );
- }
- [Fact]
- public void SkipsFunctionBody()
- {
- var script = @"
- function test()
- {
- 'dummy';
- }
- test();
- ";
- var nodes = CollectStepNodes(script);
- Assert.Collection(nodes,
- node => Assert.IsType<FunctionDeclaration>(node), // function(test) ...;
- node => Assert.IsType<ExpressionStatement>(node), // test();
- node => Assert.True(node.IsLiteral("dummy")), // 'dummy';
- node => Assert.Null(node) // return point
- );
- }
- [Fact]
- public void SkipsReturnPointOfImplicitConstructor()
- {
- var script = @"
- class Test
- {
- }
- new Test();
- 'dummy';
- ";
- var nodes = CollectStepNodes(script);
- Assert.Collection(nodes,
- node => Assert.IsType<ClassDeclaration>(node), // class Test
- node => Assert.IsType<ExpressionStatement>(node), // new Test();
- node => Assert.True(node.IsLiteral("dummy")) // 'dummy';
- );
- }
- [Fact]
- public void StepIntoNamedFunctionCalls()
- {
- var script = @"
- function a( ) { return 2; }
- function b(l) { return l + a(); }
- function c( ) { return b(3) + a(); }
- let res = c();
- ";
- var steps = StepIntoScript(script);
- Assert.Collection(steps,
- step => Assert.Equal("function c( ) { »return b(3) + a(); }", step),
- step => Assert.Equal("function b(l) { »return l + a(); }", step),
- step => Assert.Equal("function a( ) { »return 2; }", step),
- step => Assert.Equal("function a( ) { return 2; }»", step),
- step => Assert.Equal("function b(l) { return l + a(); }»", step),
- step => Assert.Equal("function a( ) { »return 2; }", step),
- step => Assert.Equal("function a( ) { return 2; }»", step),
- step => Assert.Equal("function c( ) { return b(3) + a(); }»", step));
- }
- [Fact]
- public void StepIntoArrowFunctionCalls()
- {
- var script = @"
- const a = ( ) => 2;
- const b = (l) => l + a();
- const c = ( ) => b(3) + a();
- let res = c();
- ";
- var steps = StepIntoScript(script);
- Assert.Collection(steps,
- step => Assert.Equal("const c = ( ) => »b(3) + a();", step),
- step => Assert.Equal("const b = (l) => »l + a();", step),
- step => Assert.Equal("const a = ( ) => »2;", step),
- step => Assert.Equal("const a = ( ) => 2»;", step),
- step => Assert.Equal("const b = (l) => l + a()»;", step),
- step => Assert.Equal("const a = ( ) => »2;", step),
- step => Assert.Equal("const a = ( ) => 2»;", step),
- step => Assert.Equal("const c = ( ) => b(3) + a()»;", step));
- }
- private List<string> StepIntoScript(string script)
- {
- var engine = new Engine(options => options
- .DebugMode()
- .InitialStepMode(StepMode.Into));
- var stepStatements = new List<string>();
- var scriptLines = script.Replace("\r\n", "\n").Replace("\r", "\n").Split('\n');
- engine.Debugger.Step += (sender, information) =>
- {
- if (information.CurrentNode is not VariableDeclaration && information.CurrentNode is not FunctionDeclaration)
- OutputPosition(information.Location);
- return StepMode.Into;
- };
- engine.Execute(script);
- return stepStatements;
- void OutputPosition(in SourceLocation location)
- {
- var line = scriptLines[location.Start.Line - 1];
- var withPositionIndicator = string.Concat(line.Substring(0, location.Start.Column), "»", line.Substring(location.Start.Column));
- stepStatements.Add(withPositionIndicator.TrimEnd());
- }
- }
- }
- }
|