场景
想找一个支持windows/linux/armlinux的脚本引擎。
Jint总结
- 编译为单文件模式并裁剪后,Windows/Linux可执行文件仅增加4MB左右;
- Linux/Windows/ARM均测试通过。
- 性能明显比ClearScript、CScript差,但优点是打包后体积小;
- Windows单次命令执行0.0005ms左右,ArmLinux单词执行大约0.02ms左右;
- 支持内联JS lambda函数;
博主认为基本满足跨平台嵌入式运行场景;
Jint功能测试代码
// See https://aka.ms/new-console-template for more information
using Jint;
Console.WriteLine("Hello, World!");
var engine0 = new Engine()
.Execute(@"
var x = 1 + 2;
var add1 = (x1,x2)=>{return x1+x2;}
var y = add1(10, 3);
"); //
Console.WriteLine(engine0.GetValue("x").ToObject());
Console.WriteLine(engine0.GetValue("y").ToObject());
var engine1 = new Engine()
.Execute("var x = 1 + 2;"); // 输出: 3
Console.WriteLine(engine1.GetValue("x").ToObject());
var engine2 = new Engine()
.Execute("function add(a, b) { return a + b; }");
var result2 = engine2.Invoke("add", 5, 3).ToObject(); // 8
Console.WriteLine(result2);
// 创建 Jint 引擎
var engine = new Engine()
.SetValue("log", new Action<object>(Console.WriteLine)); // 添加 console.log 功能
// 定义一个包含 if/else、switch 和数学计算的 JavaScript 代码
string jsCode = @"
function calculate(x, y, operation) {
let result;
// if/else 示例
if (operation === 'add') {
result = x + y;
} else if (operation === 'subtract') {
result = x - y;
} else if (operation === 'multiply') {
result = x * y;
} else if (operation === 'divide') {
result = x / y;
} else {
result = 'Unknown operation';
}
// switch 示例
let message;
switch (operation) {
case 'add':
message = 'Addition result: ' + result;
break;
case 'subtract':
message = 'Subtraction result: ' + result;
break;
case 'multiply':
message = 'Multiplication result: ' + result;
break;
case 'divide':
message = 'Division result: ' + result;
break;
default:
message = 'Unknown operation: ' + operation;
}
// 数学计算示例
let powerResult = Math.pow(x, y);
let sqrtResult = Math.sqrt(x);
let randomValue = Math.random();
return {
basicResult: result,
message: message,
powerResult: powerResult,
sqrtResult: sqrtResult,
randomValue: randomValue
};
}
// 测试计算函数
let test1 = calculate(10, 5, 'add');
log(test1.message);
log('10^5 = ' + test1.powerResult);
let test2 = calculate(20, 4, 'divide');
log(test2.message);
log('√20 ≈ ' + test2.sqrtResult.toFixed(2));
let test3 = calculate(7, 3, 'unknown');
log(test3.message);
log('Random value: ' + test3.randomValue);
";
try
{
// 执行 JavaScript 代码
engine.Execute(jsCode);
}
catch (Exception ex)
{
Console.WriteLine($"执行 JavaScript 时出错: {ex.Message}");
}
Console.ReadLine();
性能测试代码
// See https://aka.ms/new-console-template for more information
using System.Diagnostics;
using Jint;
Console.WriteLine("Hello, World!");
// 创建 Jint 引擎实例
Engine engine = new Engine();
// 预编译多个代码块
var script1 = Engine.PrepareScript("function add(a, b) { return a + b; }");
var script2 = Engine.PrepareScript("function multiply(a, b) { return a * b; }");
var script3 = Engine.PrepareScript("function factorial(n) { return n <= 1 ? 1 : n * factorial(n - 1); }");
// 执行预编译的代码块
engine.Execute(script1);
engine.Execute(script2);
engine.Execute(script3);
// 测试预编译函数的执行性能
TestPerformance(engine, "add(5, 10)", "加法函数", 1000000);
TestPerformance(engine, "multiply(5, 10)", "乘法函数", 1000000);
TestPerformance(engine, "factorial(10)", "阶乘函数", 100000);
Console.ReadLine();
static void TestPerformance(Engine engine, string expression, string testName, int iterations)
{
// 预编译测试表达式
var compiledExpr = Engine.PrepareScript(expression);
// 修复错误:直接调用 Evaluate 方法获取结果
Console.WriteLine($"{expression}:{engine.Evaluate(compiledExpr).ToObject()}" );
var stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < iterations; i++)
{
engine.Execute(compiledExpr);
}
stopwatch.Stop();
Console.WriteLine($"{testName} 执行 {iterations} 次耗时: {stopwatch.ElapsedMilliseconds} ms");
Console.WriteLine($"平均每次执行时间: {(double)stopwatch.ElapsedMilliseconds / iterations} ms");
}
Windows执行结果:

Linux-Armx64 800MHZ 嵌入式设备执行结果:

Jint安全使用注意事项
Jint 是一个 .NET 的 JavaScript 解释器,在使用时需要注意以下安全性问题:
1. 脚本执行限制
- 设置执行超时:防止无限循环或长时间运行的脚本
var engine = new Engine(options => { options.TimeoutInterval(TimeSpan.FromSeconds(5)); // 5秒超时 });
- 限制内存使用:防止内存耗尽攻击
options.MaxMemory(10_000_000); // 限制最大内存为10MB
2. 沙箱环境隔离
- 限制访问.NET类型:默认情况下Jint允许访问所有.NET类型
options.AllowClr(false); // 禁用CLR访问 // 或限制特定程序集 options.AllowClr(typeof(Console).Assembly); // 只允许访问System.Console
- 自定义类型解析器:精确控制可访问的类型
options.SetTypeResolver(new CustomTypeResolver());
3. 输入验证
- 验证脚本内容:检查是否包含危险操作
if (script.Contains("System.IO.File")) { throw new SecurityException("禁止的文件操作"); }
4. 权限控制
- 限制危险API:如文件系统、网络访问等
// 覆盖默认函数实现 engine.SetValue("fetch", new Func<string, object>(url => { throw new JavaScriptException("网络访问被禁用"); }));
5. 错误处理
- 捕获并处理异常:防止敏感信息泄露
try { engine.Execute(script); } catch (JavaScriptException ex) { // 记录但不暴露内部细节 logger.Error($"脚本执行错误: {ex.Message}"); throw new ApplicationException("脚本执行出错"); }
6. 其他注意事项
- 避免将用户输入直接作为脚本执行
- 定期更新Jint到最新版本以修复安全漏洞
- 考虑使用更严格的模式(如严格模式)
options.Strict(true);