123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- using Jint.Runtime.Debugger;
- namespace Jint.Tests.Runtime.Debugger
- {
- public class CallStackTests
- {
- [Fact]
- public void IncludesFunctionNames()
- {
- var script = @"
- function foo()
- {
- debugger;
- }
-
- function bar()
- {
- foo();
- }
- bar()";
- TestHelpers.TestAtBreak(script, info =>
- {
- Assert.Collection(info.CallStack,
- frame => Assert.Equal("foo", frame.FunctionName),
- frame => Assert.Equal("bar", frame.FunctionName),
- frame => Assert.Equal("(anonymous)", frame.FunctionName)
- );
- });
- }
- [Fact]
- public void IncludesLocations()
- {
- var script = @"
- function foo()
- {
- debugger;
- }
-
- function bar()
- {
- foo();
- }
- bar()";
- TestHelpers.TestAtBreak(script, info =>
- {
- // The line numbers here may mislead - the positions are, as would be expected,
- // at the position before the currently executing line, not the line after.
- // Remember that Esprima (and hence Jint) line numbers are 1-based, not 0-based.
- Assert.Collection(info.CallStack,
- // "debugger;"
- frame => Assert.Equal(Position.From(4, 0), frame.Location.Start),
- // "foo();"
- frame => Assert.Equal(Position.From(9, 0), frame.Location.Start),
- // "bar();"
- frame => Assert.Equal(Position.From(12, 0), frame.Location.Start)
- );
- });
- }
- [Fact]
- public void IncludesFunctionLocations()
- {
- var script = @"
- function foo()
- {
- debugger;
- }
-
- function bar()
- {
- foo();
- }
- bar()";
- TestHelpers.TestAtBreak(script, info =>
- {
- // Remember that Esprima (and hence Jint) line numbers are 1-based, not 0-based.
- Assert.Collection(info.CallStack,
- // function foo()
- frame => Assert.Equal(Position.From(2, 0), frame.FunctionLocation?.Start),
- // function bar()
- frame => Assert.Equal(Position.From(7, 0), frame.FunctionLocation?.Start),
- // global - no function location
- frame => Assert.Equal(null, frame.FunctionLocation?.Start)
- );
- });
- }
- [Fact]
- public void HasReturnValue()
- {
- string script = @"
- function foo()
- {
- return 'result';
- }
- foo();";
- var engine = new Engine(options => options.DebugMode().InitialStepMode(StepMode.Into));
- bool atReturn = false;
- bool didCheckReturn = false;
- engine.Debugger.Step += (sender, info) =>
- {
- if (atReturn)
- {
- Assert.NotNull(info.CurrentCallFrame.ReturnValue);
- Assert.Equal("result", info.CurrentCallFrame.ReturnValue.AsString());
- didCheckReturn = true;
- atReturn = false;
- }
- if (info.CurrentNode is ReturnStatement)
- {
- // Step one further, and we should have the return value
- atReturn = true;
- }
- return StepMode.Into;
- };
- engine.Execute(script);
- Assert.True(didCheckReturn);
- }
- [Fact]
- public void HasThis()
- {
- string script = @"
- function Thing(name)
- {
- this.name = name;
- }
- Thing.prototype.test = function()
- {
- debugger;
- }
- var car = new Thing('car');
- car.test();
- ";
- TestHelpers.TestAtBreak(script, (engine, info) =>
- {
- Assert.Collection(info.CallStack,
- frame => Assert.Equal(engine.Realm.GlobalObject.Get("car"), frame.This),
- frame => Assert.Equal(engine.Realm.GlobalObject, frame.This)
- );
- });
- }
- [Fact]
- public void NamesRegularFunction()
- {
- string script = @"
- function regularFunction() { debugger; }
- regularFunction();";
- TestHelpers.TestAtBreak(script, info =>
- {
- Assert.Equal("regularFunction", info.CurrentCallFrame.FunctionName);
- });
- }
- [Fact]
- public void NamesFunctionExpression()
- {
- string script = @"
- const functionExpression = function() { debugger; }
- functionExpression()";
- TestHelpers.TestAtBreak(script, info =>
- {
- Assert.Equal("functionExpression", info.CurrentCallFrame.FunctionName);
- });
- }
- [Fact]
- public void NamesNamedFunctionExpression()
- {
- string script = @"
- const functionExpression = function namedFunction() { debugger; }
- functionExpression()";
- TestHelpers.TestAtBreak(script, info =>
- {
- Assert.Equal("namedFunction", info.CurrentCallFrame.FunctionName);
- });
- }
- [Fact]
- public void NamesArrowFunction()
- {
- string script = @"
- const arrowFunction = () => { debugger; }
- arrowFunction()";
- TestHelpers.TestAtBreak(script, info =>
- {
- Assert.Equal("arrowFunction", info.CurrentCallFrame.FunctionName);
- });
- }
- [Fact]
- public void NamesNewFunction()
- {
- string script = @"
- const newFunction = new Function('debugger;');
- newFunction()";
- TestHelpers.TestAtBreak(script, info =>
- {
- // Ideally, this should be "(anonymous)", but FunctionConstructor sets the "anonymous" name.
- Assert.Equal("anonymous", info.CurrentCallFrame.FunctionName);
- });
- }
- [Fact]
- public void NamesMemberFunction()
- {
- string script = @"
- const obj = { memberFunction() { debugger; } };
- obj.memberFunction()";
- TestHelpers.TestAtBreak(script, info =>
- {
- Assert.Equal("memberFunction", info.CurrentCallFrame.FunctionName);
- });
- }
- [Fact]
- public void NamesAnonymousFunction()
- {
- string script = @"
- (function()
- {
- debugger;
- }());";
- TestHelpers.TestAtBreak(script, info =>
- {
- Assert.Equal("(anonymous)", info.CurrentCallFrame.FunctionName);
- });
- }
- [Fact]
- public void NamesGetAccessor()
- {
- string script = @"
- const obj = {
- get accessor()
- {
- debugger;
- return 'test';
- }
- };
- const x = obj.accessor;";
- TestHelpers.TestAtBreak(script, info =>
- {
- Assert.Equal("get accessor", info.CurrentCallFrame.FunctionName);
- });
- }
- [Fact]
- public void NamesSetAccessor()
- {
- string script = @"
- const obj = {
- set accessor(value)
- {
- debugger;
- this.value = value;
- }
- };
- obj.accessor = 42;";
- TestHelpers.TestAtBreak(script, info =>
- {
- Assert.Equal("set accessor", info.CurrentCallFrame.FunctionName);
- });
- }
- }
- }
|