Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Jint.Repl/Jint.Repl.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
<TargetFramework>net10.0</TargetFramework>
<OutputType>Exe</OutputType>
<IsPackable>false</IsPackable>
<AssemblyOriginatorKeyFile>..\Jint\Jint.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<PublishAot>true</PublishAot>
</PropertyGroup>
<ItemGroup>
Expand Down
99 changes: 89 additions & 10 deletions Jint.Repl/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Jint.Native;
using Jint.Native.Json;
using Jint.Runtime;
using Jint.Runtime.Modules;

// ReSharper disable LocalizableElement

Expand All @@ -14,6 +15,7 @@
// Parse command line arguments
string? inputFile = null;
int? timeoutSeconds = null;
bool runAsModule = false;

for (int i = 0; i < args.Length; i++)
{
Expand All @@ -23,6 +25,10 @@
if (i + 1 < args.Length)
{
inputFile = args[++i];
if (inputFile.EndsWith(".mjs", StringComparison.OrdinalIgnoreCase))
{
runAsModule = true;
}
}
else
{
Expand All @@ -41,6 +47,9 @@
return 1;
}
break;
case "-m" or "--module":
runAsModule = true;
break;
case "-h" or "--help":
PrintHelp();
return 0;
Expand All @@ -49,6 +58,10 @@
if (!args[i].StartsWith("-") && inputFile == null)
{
inputFile = args[i];
if (inputFile.EndsWith(".mjs", StringComparison.OrdinalIgnoreCase))
{
runAsModule = true;
}
}
break;
}
Expand All @@ -61,6 +74,13 @@
{
cfg.TimeoutInterval(TimeSpan.FromSeconds(timeoutSeconds.Value));
}
if (runAsModule)
{
var basePath = inputFile != null
? Path.GetDirectoryName(Path.GetFullPath(inputFile))!
: Directory.GetCurrentDirectory();
cfg.EnableModules(basePath, restrictToBasePath: false);
}
});

engine
Expand All @@ -70,6 +90,11 @@
path => engine.Evaluate(File.ReadAllText(path)))
);

var test262 = Test262Object.Install(engine);

var agentManager = new Test262AgentManager();
agentManager.InstallAgent(engine, test262);

// Execute file if provided via -f
if (!string.IsNullOrEmpty(inputFile))
{
Expand All @@ -81,20 +106,33 @@

try
{
var script = File.ReadAllText(inputFile);
var result = engine.Evaluate(script, inputFile);
if (!result.IsUndefined())
if (runAsModule)
{
var absolutePath = Path.GetFullPath(inputFile);
engine.Modules.Import(new Uri(absolutePath).AbsoluteUri);
}
else
{
Console.WriteLine(result);
var script = File.ReadAllText(inputFile);
var result = engine.Evaluate(script, inputFile);
if (!result.IsUndefined())
{
Console.WriteLine(result);
}
}
return 0;
}
catch (JavaScriptException je)
{
Console.Error.WriteLine($"Error: {je.Message}");
Console.Error.WriteLine(FormatJavaScriptException(je));
Console.Error.WriteLine(je.JavaScriptStackTrace);
return 1;
}
catch (ModuleResolutionException mre)
{
Console.Error.WriteLine($"Error: {mre.Message}");
return 1;
}
catch (TimeoutException)
{
Console.Error.WriteLine("Error: Script execution timed out");
Expand All @@ -113,19 +151,32 @@
try
{
var script = Console.In.ReadToEnd();
var result = engine.Evaluate(script, "stdin");
if (!result.IsUndefined())
if (runAsModule)
{
Console.WriteLine(result);
engine.Modules.Add("<stdin>", script);
engine.Modules.Import("<stdin>");
}
else
{
var result = engine.Evaluate(script, "stdin");
if (!result.IsUndefined())
{
Console.WriteLine(result);
}
}
return 0;
}
catch (JavaScriptException je)
{
Console.Error.WriteLine($"Error: {je.Message}");
Console.Error.WriteLine(FormatJavaScriptException(je));
Console.Error.WriteLine(je.JavaScriptStackTrace);
return 1;
}
catch (ModuleResolutionException mre)
{
Console.Error.WriteLine($"Error: {mre.Message}");
return 1;
}
catch (TimeoutException)
{
Console.Error.WriteLine("Error: Script execution timed out");
Expand Down Expand Up @@ -185,7 +236,8 @@
catch (JavaScriptException je)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(je.ToString());
Console.WriteLine(FormatJavaScriptException(je));
Console.Error.WriteLine(je.JavaScriptStackTrace);
}
catch (TimeoutException)
{
Expand All @@ -199,6 +251,31 @@
}
}

static string FormatJavaScriptException(JavaScriptException je)
{
if (!je.Error.IsObject())
{
return $"Uncaught exception: {je.Error}";
}

var obj = je.Error.AsObject();
var name = obj.Get(new JsString("name"), je.Error);
if (name.IsUndefined())
{
var ctor = obj.Get(new JsString("constructor"), je.Error);
if (ctor.IsObject())
{
name = ctor.AsObject().Get(new JsString("name"), ctor);
}
}

var errorName = name.IsUndefined() ? "Error" : name.ToString();
var message = obj.Get(new JsString("message"), je.Error);
return message.IsUndefined() || message.ToString().Length == 0
? $"Uncaught exception: {errorName}"
: $"Uncaught exception: {errorName}: {message}";
}

static void PrintHelp()
{
Console.WriteLine("Jint REPL - JavaScript interpreter");
Expand All @@ -207,12 +284,14 @@ static void PrintHelp()
Console.WriteLine();
Console.WriteLine("Options:");
Console.WriteLine(" -f, --file <path> Execute JavaScript file");
Console.WriteLine(" -m, --module Run script as ES6 module");
Console.WriteLine(" -t, --timeout <secs> Set execution timeout in seconds");
Console.WriteLine(" -h, --help Show this help message");
Console.WriteLine();
Console.WriteLine("Examples:");
Console.WriteLine(" jint Start interactive REPL");
Console.WriteLine(" jint script.js Execute script.js");
Console.WriteLine(" jint -m module.js Execute module.js as ES6 module");
Console.WriteLine(" jint -f script.js -t 10 Execute with 10 second timeout");
Console.WriteLine(" echo \"1+1\" | jint Execute from stdin");
Console.WriteLine(" echo \"1+1\" | jint -t 5 Execute from stdin with timeout");
Expand Down
45 changes: 1 addition & 44 deletions Jint.Tests.Test262/Test262Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,54 +60,11 @@ private static Engine BuildTestExecutor(Test262File file, Test262AgentManager? a
return JsValue.Undefined;
}));

