Skip to content

Commit

Permalink
Significantly reduce recursion limit
Browse files Browse the repository at this point in the history
  • Loading branch information
nilproject committed Aug 9, 2022
1 parent 7fabeb5 commit ef34019
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 230 deletions.
65 changes: 25 additions & 40 deletions NiL.JS/Core/Functions/MethodProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -345,25 +345,18 @@ private WrapperDelegate makeFastWrapper(MethodInfo methodInfo)
if (methodInfo.ReturnType == typeof(void))
tree = Expression.Block(tree, Expression.Constant(null));

try
{
return Expression
.Lambda<WrapperDelegate>(
Expression.Convert(tree, typeof(object)),
methodInfo.Name,
new[]
{
target,
context,
arguments,
argumentsObjectPrm
})
.Compile();
}
catch
{
throw;
}
return Expression
.Lambda<WrapperDelegate>(
Expression.Convert(tree, typeof(object)),
methodInfo.Name,
new[]
{
target,
context,
arguments,
argumentsObjectPrm
})
.Compile();
}

private WrapperDelegate makeFastWrapper(ConstructorInfo constructorInfo)
Expand Down Expand Up @@ -429,25 +422,18 @@ private WrapperDelegate makeFastWrapper(ConstructorInfo constructorInfo)
}
}

try
{
return Expression
.Lambda<WrapperDelegate>(
Expression.Convert(tree, typeof(object)),
constructorInfo.DeclaringType.Name,
new[]
{
target,
context,
arguments,
argumentsObjectPrm
})
.Compile();
}
catch
{
throw;
}
return Expression
.Lambda<WrapperDelegate>(
Expression.Convert(tree, typeof(object)),
constructorInfo.DeclaringType.Name,
new[]
{
target,
context,
arguments,
argumentsObjectPrm
})
.Compile();
}

private object callRestPrmsConverter(Context initiator, Expressions.Expression[] arguments, Arguments argumentsObject)
Expand Down Expand Up @@ -701,9 +687,8 @@ public override Delegate MakeDelegate(Type delegateType)
}
catch
{
return base.MakeDelegate(delegateType);
}

return base.MakeDelegate(delegateType);
}
#endif

Expand Down
33 changes: 30 additions & 3 deletions NiL.JS/Core/JSException.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using NiL.JS.BaseLibrary;
using NiL.JS.Core.Interop;

Expand Down Expand Up @@ -52,7 +53,7 @@ public JSException(Error avatar, Exception innerException)
Error = Context.CurrentGlobalContext.ProxyValue(avatar);
}

public override string StackTrace => _stackTraceOverride ?? base.StackTrace;
public override string StackTrace => (_stackTraceOverride ??= getStackTrace()) ?? base.StackTrace;

public override string Message
{
Expand Down Expand Up @@ -80,9 +81,35 @@ public override string Message
}
}

internal void InternalSetStackTrace(string stackTrace)
private string getStackTrace()
{
_stackTraceOverride = stackTrace;
var stackTrace = new List<string>();

var innerEx = this as Exception;
while (innerEx != null)
{
var isOurException = false;
for (var i = innerEx.Data.Count; i-- > 0;)
{
var item = innerEx.Data[new CallStackMarker(i)] as Tuple<Context, CodeCoordinates>;
if (item == null)
continue;

isOurException = true;
stackTrace.Add(" at " + (item.Item1?._owner?.name ?? "<unknown function>") + (item.Item2 != null ? ": line " + item.Item2.Line : string.Empty));
}

if (!isOurException)
stackTrace.Add(innerEx.StackTrace);

innerEx = innerEx.InnerException;
}

if (stackTrace.Count == 0)
return null;

stackTrace.Reverse();
return string.Join(Environment.NewLine, stackTrace);
}
}
}
18 changes: 18 additions & 0 deletions NiL.JS/ExceptionHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -204,5 +204,23 @@ internal static void Throw(Exception exception)
{
throw exception;
}

