當前位置: 華文頭條 > 推薦

.NET 全面擁抱 Javascript,Jint 火了

2024-02-05推薦

大家好,很高興又見面了,我是" 高級前端‬進階 ‬",由我帶著大家一起關註前端前沿、深入前端底層技術,大家一起進步,也歡迎大家關註、點贊、收藏、轉發!

1.什麽是 Jint

Jint 是 .NET 的 Javascript 直譯器,可以在任何現代 .NET 平台上執行,支持 .NET Standard 2.0 和 .NET 4.6.2 目標(及更高版本)。在效能方面,Jint 也是非常優秀:

  • 由於 Jint 既不生成任何 .NET 字節碼也不使用 DLR,因此可以非常快地執行相對較小的指令碼
  • 如果重復執行相同的指令碼,則應該緩存 Esprima 生成的指令碼或模組例項並將其提供給 Jint 而不是內容字串
  • 更適合在嚴格模式下執行引擎,可以提高效能
  • Jint 可以適應以下典型場景:

  • 在安全的沙盒環境中在 .NET 應用程式內執行 JavaScript
  • 將本機 .NET 物件和函式公開給 JavaScript 程式碼,以 JSON 形式獲取資料庫查詢結果、呼叫 .NET 方法等
  • 支持 .NET 應用程式中的指令碼編寫,允許使用者使用 JavaScript 自訂應用程式(如 Unity 遊戲)
  • Jint 的一些使用者包括 RavenDB、EventStore、OrchardCore、ELSA Workflows、docfx、JavaScript Engine Switcher 等等。

    目前 Jint 在 Github 透過 BSD-2-Clause 協定開源,有超過 3.7k 的 star,1k 的 fork、1.7k 的計畫依賴量,是一個值得關註的開源計畫。

    2.如何使用 Jint

    基礎範例

    下面範例定義了一個名為 log 的新值,該值指向 Console.WriteLine,然後執行一個呼叫 log('Hello World!') 的指令碼。

    var engine = new Engine() .SetValue("log", new Action<object>(Console.WriteLine));engine.Execute(@" function hello() { log('Hello World'); }; hello();");

    變量 x 設定為 3,並且 x * x 在 JavaScript 中計算。結果直接返回到 .NET,在本例中為雙精度值 9。

    var square = new Engine() .SetValue("x", 3) // define a new variable .Evaluate("x * x") // evaluate a statement .ToObject(); // converts the value to .NET

    還可以直接傳遞 POCO 或匿名物件並從 JavaScript 使用。例如,在此範例中,一個新的 Person 例項是透過 JavaScript 操作的。

    var p = new Person { Name = "Mickey Mouse"};var engine = new Engine() .SetValue("p", p) .Execute("p.Name ='Minnie'");Assert.AreEqual("Minnie", p.Name);

    可以呼叫 JavaScript 函式參照:

    var add = new Engine() .Execute("function add(a, b) { return a + b; }") .GetValue("add");add.Invoke(1, 2); // -> 3

    或者透過函式名稱呼叫:

    var engine = new Engine() .Execute("function add(a, b) { return a + b; }");engine.Invoke("add", 1, 2); // -> 3

    存取 .NET 程式集和類

    開發者可以透過如下配置引擎例項來允許引擎存取任何 .NET 類:

    var engine = new Engine(cfg => cfg.AllowClr());

    然後就可以將系統名稱空間作為全域值進行存取。以下是它在命令列實用程式上下文中的使用方式:

    jint> var file = new System.IO.StreamWriter('log.txt');jint> file.WriteLine('Hello World !');jint> file.Dispose();

    國際化

    如果不想使用電腦的預設值,則可以在使用區域設定 JavaScript 方法時強制引擎應使用的時區或文化,下面範例強制將時區設定為太平洋標準時間。

    var PST = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");var engine = new Engine(cfg => cfg.LocalTimeZone(PST));engine.Execute("new Date().toString()"); // Wed Dec 31 1969 16:00:00 GMT-08:00

    下面範例使用法語作為預設區域性:

    var FR = CultureInfo.GetCultureInfo("fr-FR");var engine = new Engine(cfg => cfg.Culture(FR));engine.Execute("new Number(1.23).toString()"); // 1.23engine.Execute("new Number(1.23).toLocaleString()"); // 1,23

    使用模組

    可以使用模組從多個指令碼檔匯入和匯出變量:

    var engine = new Engine(options =>{ options.EnableModules(@"C:\Scripts");})var ns = engine.Modules.Import("./my-module.js");var value = ns.Get("value").AsString();

    預設情況下,模組解析演算法將僅限於 EnableModules 中指定的基本路徑,並且沒有包支持。但是,開發者可以透過兩種方式提供自己的包。 使用 JavaScript 原始碼定義模組:

    engine.Modules.Add("user", "export const name ='John';");var ns = engine.Modules.Import("user");var name = ns.Get("name").AsString();

    或者使用模組構建器定義模組,其允許從 .NET 匯出 CLR 類和值:

    // Create the module 'lib' with the class My class and the variable versionengine.Modules.Add("lib", builder => builder .ExportType<My class>() .ExportValue("version", 15));// Create a user-defined module and do something with 'lib'engine.Modules.Add("custom", @" import {My class, version} from 'lib'; const x = new My class(); export const result as x.doSomething();");// Import the user-defined module; this will execute the import chainvar ns = engine.Modules.Import("custom");// The result contains "live" bindings to the modulevar id = ns.Get("result").AsInteger();

    3.Jint 的安全性

    以下功能為開發者提供了一個安全的沙盒環境來執行使用者指令碼:

  • 定義記憶體限制,以防止分配耗盡記憶體。
  • 啟用 / 禁用 BCL 的使用以防止指令碼呼叫 .NET 程式碼。
  • 限制語句數量以防止無限迴圈。
  • 限制呼叫深度以防止深度遞迴呼叫。
  • 定義超時,以防止指令碼花費太長時間才能完成。
  • 4.本文總結

    本文主要和大家介紹 Jint ,其是 .NET 的 Javascript 直譯器,可以在任何現代 .NET 平台上執行,支持 .NET Standard 2.0 和 .NET 4.6.2 目標(及更高版本)。因為篇幅問題,關於 Jint 主題只是做了一個簡短的介紹,但是文末的參考資料提供了大量優秀文件以供學習,如果有興趣可以自行閱讀。如果大家有什麽疑問歡迎在評論區留言。

    參考資料

    https://github.com/sebastienros/jint

    https://blog.devgenius.io/a-javascript-rules-engine-in-net-6-fb092cdc44c

    https://github.com/topics/jint