var o = engine.Realm.Intrinsics.Object.Construct(Arguments.Empty);
o.FastSetProperty("evalScript", new PropertyDescriptor(new ClrFunction(engine, "evalScript",
(_, args) =>
{
if (args.Length > 1)
{
throw new Exception("only script parsing supported");
}

var script = Engine.PrepareScript(args.At(0).AsString(), options: new ScriptPreparationOptions
{
ParsingOptions = ScriptParsingOptions.Default with { Tolerant = false },
});

return engine.Evaluate(script);
}), true, true, true));

o.FastSetProperty("createRealm", new PropertyDescriptor(new ClrFunction(engine, "createRealm",
(_, args) =>
{
var realm = engine._host.CreateRealm();
realm.GlobalObject.Set("global", realm.GlobalObject);
return realm.GlobalObject;
}), true, true, true));

o.FastSetProperty("detachArrayBuffer", new PropertyDescriptor(new ClrFunction(engine, "detachArrayBuffer",
(_, args) =>
{
var buffer = (JsArrayBuffer) args.At(0);
buffer.DetachArrayBuffer();
return JsValue.Undefined;
}), true, true, true));

o.FastSetProperty("gc", new PropertyDescriptor(new ClrFunction(engine, "gc",
(_, _) =>
{
GC.Collect();
GC.WaitForPendingFinalizers();
return JsValue.Undefined;
}), true, true, true));

o.FastSetProperty("IsHTMLDDA", new PropertyDescriptor(new IsHTMLDDA(engine), true, true, true));
var o = Test262Object.Install(engine);

// Install agent support if needed
agentManager?.InstallAgent(engine, o);

engine.SetValue("$262", o);

