-
-
Notifications
You must be signed in to change notification settings - Fork 547
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
1,185 additions
and
101 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
using Esprima; | ||
using Jint.Runtime.Debugger; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Text.RegularExpressions; | ||
using System.Threading.Tasks; | ||
using Xunit; | ||
|
||
namespace Jint.Tests.Runtime.Debugger | ||
{ | ||
public class BreakPointTests | ||
{ | ||
[Fact] | ||
public void BreakPointBreaksAtPosition() | ||
{ | ||
string script = @"let x = 1, y = 2; | ||
if (x === 1) | ||
{ | ||
x++; y *= 2; | ||
}"; | ||
|
||
var engine = new Engine(options => options.DebugMode()); | ||
|
||
bool didBreak = false; | ||
engine.Break += (sender, info) => | ||
{ | ||
Assert.Equal(4, info.CurrentStatement.Location.Start.Line); | ||
Assert.Equal(5, info.CurrentStatement.Location.Start.Column); | ||
didBreak = true; | ||
return StepMode.None; | ||
}; | ||
|
||
engine.BreakPoints.Add(new BreakPoint(4, 5)); | ||
engine.Execute(script); | ||
Assert.True(didBreak); | ||
} | ||
|
||
[Fact] | ||
public void BreakPointBreaksInCorrectSource() | ||
{ | ||
string script1 = @"let x = 1, y = 2; | ||
if (x === 1) | ||
{ | ||
x++; y *= 2; | ||
}"; | ||
|
||
string script2 = @"function test(x) | ||
{ | ||
return x + 2; | ||
}"; | ||
|
||
string script3 = @"const z = 3; | ||
test(z);"; | ||
|
||
var engine = new Engine(options => { options.DebugMode(); }); | ||
|
||
engine.BreakPoints.Add(new BreakPoint("script2", 3, 0)); | ||
|
||
bool didBreak = false; | ||
engine.Break += (sender, info) => | ||
{ | ||
Assert.Equal("script2", info.CurrentStatement.Location.Source); | ||
Assert.Equal(3, info.CurrentStatement.Location.Start.Line); | ||
Assert.Equal(0, info.CurrentStatement.Location.Start.Column); | ||
didBreak = true; | ||
return StepMode.None; | ||
}; | ||
|
||
// We need to specify the source to the parser. | ||
// And we need locations too (Jint specifies that in its default options) | ||
engine.Execute(script1, new ParserOptions("script1") { Loc = true }); | ||
Assert.False(didBreak); | ||
|
||
engine.Execute(script2, new ParserOptions("script2") { Loc = true }); | ||
Assert.False(didBreak); | ||
|
||
// Note that it's actually script3 that executes the function in script2 | ||
// and triggers the breakpoint | ||
engine.Execute(script3, new ParserOptions("script3") { Loc = true }); | ||
Assert.True(didBreak); | ||
} | ||
|
||
[Fact] | ||
public void DebuggerStatementTriggersBreak() | ||
{ | ||
string script = @"'dummy'; | ||
debugger; | ||
'dummy';"; | ||
|
||
var engine = new Engine(options => options | ||
.DebugMode() | ||
.DebuggerStatementHandling(DebuggerStatementHandling.Script)); | ||
|
||
bool didBreak = false; | ||
engine.Break += (sender, info) => | ||
{ | ||
didBreak = true; | ||
return StepMode.None; | ||
}; | ||
|
||
engine.Execute(script); | ||
|
||
Assert.True(didBreak); | ||
} | ||
|
||
[Fact(Skip = "Non-source breakpoint is triggered before Statement, while debugger statement is now triggered by ExecuteInternal")] | ||
public void DebuggerStatementAndBreakpointTriggerSingleBreak() | ||
{ | ||
string script = @"'dummy'; | ||
debugger; | ||
'dummy';"; | ||
|
||
var engine = new Engine(options => options | ||
.DebugMode() | ||
.DebuggerStatementHandling(DebuggerStatementHandling.Script)); | ||
|
||
engine.BreakPoints.Add(new BreakPoint(2, 0)); | ||
|
||
int breakTriggered = 0; | ||
engine.Break += (sender, info) => | ||
{ | ||
breakTriggered++; | ||
return StepMode.None; | ||
}; | ||
|
||
engine.Execute(script); | ||
|
||
Assert.Equal(1, breakTriggered); | ||
} | ||
|
||
[Fact] | ||
public void BreakpointOverridesStepOut() | ||
{ | ||
string script = @"function test() | ||
{ | ||
'dummy'; | ||
'source'; | ||
'dummy'; | ||
'target'; | ||
} | ||
test();"; | ||
|
||
var engine = new Engine(options => options.DebugMode()); | ||
|
||
engine.BreakPoints.Add(new BreakPoint(4, 0)); | ||
engine.BreakPoints.Add(new BreakPoint(6, 0)); | ||
|
||
int step = 0; | ||
engine.Break += (sender, info) => | ||
{ | ||
step++; | ||
switch (step) | ||
{ | ||
case 1: | ||
return StepMode.Out; | ||
case 2: | ||
Assert.True(info.ReachedLiteral("target")); | ||
break; | ||
} | ||
return StepMode.None; | ||
}; | ||
|
||
engine.Execute(script); | ||
|
||
Assert.Equal(2, step); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,228 @@ | ||
using Jint.Runtime.Debugger; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Xunit; | ||
|
||
namespace Jint.Tests.Runtime.Debugger | ||
{ | ||
public class CallStackTests | ||
{ | ||
[Fact] | ||
public void NamesRegularFunction() | ||
{ | ||
var engine = new Engine(options => options | ||
.DebugMode() | ||
.DebuggerStatementHandling(DebuggerStatementHandling.Script)); | ||
|
||
bool didBreak = false; | ||
engine.Break += (sender, info) => | ||
{ | ||
didBreak = true; | ||
Assert.Equal("regularFunction", info.CallStack.Peek()); | ||
return StepMode.None; | ||
}; | ||
|
||
engine.Execute( | ||
@"function regularFunction() { debugger; } | ||
regularFunction()"); | ||
|
||
Assert.True(didBreak); | ||
} | ||
|
||
[Fact] | ||
public void NamesFunctionExpression() | ||
{ | ||
var engine = new Engine(options => options | ||
.DebugMode() | ||
.DebuggerStatementHandling(DebuggerStatementHandling.Script)); | ||
|
||
bool didBreak = false; | ||
engine.Break += (sender, info) => | ||
{ | ||
didBreak = true; | ||
Assert.Equal("functionExpression", info.CallStack.Peek()); | ||
return StepMode.None; | ||
}; | ||
|
||
engine.Execute( | ||
@"const functionExpression = function() { debugger; } | ||
functionExpression()"); | ||
|
||
Assert.True(didBreak); | ||
} | ||
|
||
[Fact] | ||
public void NamesNamedFunctionExpression() | ||
{ | ||
var engine = new Engine(options => options | ||
.DebugMode() | ||
.DebuggerStatementHandling(DebuggerStatementHandling.Script)); | ||
|
||
bool didBreak = false; | ||
engine.Break += (sender, info) => | ||
{ | ||
didBreak = true; | ||
Assert.Equal("namedFunction", info.CallStack.Peek()); | ||
return StepMode.None; | ||
}; | ||
|
||
engine.Execute( | ||
@"const functionExpression = function namedFunction() { debugger; } | ||
functionExpression()"); | ||
|
||
Assert.True(didBreak); | ||
} | ||
|
||
[Fact] | ||
public void NamesArrowFunction() | ||
{ | ||
var engine = new Engine(options => options | ||
.DebugMode() | ||
.DebuggerStatementHandling(DebuggerStatementHandling.Script)); | ||
|
||
bool didBreak = false; | ||
engine.Break += (sender, info) => | ||
{ | ||
didBreak = true; | ||
Assert.Equal("arrowFunction", info.CallStack.Peek()); | ||
return StepMode.None; | ||
}; | ||
|
||
engine.Execute( | ||
@"const arrowFunction = () => { debugger; } | ||
arrowFunction()"); | ||
|
||
Assert.True(didBreak); | ||
} | ||
|
||
[Fact] | ||
public void NamesNewFunction() | ||
{ | ||
var engine = new Engine(options => options | ||
.DebugMode() | ||
.DebuggerStatementHandling(DebuggerStatementHandling.Script)); | ||
|
||
bool didBreak = false; | ||
engine.Break += (sender, info) => | ||
{ | ||
didBreak = true; | ||
// Ideally, this should be "(anonymous)", but FunctionConstructor sets the "anonymous" name. | ||
Assert.Equal("anonymous", info.CallStack.Peek()); | ||
return StepMode.None; | ||
}; | ||
|
||
engine.Execute( | ||
@"const newFunction = new Function('debugger;'); | ||
newFunction()"); | ||
|
||
Assert.True(didBreak); | ||
} | ||
|
||
[Fact] | ||
public void NamesMemberFunction() | ||
{ | ||
var engine = new Engine(options => options | ||
.DebugMode() | ||
.DebuggerStatementHandling(DebuggerStatementHandling.Script)); | ||
|
||
bool didBreak = false; | ||
engine.Break += (sender, info) => | ||
{ | ||
didBreak = true; | ||
Assert.Equal("memberFunction", info.CallStack.Peek()); | ||
return StepMode.None; | ||
}; | ||
|
||
engine.Execute( | ||
@"const obj = { memberFunction() { debugger; } }; | ||
obj.memberFunction()"); | ||
|
||
Assert.True(didBreak); | ||
} | ||
|
||
[Fact] | ||
public void NamesAnonymousFunction() | ||
{ | ||
var engine = new Engine(options => options | ||
.DebugMode() | ||
.DebuggerStatementHandling(DebuggerStatementHandling.Script)); | ||
|
||
bool didBreak = false; | ||
engine.Break += (sender, info) => | ||
{ | ||
didBreak = true; | ||
Assert.Equal("(anonymous)", info.CallStack.Peek()); | ||
return StepMode.None; | ||
}; | ||
|
||
engine.Execute( | ||
@"(function() | ||
{ | ||
debugger; | ||
}());"); | ||
|
||
Assert.True(didBreak); | ||
} | ||
|
||
[Fact(Skip = "Debugger has no accessor awareness yet")] | ||
public void NamesGetAccessor() | ||
{ | ||
var engine = new Engine(options => options | ||
.DebugMode() | ||
.DebuggerStatementHandling(DebuggerStatementHandling.Script)); | ||
|
||
bool didBreak = false; | ||
engine.Break += (sender, info) => | ||
{ | ||
didBreak = true; | ||
Assert.Equal("get accessor", info.CallStack.Peek()); | ||
return StepMode.None; | ||
}; | ||
|
||
engine.Execute( | ||
@" | ||
const obj = { | ||
get accessor() | ||
{ | ||
debugger; | ||
return 'test'; | ||
} | ||
}; | ||
const x = obj.accessor;"); | ||
|
||
Assert.True(didBreak); | ||
} | ||
|
||
[Fact(Skip = "Debugger has no accessor awareness yet")] | ||
public void NamesSetAccessor() | ||
{ | ||
var engine = new Engine(options => options | ||
.DebugMode() | ||
.DebuggerStatementHandling(DebuggerStatementHandling.Script)); | ||
|
||
bool didBreak = false; | ||
engine.Break += (sender, info) => | ||
{ | ||
didBreak = true; | ||
Assert.Equal("set accessor", info.CallStack.Peek()); | ||
return StepMode.None; | ||
}; | ||
|
||
engine.Execute( | ||
@" | ||
const obj = { | ||
set accessor(value) | ||
{ | ||
debugger; | ||
this.value = value; | ||
} | ||
}; | ||
obj.accessor = 42;"); | ||
|
||
Assert.True(didBreak); | ||
} | ||
} | ||
} |
Oops, something went wrong.