Closed imsmart-tech closed 5 years ago
Hello, Paul!
A good idea, you should first suggest it to developers of the Microsoft ClearScript.V8.
Done. https://github.com/Microsoft/ClearScript/issues/7 Let's see how it will be handled. :-|
Check their answer in the link above. Can I call V8 directly or it needs to wrapped? I feel it should be included in the wrapper anyway. Let me know...
Can I call V8 directly or it needs to wrapped?
You can use the V8ScriptEngine
class directly, but you will have to abandon the JavaScript Engine Switcher (at least you have to uninstall the JavaScriptEngineSwitcher.V8-*
packages) and install the ClearScript.V8 package.
I feel it should be included in the wrapper anyway.
Interrupt
method will be included in the IJsEngine
interface, but it will take time, because it require changing the public API. Wait for release of version 3.0.
Hello, Paul!
I feel it should be included in the wrapper anyway. Let me know...
This feature was implemented in version 3.0.0 Alpha 1. While this feature is supported by only two modules: JavaScriptEngineSwitcher.V8 and JavaScriptEngineSwitcher.ChakraCore.
My version of the example with timeout looks like this:
Contents of the JsEngineExtensions.cs
file:
using System;
using System.Threading;
using JavaScriptEngineSwitcher.Core;
namespace TestScriptTimeout
{
public static class JsEngineExtensions
{
public static object TimedEvaluate(this IJsEngine engine, TimeSpan timeout, string code)
{
if (engine.SupportsScriptInterruption)
{
using (var timer = new Timer(state => engine.Interrupt()))
{
try
{
timer.Change(timeout, TimeSpan.FromMilliseconds(Timeout.Infinite));
return engine.Evaluate(code);
}
catch (JsScriptInterruptedException exception)
{
throw new TimeoutException("Script execution timed out", exception);
}
}
}
else
{
throw new NotSupportedException(string.Format("JavaScript engine with name '{0}' does " +
"not support interruption of the script execution.", engine.Name));
}
}
}
}
Contents of the Program.cs
file:
using System;
using JavaScriptEngineSwitcher.ChakraCore;
using JavaScriptEngineSwitcher.Core;
using JavaScriptEngineSwitcher.Msie;
using JavaScriptEngineSwitcher.V8;
namespace TestScriptTimeout
{
class Program
{
static Program()
{
JsEngineSwitcher engineSwitcher = JsEngineSwitcher.Instance;
engineSwitcher.EngineFactories
.AddChakraCore()
.AddMsie(options =>
{
options.EngineMode = JsEngineMode.ChakraIeJsRt;
})
.AddV8()
;
engineSwitcher.DefaultEngineName = V8JsEngine.EngineName;
}
static void Main(string[] args)
{
using (var engine = JsEngineSwitcher.Instance.CreateDefaultEngine())
{
try
{
engine.TimedEvaluate(TimeSpan.FromSeconds(5), "while (true) {}");
}
catch (TimeoutException)
{
Console.WriteLine("Timed out!");
}
catch (NotSupportedException e)
{
Console.WriteLine(e.Message);
}
}
}
}
}
In version 3.0.0 Alpha 2, this feature is now supported by third module - JavaScriptEngineSwitcher.Vroom.
In version 3.0.0 Alpha 3, this feature is now supported by fourth module - JavaScriptEngineSwitcher.Msie.
Hello, Paul!
In version 3.0.0 the ability to interrupt execution of the script was added to the following modules: JavaScriptEngineSwitcher.ChakraCore, JavaScriptEngineSwitcher.Msie, JavaScriptEngineSwitcher.V8 and JavaScriptEngineSwitcher.Vroom.
With all the changes, my version of the example with timeout looks like this:
Contents of the JsEngineExtensions.cs
file:
using System;
using System.Threading;
using JavaScriptEngineSwitcher.Core;
namespace TestScriptTimeout
{
public static class JsEngineExtensions
{
public static object TimedEvaluate(this IJsEngine engine, TimeSpan timeout,
string expression)
{
if (engine.SupportsScriptInterruption)
{
using (var timer = new Timer(state => engine.Interrupt()))
{
try
{
timer.Change(timeout, TimeSpan.FromMilliseconds(Timeout.Infinite));
return engine.Evaluate(expression);
}
catch (JsInterruptedException e)
{
throw new TimeoutException("Script execution timed out", e);
}
}
}
else
{
throw new NotSupportedException(string.Format("JavaScript engine with name " +
"'{0}' does not support interruption of the script execution.", engine.Name));
}
}
}
}
Contents of the Program.cs
file:
using System;
using JavaScriptEngineSwitcher.ChakraCore;
using JavaScriptEngineSwitcher.Core;
using JavaScriptEngineSwitcher.Msie;
using JavaScriptEngineSwitcher.V8;
using JavaScriptEngineSwitcher.Vroom;
namespace TestScriptTimeout
{
class Program
{
static Program()
{
IJsEngineSwitcher engineSwitcher = JsEngineSwitcher.Current;
engineSwitcher.EngineFactories
.AddChakraCore()
.AddMsie(options =>
{
options.EngineMode = JsEngineMode.ChakraIeJsRt;
})
.AddV8()
.AddVroom()
;
engineSwitcher.DefaultEngineName = ChakraCoreJsEngine.EngineName;
}
static void Main(string[] args)
{
const string expression = @"function sleep(millisecondsTimeout) {
var totalMilliseconds = new Date().getTime() + millisecondsTimeout;
while (new Date() < totalMilliseconds)
{ }
}
sleep(600 * 1000);";
using (IJsEngine engine = JsEngineSwitcher.Current.CreateDefaultEngine())
{
try
{
object result = engine.TimedEvaluate(TimeSpan.FromSeconds(5), expression);
}
catch (TimeoutException)
{
Console.WriteLine("Timed out!");
}
catch (NotSupportedException e)
{
Console.WriteLine(e.Message);
}
}
}
}
}
Hi,
Is there a way to get a script timeout with V8 like it seems to be possible with Jint? I am trying to code the timeout in C# and that is not so obvious so I thought that must be easier to implement the timeout like it's done for Jint.
Paul