foreach (var include in file.Includes)
{
engine.Execute(State.Sources[include]);
Expand Down
1 change: 1 addition & 0 deletions Jint/AssemblyInfoExtras.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Jint.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100bf2553c9f214cb21f1f64ed62cadad8fe4f2fa11322a5dfa1d650743145c6085aba05b145b29867af656e0bb9bfd32f5d0deb1668263a38233e7e8e5bad1a3c6edd3f2ec6c512668b4aa797283101444628650949641b4f7cb16707efba542bb754afe87ce956f3a5d43f450d14364eb9571cbf213d1061852fb9dd47a6c05c4")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Jint.Tests.Test262, PublicKey=0024000004800000940000000602000000240000525341310004000001000100bf2553c9f214cb21f1f64ed62cadad8fe4f2fa11322a5dfa1d650743145c6085aba05b145b29867af656e0bb9bfd32f5d0deb1668263a38233e7e8e5bad1a3c6edd3f2ec6c512668b4aa797283101444628650949641b4f7cb16707efba542bb754afe87ce956f3a5d43f450d14364eb9571cbf213d1061852fb9dd47a6c05c4")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Jint.Benchmark, PublicKey=0024000004800000940000000602000000240000525341310004000001000100bf2553c9f214cb21f1f64ed62cadad8fe4f2fa11322a5dfa1d650743145c6085aba05b145b29867af656e0bb9bfd32f5d0deb1668263a38233e7e8e5bad1a3c6edd3f2ec6c512668b4aa797283101444628650949641b4f7cb16707efba542bb754afe87ce956f3a5d43f450d14364eb9571cbf213d1061852fb9dd47a6c05c4")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Jint.Repl, PublicKey=0024000004800000940000000602000000240000525341310004000001000100bf2553c9f214cb21f1f64ed62cadad8fe4f2fa11322a5dfa1d650743145c6085aba05b145b29867af656e0bb9bfd32f5d0deb1668263a38233e7e8e5bad1a3c6edd3f2ec6c512668b4aa797283101444628650949641b4f7cb16707efba542bb754afe87ce956f3a5d43f450d14364eb9571cbf213d1061852fb9dd47a6c05c4")]

[module: System.Runtime.CompilerServices.SkipLocalsInit]
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

using System.Collections.Concurrent;
using System.Diagnostics;
using System.Threading;
using Jint.Native;
using Jint.Native.Object;
using Jint.Runtime;
using Jint.Runtime.Descriptors;
using Jint.Runtime.Interop;

namespace Jint.Tests.Test262;
namespace Jint;

/// <summary>
/// Implements the $262.agent API for Test262 multi-agent tests.
Expand All @@ -21,7 +22,7 @@ internal sealed class Test262AgentManager : IDisposable
private readonly Stopwatch _stopwatch = Stopwatch.StartNew();
private byte[]? _broadcastBufferData;
private int _broadcastBufferLength;
private readonly object _broadcastLock = new();
private readonly Lock _broadcastLock = new();
private readonly ManualResetEventSlim _broadcastEvent = new(false);
private int _broadcastVersion;

Expand Down Expand Up @@ -67,7 +68,7 @@ public void InstallAgent(Engine engine, ObjectInstance container)
agent.FastSetProperty("sleep", new PropertyDescriptor(new ClrFunction(engine, "sleep",
(_, args) =>
{
var ms = (int)TypeConverter.ToNumber(args.At(0));
var ms = (int) TypeConverter.ToNumber(args.At(0));
Thread.Sleep(ms);
return JsValue.Undefined;
}), true, true, true));
Expand Down Expand Up @@ -120,7 +121,7 @@ public void Dispose()
List<AgentWorker> workers;
lock (_workers)
{
workers = [.._workers];
workers = [.. _workers];
}

foreach (var worker in workers)
Expand Down Expand Up @@ -194,7 +195,7 @@ private void Run()
agentObj.FastSetProperty("sleep", new PropertyDescriptor(new ClrFunction(engine, "sleep",
(_, args) =>
{
var ms = (int)TypeConverter.ToNumber(args.At(0));
var ms = (int) TypeConverter.ToNumber(args.At(0));
Thread.Sleep(ms);
return JsValue.Undefined;
}), true, true, true));
Expand Down Expand Up @@ -274,8 +275,8 @@ private static JsSharedArrayBuffer CreateSharedArrayBuffer(Engine engine, byte[]
// Create a new SharedArrayBuffer that shares the same underlying byte array
// Get prototype via the constructor's "prototype" property
var constructor = engine.Realm.Intrinsics.SharedArrayBuffer;
var prototype = (ObjectInstance)constructor.Get(CommonProperties.Prototype);
var sab = new JsSharedArrayBuffer(engine, data, null, (uint)byteLength)
var prototype = (ObjectInstance) constructor.Get(CommonProperties.Prototype);
var sab = new JsSharedArrayBuffer(engine, data, null, (uint) byteLength)
{
_prototype = prototype
};
Expand Down
Loading
Loading