internal static void SetCallStackData(Exception e, Context context, CodeNode codeNode)
{
foreach (var item in e.Data.Values)
{
if ((item as Tuple<Context, CodeCoordinates>).Item1 == context)
return;
}

e.Data.Add(
new CallStackMarker(e.Data.Count),
Tuple.Create(
context,
CodeCoordinates.FromTextPosition(
ExceptionHelper.GetCode(context),
codeNode.Position,
codeNode.Length)));
}
}
}
120 changes: 52 additions & 68 deletions NiL.JS/Expressions/Call.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,72 +82,20 @@ public Call(Expression first, Expression[] arguments, bool optionalChaining)

public override JSValue Evaluate(Context context)
{
#if DEBUG
if (context._callDepth >= 800)
#else
if (context._callDepth >= 1000)
#endif
if (context._callDepth >= 60)
ExceptionHelper.Throw(new RangeError("Stack overflow."), this, context);

var function = _left.Evaluate(context);

JSValue targetObject = context._objectSource;

ICallable callable = null;
Function func = null;

if (function._valueType == JSValueType.Function)
{
func = function._oValue as Function;
callable = func;
}

if (func == null)
{
callable = function._oValue as ICallable;
if (callable == null)
callable = function.Value as ICallable;

if (callable == null)
{
var typeProxy = function.Value as Proxy;
if (typeProxy != null)
callable = typeProxy.PrototypeInstance as ICallable;
}

if (callable == null)
{
if (OptionalChaining)
return JSValue.undefined;

for (int i = 0; i < _arguments.Length; i++)
{
context._objectSource = null;
_arguments[i].Evaluate(context);
}

context._objectSource = null;

// Аргументы должны быть вычислены даже если функция не существует.
ExceptionHelper.ThrowTypeError(_left.ToString() + " is not a function", this, context);

return null;
}
}

if (func == null)
{
switch (_callMode)
{
case CallMode.Construct:
return callable.Construct(Tools.CreateArguments(_arguments, context));

case CallMode.Super:
return callable.Construct(targetObject, Tools.CreateArguments(_arguments, context));

default:
return callable.Call(targetObject, Tools.CreateArguments(_arguments, context));
}
return callCallable(context, targetObject, function);
}

if (_allowTCO
Expand Down Expand Up @@ -177,22 +125,58 @@ public override JSValue Evaluate(Context context)
}
catch (Exception e)
{
foreach(var item in e.Data.Values)
{
if ((item as Tuple<Context, CodeCoordinates>).Item1 == context)
throw;
}
ExceptionHelper.SetCallStackData(e, context, this);
throw;
}
}

e.Data.Add(
new CallStackMarker(e.Data.Count),
Tuple.Create(
context,
CodeCoordinates.FromTextPosition(
ExceptionHelper.GetCode(context),
Position,
Length)));
private void throwNaF(Context context)
{
for (int i = 0; i < _arguments.Length; i++)
{
context._objectSource = null;
_arguments[i].Evaluate(context);
}

throw;
context._objectSource = null;

// Аргументы должны быть вычислены даже если функция не существует.
ExceptionHelper.ThrowTypeError(_left.ToString() + " is not a function", this, context);
}

private JSValue callCallable(Context context, JSValue targetObject, JSValue function)
{
var callable = function._oValue as ICallable;
if (callable == null)
callable = function.Value as ICallable;

if (callable == null)
{
var typeProxy = function.Value as Proxy;
if (typeProxy != null)
callable = typeProxy.PrototypeInstance as ICallable;
}

if (callable == null)
{
if (OptionalChaining)
return JSValue.undefined;

throwNaF(context);

return null;
}

switch (_callMode)
{
case CallMode.Construct:
return callable.Construct(Tools.CreateArguments(_arguments, context));

case CallMode.Super:
return callable.Construct(targetObject, Tools.CreateArguments(_arguments, context));

default:
return callable.Call(targetObject, Tools.CreateArguments(_arguments, context));
}
}

Expand Down
Loading

0 comments on commit ef34019

Please sign in to comment.