diff --git a/Directory.Packages.props b/Directory.Packages.props
index 917e1a124..912e7c868 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -25,6 +25,8 @@
+
+
diff --git a/Jint.AotExample/Jint.AotExample.csproj b/Jint.AotExample/Jint.AotExample.csproj
index 9072d51b5..9d46980f5 100644
--- a/Jint.AotExample/Jint.AotExample.csproj
+++ b/Jint.AotExample/Jint.AotExample.csproj
@@ -6,6 +6,7 @@
enable
false
true
+ $(NoWarn);NU1507
diff --git a/Jint.Repl/Jint.Repl.csproj b/Jint.Repl/Jint.Repl.csproj
index a5cec8738..e5b0992ff 100644
--- a/Jint.Repl/Jint.Repl.csproj
+++ b/Jint.Repl/Jint.Repl.csproj
@@ -4,6 +4,7 @@
Exe
false
true
+ $(NoWarn);NU1507
diff --git a/Jint.Tests.CommonScripts/Jint.Tests.CommonScripts.csproj b/Jint.Tests.CommonScripts/Jint.Tests.CommonScripts.csproj
index c3c478749..4704422d9 100644
--- a/Jint.Tests.CommonScripts/Jint.Tests.CommonScripts.csproj
+++ b/Jint.Tests.CommonScripts/Jint.Tests.CommonScripts.csproj
@@ -4,6 +4,7 @@
net9.0
$(TargetFrameworks);net472
false
+ $(NoWarn);NU1507
diff --git a/Jint.Tests.PublicInterface/Jint.Tests.PublicInterface.csproj b/Jint.Tests.PublicInterface/Jint.Tests.PublicInterface.csproj
index 7db90bf78..03558e448 100644
--- a/Jint.Tests.PublicInterface/Jint.Tests.PublicInterface.csproj
+++ b/Jint.Tests.PublicInterface/Jint.Tests.PublicInterface.csproj
@@ -5,6 +5,7 @@
$(TargetFrameworks);net472
false
612
+ $(NoWarn);NU1507
true
diff --git a/Jint.Tests.Test262/Jint.Tests.Test262.csproj b/Jint.Tests.Test262/Jint.Tests.Test262.csproj
index 494477487..2323f9d9d 100644
--- a/Jint.Tests.Test262/Jint.Tests.Test262.csproj
+++ b/Jint.Tests.Test262/Jint.Tests.Test262.csproj
@@ -6,6 +6,7 @@
true
false
$(NoWarn);CS8002
+ $(NoWarn);NU1507
Generated
diff --git a/Jint.Tests/Jint.Tests.csproj b/Jint.Tests/Jint.Tests.csproj
index 387212c06..18706619c 100644
--- a/Jint.Tests/Jint.Tests.csproj
+++ b/Jint.Tests/Jint.Tests.csproj
@@ -7,6 +7,7 @@
true
false
$(NoWarn);612
+ $(NoWarn);NU1507
diff --git a/Jint/Engine.Async.cs b/Jint/Engine.Async.cs
new file mode 100644
index 000000000..310b85d6c
--- /dev/null
+++ b/Jint/Engine.Async.cs
@@ -0,0 +1,194 @@
+using System.Runtime.CompilerServices;
+using Jint.Native;
+using Jint.Native.Function;
+using Jint.Runtime;
+using Jint.Runtime.Interpreter;
+using Jint.Runtime.Interpreter.Expressions;
+
+namespace Jint;
+
+public partial class Engine
+{
+ ///
+ /// Invoke the current value as function.
+ ///
+ /// The name of the function to call.
+ /// The arguments of the function call.
+ /// The value returned by the function call.
+ public ValueTask InvokeAsync(string propertyName, params object?[] arguments)
+ {
+ return InvokeAsync(propertyName, thisObj: null, arguments);
+ }
+
+ ///
+ /// Invoke the current value as function.
+ ///
+ /// The name of the function to call.
+ /// The this value inside the function call.
+ /// The arguments of the function call.
+ /// The value returned by the function call.
+ public ValueTask InvokeAsync(string propertyName, object? thisObj, object?[] arguments)
+ {
+ var value = GetValue(propertyName);
+
+ return InvokeAsync(value, thisObj, arguments);
+ }
+
+ ///
+ /// Invoke the current value as function.
+ ///
+ /// The function to call.
+ /// The arguments of the function call.
+ /// The value returned by the function call.
+ public ValueTask InvokeAsync(JsValue value, params object?[] arguments)
+ {
+ return InvokeAsync(value, thisObj: null, arguments);
+ }
+
+ ///
+ /// Invoke the current value as function.
+ ///
+ /// The function to call.
+ /// The this value inside the function call.
+ /// The arguments of the function call.
+ /// The value returned by the function call.
+ public async ValueTask InvokeAsync(JsValue value, object? thisObj, object?[] arguments)
+ {
+ var callable = value as ICallable;
+ if (callable is null)
+ {
+ ExceptionHelper.ThrowJavaScriptException(Realm.Intrinsics.TypeError, "Can only invoke functions");
+ }
+
+ async ValueTask DoInvokeAsync()
+ {
+ var items = _jsValueArrayPool.RentArray(arguments.Length);
+ for (var i = 0; i < arguments.Length; ++i)
+ {
+ items[i] = JsValue.FromObject(this, arguments[i]);
+ }
+
+ // ensure logic is in sync between Call, Construct, engine.Invoke and JintCallExpression!
+ JsValue result;
+ var thisObject = JsValue.FromObject(this, thisObj);
+ if (callable is Function functionInstance)
+ {
+ var callStack = CallStack;
+ callStack.Push(functionInstance, expression: null, ExecutionContext);
+ try
+ {
+ result = await callable.CallAsync(thisObject, items).ConfigureAwait(false);
+ }
+ finally
+ {
+ // if call stack was reset due to recursive call to engine or similar, we might not have it anymore
+ if (callStack.Count > 0)
+ {
+ callStack.Pop();
+ }
+ }
+ }
+ else
+ {
+ result = await callable.CallAsync(thisObject, items).ConfigureAwait(false);
+ }
+
+ _jsValueArrayPool.ReturnArray(items);
+ return result;
+ }
+
+ return await ExecuteWithConstraintsAsync(Options.Strict, DoInvokeAsync).ConfigureAwait(false);
+ }
+
+ ///
+ /// Invokes the callable and returns the resulting object.
+ ///
+ /// The callable.
+ /// Value bound as this.
+ /// The arguments of the call.
+ /// The value returned by the call.
+ public ValueTask CallAsync(JsValue callable, JsValue thisObject, JsValue[] arguments)
+ {
+ ValueTask Callback()
+ {
+ if (!callable.IsCallable)
+ {
+ ExceptionHelper.ThrowArgumentException(callable + " is not callable");
+ }
+
+ return CallAsync((ICallable) callable, thisObject, arguments, null);
+ }
+
+ return ExecuteWithConstraintsAsync(Options.Strict, Callback);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal ValueTask CallAsync(ICallable callable, JsValue thisObject, JsValue[] arguments, JintExpression? expression)
+ {
+ if (callable is Function functionInstance)
+ {
+ return CallAsync(functionInstance, thisObject, arguments, expression);
+ }
+
+ return callable.CallAsync(thisObject, arguments);
+ }
+
+ internal async ValueTask CallAsync(
+ Function function,
+ JsValue thisObject,
+ JsValue[] arguments,
+ JintExpression? expression)
+ {
+ // ensure logic is in sync between Call, Construct, engine.Invoke and JintCallExpression!
+
+ var recursionDepth = CallStack.Push(function, expression, ExecutionContext);
+
+ if (recursionDepth > Options.Constraints.MaxRecursionDepth)
+ {
+ // automatically pops the current element as it was never reached
+ ExceptionHelper.ThrowRecursionDepthOverflowException(CallStack);
+ }
+
+ JsValue result;
+ try
+ {
+ result = await function.CallAsync(thisObject, arguments).ConfigureAwait(false);
+ }
+ finally
+ {
+ // if call stack was reset due to recursive call to engine or similar, we might not have it anymore
+ if (CallStack.Count > 0)
+ {
+ CallStack.Pop();
+ }
+ }
+
+ return result;
+ }
+
+ internal async ValueTask ExecuteWithConstraintsAsync(bool strict, Func> callback)
+ {
+ ResetConstraints();
+
+ var ownsContext = _activeEvaluationContext is null;
+ _activeEvaluationContext ??= new EvaluationContext(this);
+
+ try
+ {
+ using (new StrictModeScope(strict))
+ {
+ return await callback().ConfigureAwait(false);
+ }
+ }
+ finally
+ {
+ if (ownsContext)
+ {
+ _activeEvaluationContext = null!;
+ }
+ ResetConstraints();
+ _agent.ClearKeptObjects();
+ }
+ }
+
+}
diff --git a/Jint/Engine.cs b/Jint/Engine.cs
index 651ced817..1cb0f7818 100644
--- a/Jint/Engine.cs
+++ b/Jint/Engine.cs
@@ -1,5 +1,5 @@
-using System.Diagnostics;
-using System.Collections.Concurrent;
+using System.Collections.Concurrent;
+using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using Jint.Collections;
@@ -759,50 +759,7 @@ public JsValue Invoke(JsValue value, params object?[] arguments)
/// The value returned by the function call.
public JsValue Invoke(JsValue value, object? thisObj, object?[] arguments)
{
- var callable = value as ICallable;
- if (callable is null)
- {
- ExceptionHelper.ThrowJavaScriptException(Realm.Intrinsics.TypeError, "Can only invoke functions");
- }
-
- JsValue DoInvoke()
- {
- var items = _jsValueArrayPool.RentArray(arguments.Length);
- for (var i = 0; i < arguments.Length; ++i)
- {
- items[i] = JsValue.FromObject(this, arguments[i]);
- }
-
- // ensure logic is in sync between Call, Construct, engine.Invoke and JintCallExpression!
- JsValue result;
- var thisObject = JsValue.FromObject(this, thisObj);
- if (callable is Function functionInstance)
- {
- var callStack = CallStack;
- callStack.Push(functionInstance, expression: null, ExecutionContext);
- try
- {
- result = functionInstance.Call(thisObject, items);
- }
- finally
- {
- // if call stack was reset due to recursive call to engine or similar, we might not have it anymore
- if (callStack.Count > 0)
- {
- callStack.Pop();
- }
- }
- }
- else
- {
- result = callable.Call(thisObject, items);
- }
-
- _jsValueArrayPool.ReturnArray(items);
- return result;
- }
-
- return ExecuteWithConstraints(Options.Strict, DoInvoke);
+ return InvokeAsync(value, thisObj, arguments).Preserve().GetAwaiter().GetResult();
}
internal T ExecuteWithConstraints(bool strict, Func callback)
@@ -1448,28 +1405,7 @@ public JsValue Call(JsValue callable, params JsValue[] arguments)
/// The value returned by the call.
public JsValue Call(JsValue callable, JsValue thisObject, JsValue[] arguments)
{
- JsValue Callback()
- {
- if (!callable.IsCallable)
- {
- ExceptionHelper.ThrowArgumentException(callable + " is not callable");
- }
-
- return Call((ICallable) callable, thisObject, arguments, null);
- }
-
- return ExecuteWithConstraints(Options.Strict, Callback);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal JsValue Call(ICallable callable, JsValue thisObject, JsValue[] arguments, JintExpression? expression)
- {
- if (callable is Function functionInstance)
- {
- return Call(functionInstance, thisObject, arguments, expression);
- }
-
- return callable.Call(thisObject, arguments);
+ return CallAsync(callable, thisObject, arguments).Preserve().GetAwaiter().GetResult();
}
///
@@ -1528,31 +1464,7 @@ internal JsValue Call(
JsValue[] arguments,
JintExpression? expression)
{
- // ensure logic is in sync between Call, Construct, engine.Invoke and JintCallExpression!
-
- var recursionDepth = CallStack.Push(function, expression, ExecutionContext);
-
- if (recursionDepth > Options.Constraints.MaxRecursionDepth)
- {
- // automatically pops the current element as it was never reached
- ExceptionHelper.ThrowRecursionDepthOverflowException(CallStack);
- }
-
- JsValue result;
- try
- {
- result = function.Call(thisObject, arguments);
- }
- finally
- {
- // if call stack was reset due to recursive call to engine or similar, we might not have it anymore
- if (CallStack.Count > 0)
- {
- CallStack.Pop();
- }
- }
-
- return result;
+ return CallAsync(function, thisObject, arguments, expression).Preserve().GetAwaiter().GetResult();
}
private ObjectInstance Construct(
diff --git a/Jint/Jint.csproj b/Jint/Jint.csproj
index b738a4afd..0470433f7 100644
--- a/Jint/Jint.csproj
+++ b/Jint/Jint.csproj
@@ -16,6 +16,7 @@
README.md
$(NoWarn);1591
+ $(NoWarn);NU1507
true
@@ -33,12 +34,14 @@
-
+
+
+
diff --git a/Jint/JsValueExtensions.cs b/Jint/JsValueExtensions.cs
index 62112eed3..38b1506a4 100644
--- a/Jint/JsValueExtensions.cs
+++ b/Jint/JsValueExtensions.cs
@@ -649,29 +649,48 @@ public static JsValue UnwrapIfPromise(this JsValue value)
{
if (value is JsPromise promise)
{
- var engine = promise.Engine;
- var completedEvent = promise.CompletedEvent;
- engine.RunAvailableContinuations();
- completedEvent.Wait();
- switch (promise.State)
- {
- case PromiseState.Pending:
- ExceptionHelper.ThrowInvalidOperationException("'UnwrapIfPromise' called before Promise was settled");
- return null;
- case PromiseState.Fulfilled:
- return promise.Value;
- case PromiseState.Rejected:
- ExceptionHelper.ThrowPromiseRejectedException(promise.Value);
- return null;
- default:
- ExceptionHelper.ThrowArgumentOutOfRangeException();
- return null;
- }
+ return UnwrapIfPromiseAsync(value).Preserve().GetAwaiter().GetResult();
}
return value;
}
+ ///
+ /// If the value is a Promise
+ /// 1. If "Fulfilled" returns the value it was fulfilled with
+ /// 2. If "Rejected" throws "PromiseRejectedException" with the rejection reason
+ /// 3. If "Pending" throws "InvalidOperationException". Should be called only in "Settled" state
+ /// Else
+ /// returns the value intact
+ ///
+ /// value to unwrap
+ /// inner value if Promise the value itself otherwise
+ public static async ValueTask UnwrapIfPromiseAsync(this JsValue value)
+ {
+ if (value is not JsPromise promise)
+ return value;
+
+ var engine = promise.Engine;
+ var completedEventAsync = promise.CompletedEventAsync;
+ engine.RunAvailableContinuations();
+ await completedEventAsync.Task.ConfigureAwait(false);
+
+ switch (promise.State)
+ {
+ case PromiseState.Pending:
+ ExceptionHelper.ThrowInvalidOperationException("'UnwrapIfPromise' called before Promise was settled");
+ return null;
+ case PromiseState.Fulfilled:
+ return promise.Value;
+ case PromiseState.Rejected:
+ ExceptionHelper.ThrowPromiseRejectedException(promise.Value);
+ return null;
+ default:
+ ExceptionHelper.ThrowArgumentOutOfRangeException();
+ return null;
+ }
+ }
+
[MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowWrongTypeException(JsValue value, string expectedType)
{
diff --git a/Jint/Native/Function/BindFunction.cs b/Jint/Native/Function/BindFunction.cs
index 6aea0a576..9874a1cb7 100644
--- a/Jint/Native/Function/BindFunction.cs
+++ b/Jint/Native/Function/BindFunction.cs
@@ -55,6 +55,11 @@ JsValue ICallable.Call(JsValue thisObject, JsValue[] arguments)
return value;
}
+ ValueTask ICallable.CallAsync(JsValue thisObject, JsValue[] arguments)
+ {
+ return new ValueTask(this.Call(thisObject, arguments));
+ }
+
ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
{
var target = BoundTargetFunction as IConstructor;
diff --git a/Jint/Native/Function/Function.Async.cs b/Jint/Native/Function/Function.Async.cs
new file mode 100644
index 000000000..199638f5a
--- /dev/null
+++ b/Jint/Native/Function/Function.Async.cs
@@ -0,0 +1,13 @@
+using System.Diagnostics;
+
+namespace Jint.Native.Function;
+
+[DebuggerDisplay("{ToString(),nq}")]
+#pragma warning disable MA0049
+public abstract partial class Function
+{
+ protected internal virtual ValueTask CallAsync(JsValue thisObject, JsValue[] arguments) => new ValueTask(Call(thisObject, arguments));
+
+ ValueTask ICallable.CallAsync(JsValue thisObject, JsValue[] arguments) => CallAsync(thisObject, arguments);
+
+}
diff --git a/Jint/Native/Function/ScriptFunction.cs b/Jint/Native/Function/ScriptFunction.cs
index 9c07c9891..22159fc67 100644
--- a/Jint/Native/Function/ScriptFunction.cs
+++ b/Jint/Native/Function/ScriptFunction.cs
@@ -57,6 +57,14 @@ internal ScriptFunction(
/// https://tc39.es/ecma262/#sec-ecmascript-function-objects-call-thisargument-argumentslist
///
protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
+ {
+ return CallAsync(thisObject, arguments).Preserve().GetAwaiter().GetResult();
+ }
+
+ ///
+ /// https://tc39.es/ecma262/#sec-ecmascript-function-objects-call-thisargument-argumentslist
+ ///
+ protected internal override async ValueTask CallAsync(JsValue thisObject, JsValue[] arguments)
{
var strict = _functionDefinition!.Strict || _thisMode == FunctionThisMode.Strict;
using (new StrictModeScope(strict, true))
@@ -75,7 +83,7 @@ protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments
// actual call
var context = _engine._activeEvaluationContext ?? new EvaluationContext(_engine);
- var result = _functionDefinition.EvaluateBody(context, this, arguments);
+ var result = await _functionDefinition.EvaluateBodyAsync(context, this, arguments).ConfigureAwait(false);
if (result.Type == CompletionType.Throw)
{
diff --git a/Jint/Native/ICallable.cs b/Jint/Native/ICallable.cs
index e69d11109..16691f2df 100644
--- a/Jint/Native/ICallable.cs
+++ b/Jint/Native/ICallable.cs
@@ -3,4 +3,7 @@ namespace Jint.Native;
internal interface ICallable
{
JsValue Call(JsValue thisObject, params JsValue[] arguments);
+ //Task CallAsync(JsValue thisObject, params JsValue[] arguments);
+
+ ValueTask CallAsync(JsValue thisObject, params JsValue[] arguments);
}
diff --git a/Jint/Native/JsPromise.cs b/Jint/Native/JsPromise.cs
index d6f1473cb..e7d130147 100644
--- a/Jint/Native/JsPromise.cs
+++ b/Jint/Native/JsPromise.cs
@@ -1,4 +1,3 @@
-using System.Threading;
using Jint.Native.Object;
using Jint.Native.Promise;
using Jint.Runtime;
@@ -13,7 +12,7 @@ internal sealed class JsPromise : ObjectInstance
// valid only in settled state (Fulfilled or Rejected)
internal JsValue Value { get; private set; } = null!;
- internal ManualResetEventSlim CompletedEvent { get; } = new();
+ internal TaskCompletionSource CompletedEventAsync { get; } = new(TaskCreationOptions.RunContinuationsAsynchronously);
internal List PromiseRejectReactions = new();
internal List PromiseFulfillReactions = new();
@@ -128,7 +127,7 @@ private JsValue RejectPromise(JsValue reason)
var reactions = PromiseRejectReactions;
PromiseRejectReactions = new List();
PromiseFulfillReactions.Clear();
- CompletedEvent.Set();
+ CompletedEventAsync.TrySetResult(false);
// Note that this part is skipped because there is no tracking yet
// 7. If promise.[[PromiseIsHandled]] is false, perform HostPromiseRejectionTracker(promise, "reject").
@@ -148,7 +147,7 @@ private JsValue FulfillPromise(JsValue result)
var reactions = PromiseFulfillReactions;
PromiseFulfillReactions = new List();
PromiseRejectReactions.Clear();
- CompletedEvent.Set();
+ CompletedEventAsync.TrySetResult(true);
return PromiseOperations.TriggerPromiseReactions(_engine, reactions, result);
}
diff --git a/Jint/Native/JsProxy.cs b/Jint/Native/JsProxy.cs
index 9446f31c8..c930ff30d 100644
--- a/Jint/Native/JsProxy.cs
+++ b/Jint/Native/JsProxy.cs
@@ -63,6 +63,11 @@ JsValue ICallable.Call(JsValue thisObject, JsValue[] arguments)
return callable.Call(thisObject, arguments);
}
+ ValueTask ICallable.CallAsync(JsValue thisObject, JsValue[] arguments)
+ {
+ return new ValueTask(this.Call(thisObject, arguments));
+ }
+
///
/// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
///
diff --git a/Jint/Native/Object/ObjectConstructor.cs b/Jint/Native/Object/ObjectConstructor.cs
index 92e5a2c53..e094ae751 100644
--- a/Jint/Native/Object/ObjectConstructor.cs
+++ b/Jint/Native/Object/ObjectConstructor.cs
@@ -1,6 +1,5 @@
#pragma warning disable CA1859 // Use concrete types when possible for improved performance -- most of constructor methods return JsValue
-using Jint.Collections;
using Jint.Native.Iterator;
using Jint.Runtime;
using Jint.Runtime.Descriptors;
@@ -139,7 +138,7 @@ protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments
return Construct(arguments);
}
- if(arguments[0].IsNullOrUndefined())
+ if (arguments[0].IsNullOrUndefined())
{
return Construct(arguments);
}
@@ -187,7 +186,7 @@ public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
internal ObjectInstance Construct(int propertyCount)
{
var obj = new JsObject(_engine);
- obj.SetProperties(propertyCount > 0 ? new PropertyDictionary(propertyCount, checkExistingKeys: true) : null);
+ obj.SetProperties(propertyCount > 0 ? new PropertyDictionary(propertyCount, checkExistingKeys: true) : null);
return obj;
}
@@ -565,5 +564,9 @@ public JsValue Call(JsValue thisObject, params JsValue[] arguments)
return Undefined;
}
+ ValueTask ICallable.CallAsync(JsValue thisObject, JsValue[] arguments)
+ {
+ return new ValueTask(this.Call(thisObject, arguments));
+ }
}
}
diff --git a/Jint/Runtime/Interop/NamespaceReference.cs b/Jint/Runtime/Interop/NamespaceReference.cs
index 96da128bc..0734254bd 100644
--- a/Jint/Runtime/Interop/NamespaceReference.cs
+++ b/Jint/Runtime/Interop/NamespaceReference.cs
@@ -73,6 +73,11 @@ JsValue ICallable.Call(JsValue thisObject, JsValue[] arguments)
}
}
+ ValueTask ICallable.CallAsync(JsValue thisObject, JsValue[] arguments)
+ {
+ return new ValueTask(this.Call(thisObject, arguments));
+ }
+
public override JsValue Get(JsValue property, JsValue receiver)
{
var newPath = string.IsNullOrEmpty(_path)
diff --git a/Jint/Runtime/Interpreter/Expressions/ExpressionCache.cs b/Jint/Runtime/Interpreter/Expressions/ExpressionCache.cs
index 6b854df18..4aca74050 100644
--- a/Jint/Runtime/Interpreter/Expressions/ExpressionCache.cs
+++ b/Jint/Runtime/Interpreter/Expressions/ExpressionCache.cs
@@ -59,33 +59,45 @@ internal void Initialize(EvaluationContext context, ReadOnlySpan arg
public JsValue[] ArgumentListEvaluation(EvaluationContext context, out bool rented)
{
- rented = false;
+ var (jsValueArray, isRented) = ArgumentListEvaluationAsync(context).Preserve().GetAwaiter().GetResult();
+ rented = isRented;
+ return jsValueArray;
+ }
+
+ public async ValueTask<(JsValue[], bool rented)> ArgumentListEvaluationAsync(EvaluationContext context)
+ {
+ var rented = false;
if (_fullyCached)
{
- return Unsafe.As(_expressions);
+ return (Unsafe.As(_expressions), rented);
}
if (HasSpreads)
{
var args = new List(_expressions.Length);
- BuildArgumentsWithSpreads(context, args);
- return args.ToArray();
+ await BuildArgumentsWithSpreadsAsync(context, args).ConfigureAwait(false);
+ return (args.ToArray(), rented);
}
var arguments = context.Engine._jsValueArrayPool.RentArray(_expressions.Length);
rented = true;
- BuildArguments(context, arguments);
+ await BuildArgumentsAsync(context, arguments).ConfigureAwait(false);
- return arguments;
+ return (arguments, rented);
}
internal void BuildArguments(EvaluationContext context, JsValue[] targetArray)
+ {
+ BuildArgumentsAsync(context, targetArray).Preserve().GetAwaiter().GetResult();
+ }
+
+ internal async ValueTask BuildArgumentsAsync(EvaluationContext context, JsValue[] targetArray)
{
var expressions = _expressions;
for (uint i = 0; i < (uint) expressions.Length; i++)
{
- targetArray[i] = GetValue(context, expressions[i])!;
+ targetArray[i] = await GetValueAsync(context, expressions[i])!.ConfigureAwait(false);
}
}
@@ -96,11 +108,14 @@ public JsValue GetValue(EvaluationContext context, int index)
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static JsValue GetValue(EvaluationContext context, object? value)
+ private static JsValue GetValue(EvaluationContext context, object? value) => GetValueAsync(context, value).Preserve().GetAwaiter().GetResult();
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static async ValueTask GetValueAsync(EvaluationContext context, object? value)
{
return value switch
{
- JintExpression expression => expression.GetValue(context).Clone(),
+ JintExpression expression => (await expression.GetValueAsync(context).ConfigureAwait(false)).Clone(),
_ => (JsValue) value!,
};
}
@@ -140,7 +155,9 @@ internal JsValue[] DefaultSuperCallArgumentListEvaluation(EvaluationContext cont
return args.ToArray();
}
- internal void BuildArgumentsWithSpreads(EvaluationContext context, List target)
+ internal void BuildArgumentsWithSpreads(EvaluationContext context, List target) => BuildArgumentsWithSpreadsAsync(context, target).Preserve().GetAwaiter().GetResult();
+
+ internal async ValueTask BuildArgumentsWithSpreadsAsync(EvaluationContext context, List target)
{
foreach (var expression in _expressions)
{
@@ -165,7 +182,7 @@ internal void BuildArgumentsWithSpreads(EvaluationContext context, List
}
else
{
- target.Add(GetValue(context, expression)!);
+ target.Add(await GetValueAsync(context, expression)!.ConfigureAwait(false));
}
}
}
diff --git a/Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs b/Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs
index e85f6ad3e..0e5d83417 100644
--- a/Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs
+++ b/Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs
@@ -424,6 +424,12 @@ private JsValue SetValue(EvaluationContext context)
}
internal static object? AssignToIdentifier(
+ EvaluationContext context,
+ JintIdentifierExpression left,
+ JintExpression right,
+ bool hasEvalOrArguments) => AssignToIdentifierAsync(context, left, right, hasEvalOrArguments).Preserve().GetAwaiter().GetResult();
+
+ internal static async ValueTask