Skip to content

Commit

Permalink
Fix IIFE stack trace
Browse files Browse the repository at this point in the history
  • Loading branch information
lahma committed Feb 27, 2021
1 parent 89ac4fb commit 54bf05e
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 16 deletions.
34 changes: 34 additions & 0 deletions Jint.Tests/Runtime/ErrorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,40 @@ public void StackTraceCollectedOnThreeLevels()

EqualIgnoringNewLineDifferences(expected, ex.ToString());
}

[Fact]
public void StackTraceCollectedForImmediatelyInvokedFunctionExpression()
{
var engine = new Engine();
const string script = @"function getItem(items, itemIndex) {
var item = items[itemIndex];
return item;
}
(function (getItem) {
var items = null,
item = getItem(items, 5)
;
return item;
})(getItem);";

var parserOptions = new ParserOptions("get-item.js")
{
AdaptRegexp = true,
Tolerant = true
};
var ex = Assert.Throws<JavaScriptException>(() => engine.Execute(script, parserOptions));

const string expected = @"Jint.Runtime.JavaScriptException: Cannot read property '5' of null
at getItem (items, itemIndex) get-item.js:2:22
at (anonymous) (getItem) get-item.js:9:16
at get-item.js:13:2";

EqualIgnoringNewLineDifferences(expected, ex.ToString());
}


private static void EqualIgnoringNewLineDifferences(string expected, string actual)
{
Expand Down
1 change: 0 additions & 1 deletion Jint/Native/Array/ArrayPrototype.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Jint.Collections;
using Jint.Native.Number;
Expand Down
15 changes: 13 additions & 2 deletions Jint/Runtime/CallStack/CallStackElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,19 @@ namespace Jint.Runtime.CallStack
public readonly FunctionInstance Function;
public readonly JintExpression? Expression;

public Location Location =>
Expression?._expression.Location ?? ((Node?) Function._functionDefinition?.Function)?.Location ?? default;
public Location Location
{
get
{
var expressionLocation = Expression?._expression.Location;
if (expressionLocation != null && expressionLocation.Value != default)
{
return expressionLocation.Value;
}

return ((Node?) Function._functionDefinition?.Function)?.Location ?? default;
}
}

public NodeList<Expression>? Arguments =>
Function._functionDefinition?.Function.Params;
Expand Down
16 changes: 8 additions & 8 deletions Jint/Runtime/CallStack/JintCallStack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ internal string BuildCallStackString(Location location)
static void AppendLocation(
StringBuilder sb,
string shortDescription,
Location loc,
in NodeList<Expression>? arguments)
in Location loc,
in CallStackElement? element)
{
sb
.Append(" at");
Expand All @@ -91,18 +91,18 @@ internal string BuildCallStackString(Location location)
.Append(shortDescription);
}

if (arguments is not null)
if (element?.Arguments is not null)
{
// it's a function
sb.Append(" (");
for (var index = 0; index < arguments.Value.Count; index++)
for (var index = 0; index < element.Value.Arguments.Value.Count; index++)
{
if (index != 0)
{
sb.Append(", ");
}

var arg = arguments.Value[index];
var arg = element.Value.Arguments.Value[index];
sb.Append(GetPropertyKey(arg));
}
sb.Append(")");
Expand All @@ -112,7 +112,7 @@ internal string BuildCallStackString(Location location)
.Append(" ")
.Append(loc.Source)
.Append(":")
.Append(loc.Start.Line)
.Append(loc.End.Line)
.Append(":")
.Append(loc.Start.Column + 1) // report column number instead of index
.AppendLine();
Expand All @@ -125,7 +125,7 @@ internal string BuildCallStackString(Location location)
var element = index >= 0 ? _stack[index] : (CallStackElement?) null;
var shortDescription = element?.ToString() ?? "";

AppendLocation(sb.Builder, shortDescription, location, element?.Arguments);
AppendLocation(sb.Builder, shortDescription, location, element);

location = element?.Location ?? default;
index--;
Expand All @@ -135,7 +135,7 @@ internal string BuildCallStackString(Location location)
element = index >= 0 ? _stack[index] : null;
shortDescription = element?.ToString() ?? "";

AppendLocation(sb.Builder, shortDescription, location, element?.Arguments);
AppendLocation(sb.Builder, shortDescription, location, element);

location = element?.Location ?? default;
index--;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ protected override object EvaluateInternal()
var property = _determinedProperty ?? _propertyExpression.GetValue();
if (baseValue.IsNullOrUndefined())
{
TypeConverter.CheckObjectCoercible(_engine, baseValue, _memberExpression.Property, _determinedProperty?.ToString() ?? baseReferenceName);
TypeConverter.CheckObjectCoercible(_engine, baseValue, _memberExpression.Property, TypeConverter.ToString(property));
}

// only convert if necessary
Expand Down
7 changes: 3 additions & 4 deletions Jint/Runtime/TypeConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.CompilerServices;
using Esprima;
using Esprima.Ast;
using Jint.Native;
using Jint.Native.Number;
Expand Down Expand Up @@ -552,20 +551,20 @@ private static ObjectInstance ToObjectNonObject(Engine engine, JsValue value)
{
if (!engine.Options.ReferenceResolver.CheckCoercible(o))
{
ThrowMemberNullOrUndefinedError(engine, o, sourceNode.Location, referenceName);
ThrowMemberNullOrUndefinedError(engine, o, sourceNode, referenceName);
}
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowMemberNullOrUndefinedError(
Engine engine,
JsValue o,
in Location location,
Node sourceNode,
string referencedName)
{
referencedName ??= "unknown";
var message = $"Cannot read property '{referencedName}' of {o}";
throw new JavaScriptException(engine.TypeError, message).SetCallstack(engine, location);
throw new JavaScriptException(engine.TypeError, message).SetCallstack(engine, sourceNode.Location);
}

public static void CheckObjectCoercible(Engine engine, JsValue o)
Expand Down

0 comments on commit 54bf05e

Please sign in to comment.