有没有任何基于.NET CLR/DLR的ECMAScript实现?

41

有没有人知道针对.NET CLR/DLR的ECMAScript的真正实现(即没有虚构)?理想情况下,像Java中的Rhino一样。在.NET Framework/Mono Framework上运行的Rhino的可靠版本将是完美的选择。

我只看到过少数几个项目被提及,但从未见过任何结果,也没有看到我能够在其上运行脚本的实际内容。以下是我已知的内容:

  • MSScriptControl ActiveX Control: 据我所知,这是微软最后一个ECMAScript兼容的实现(运行JScript 5.7)。我已经与MSScriptControl集成,但不认为COM互操作是这个问题的答案。对于x64来说,这是致命的选项。

  • JScript.NET: 我不认为JScript.NET可以成功解析我的任何真实脚本。它似乎处理闭包时存在问题。

  • Managed JScript: 听起来像是我想要的,但似乎已经停滞不前。这是DLR的一个重要实现示例,但随后与SilverLight纠缠在一起,自2007年以来似乎已经失去了优先级。有关此状态的可信来源将会很有帮助。

  • MyJScript: 作为DLR的教程实现构建。有人知道它实现的完整性吗?

  • Jint: 为.NET提供的JavaScript解释器,目前还不支持柯里化或try-catch-finally

  • RemObjects Script for .NET: 一种正在开发中的有趣选项。他们的营销方式让我感到困惑,不过听起来它可能最终会成为一个适合的工具。如果有人对此了解更多,那将非常有帮助。

  • V8 for .NET: 如果有人将V8移植到.NET上,这将是很棒的事情。据我所知,目前没有大量关于这方面的努力。链接是一个调用受控C++包装器中的V8引擎的想法。

  • 背景:我希望在.NET中执行JavaScript;即加载一组脚本到上下文中,并调用该上下文并检索执行结果。目前我通过麻烦的COM互操作来使用MSScriptControl。COM的不一致性使得部署和确保一致的执行非常困难。

    我希望能够在.NET中执行相对复杂的JavaScript测试套件。这不是为了创建用户宏或简单的小脚本;我需要像Rhino这样实际的JavaScript环境。如果实现是运行在CLR上(而不是COM上),这将有助于解决当前的一些问题。


    1
    你能通过ikvm运行犀牛吗?http://ikvm.net/ - Stobor
    9
    JavaScript 选择 Mozilla Rhino,再选择 IKVM.NET,最后选择 .NET。这就像是三明治一样 :) - Ionuț G. Stan
    或者使用VMKit(llvm.org)上的Rhino。 - Jared Updike
    Jint 现在处理柯里化和异常。 - Sébastien Ros - MSFT
    我的非正式实现正在进行中... - ChaosPandion
    @Sean McMillan,您能否将这个作为答案添加,这样我们就可以评论,分享发现等。 - mckamey
    9个回答

    18

    目前,我已经修改了EcmaScript.NET的一个版本,并将其整合进我的YUICompressor.NET(项目)中。

    如果你从这里获取源代码,我已经在项目中包含了我的修改代码,可以引用它。这是我在.NET中找到的唯一能够处理服务器端JavaScript解析的代码来源。

    不幸的是,我不能记得我是如何最终找到它的。我必须承认这是个艰难的过程。我想我在某个地方找到了有关Rhino(Java代码)的Mozilla开发人员页面的一些参考资料,这导致我找到了C# .NET实现。

    我不得不稍微修改它以与YUI Compressor团队对他们的代码分支所做的一些更改同步。因此,我拥有的修改分支可能不是最好的...但它是我看到的最接近原始Java分支的代码。

    自2007年以来,EcmaScript.NET的原始C#代码似乎没有被修改过...至少下载页面上是这样。

    也许这会有所帮助??

    希望有所帮助。


    非常好,我很欣赏这些细节。如果它可以处理YUI压缩器的脚本,那么对于我的东西来说应该已经足够了。如果你不想将其作为主要目标进行维护,那么将其作为一个独立的项目并获得其他人的帮助可能会更容易。我非常乐意为任何我所做的修复/改进做出贡献。谢谢! - mckamey
    1
    我肯定不想要对修改后的版本拥有所有权,所以我很高兴将其移动到 CodePlex 中,成为一个单独的项目…假设我所拥有的代码库…呃…是可以接受的 :) (我也更喜欢 CodePlex 而非 Google Code :P) - Pure.Krome
    这是一个已经停止开发的项目吗?另外,我昨天发布了 YUICompressor.NET 的一个新版本 :) - Pure.Krome
    这适用于许多情况(尤其是YUI Compressor),但我遇到了许多需要更新版本的Rhino的情况。由于EcmaScript.NET代码库已经从Rhino(重命名类等)大幅更改,因此几乎不可能随着补丁的更新而保持最新状态。 - mckamey
    正如AC在回答这个问题的另一个答案中提到的那样,Jurassic(http://jurassic.codeplex.com/)看起来非常有吸引力。它还声称比Chrome更“符合”ECMAScript 3规范——如果是真的,那就意味着它非常好。 - Andrew Theken
    显示剩余4条评论

    14

    依然存活:

    • Jurassic(在过去一年内有提交)
    • Jint(正在接收拉取请求)

    其他项目,大多已死:

    奇怪的方法:

    • Rhino over IKVM(在评论中提到过,这里有更多关于如何做的信息。)

    +1 对于 IronJS。我肯定会关注它的。不过听起来它现在还处于很早期的阶段。有没有什么迹象表明它运行得如何? - mckamey

    12

    目前还没有人提到过Jurassic http://jurassic.codeplex.com/。我不知道它整体表现如何(性能、易用性等),但至少它可以解析非常复杂的脚本(其他实现不行),并支持ECMAScript 5规范。我在这里添加了链接供参考。


    我在Jurassic添加了ActiveXObject支持,形式为这个项目:http://jurascript.codeplex.com/ ,这样你就可以重用大多数旧的WSH/JScript脚本。显然,在假设不会出现问题之前,应该对它们进行彻底的测试。 :) - aikeru
    Jurassic是比较友好的框架之一,而且性能也很不错。 - Surya Pratap

    8

    没有人提到ClearScript,所以ClearScript

    它不是一种实现;它是一个互操作包装器,支持V8、JScript和VBScript,并且具有从.NET代码调用它们的非常好的API。

    来自CodePlex页面的示例代码:

    using System;
    using Microsoft.ClearScript;
    using Microsoft.ClearScript.V8;
    
    // create a script engine
    using (var engine = new V8ScriptEngine())
    {
        // expose a host type
        engine.AddHostType("Console", typeof(Console));
        engine.Execute("Console.WriteLine('{0} is an interesting number.', Math.PI)");
    
        // expose a host object
        engine.AddHostObject("random", new Random());
        engine.Execute("Console.WriteLine(random.NextDouble())");
    
        // expose entire assemblies
        engine.AddHostObject("lib", new HostTypeCollection("mscorlib", "System.Core"));
        engine.Execute("Console.WriteLine(lib.System.DateTime.Now)");
    
        // create a host object from script
        engine.Execute(@"
            birthday = new lib.System.DateTime(2007, 5, 22);
            Console.WriteLine(birthday.ToLongDateString());
        ");
    
        // use a generic class from script
        engine.Execute(@"
            Dictionary = lib.System.Collections.Generic.Dictionary;
            dict = new Dictionary(lib.System.String, lib.System.Int32);
            dict.Add('foo', 123);
        ");
    
        // call a host method with an output parameter
        engine.AddHostObject("host", new HostFunctions());
        engine.Execute(@"
            intVar = host.newVar(lib.System.Int32);
            found = dict.TryGetValue('foo', intVar.out);
            Console.WriteLine('{0} {1}', found, intVar);
        ");
    
        // create and populate a host array
        engine.Execute(@"
            numbers = host.newArr(lib.System.Int32, 20);
            for (var i = 0; i < numbers.Length; i++) { numbers[i] = i; }
            Console.WriteLine(lib.System.String.Join(', ', numbers));
        ");
    
        // create a script delegate
        engine.Execute(@"
            Filter = lib.System.Func(lib.System.Int32, lib.System.Boolean);
            oddFilter = new Filter(function(value) {
                return (value & 1) ? true : false;
            });
        ");
    
        // use LINQ from script
        engine.Execute(@"
            oddNumbers = numbers.Where(oddFilter);
            Console.WriteLine(lib.System.String.Join(', ', oddNumbers));
        ");
    
        // call a script function
        engine.Execute("function print(x) { Console.WriteLine(x); }");
        engine.Script.print(DateTime.Now.DayOfWeek);
    
        // examine a script object
        engine.Execute("person = { name: 'Fred', age: 5 }");
        Console.WriteLine(engine.Script.person.name);
    }
    

    7

    感谢@Sebastien的建议。我想创建一个类似于Orchard.Scripting.Dlr的JavaScript脚本模块,这是我应该使用的库吗?还是有更适合DLR的东西? - Behnam Esmaili
    这是要使用的库,但它已被弃用,建议使用Github上的新库:https://github.com/sebastienros/jint - Sébastien Ros - MSFT

    6
    你应该尝试使用Codeplex上的Javascript .NET (http://javascriptdotnet.codeplex.com/)。他们使用托管C++包装了v8,然后你可以在.NET应用程序中使用此库,并且它非常好用。如果你问我,开源提供了一些相当不错的功能。

    祝好。


    你(或其他人)知道这个实现有什么需要注意的地方吗?它是纯托管的吗?还是需要特定的处理器架构?我很好奇它是否可以在Mono或其他备选CLR上运行。 - mckamey
    很遗憾,由于托管C++在Linux上无法运行,因此您将无法在Mono上运行它。Javascript .NET在x86平台上运行,因为v8是在x86上的,但很遗憾,由于v8不支持多线程功能,您将无法在多线程应用程序中使用Javascript .NET。这大概就是我所知道的关于该项目的全部内容了。我在我的个人应用程序中使用它,目前运行良好。 - Deacon Frost

    4
    你可以使用Jscript.net,它可以与任意javascript代码一起使用;你只需要通过编译jsc /fast- bar.js来关闭“快速模式”。我没有测试过这个方法,但是在阅读这篇文章时注意到了它,并认为这是另一个合理的解决方案。MSDN提供了此选项的文档以及如果不使用此选项的限制

    4

    V8.NET

    这可能是我遇到的最好的一个。
    https://v8dotnet.codeplex.com/documentation

    此外,它从一开始就考虑了Mono端口的构建。 它允许您在托管代码中完全控制V8引擎的功能。


    1

    我更喜欢JINT而不是其他的。

    JINT可能会慢一些,但易于调试并与自己的.NET类进行交互。 (对于jscript.dll等设置[ComVisile]属性很困难)。

    就线程而言,JINT和Jurassic的工作方式符合我的预期。要使用JScript引擎或Google V8,必须注意UI线程问题。

    然而,在某些方面上,JINT已经过时了,因为我在编译JQuery 1.5或更高版本时遇到了麻烦。

    我希望Jurassic可以通过创建'AllowBob'sCLRClass=true'来消除其将自己的类粘贴在一起以使其工作的限制。

    我必须重新编写整个类。这很困难...


    1
    这个线程已经三年了,里面的信息可能已经过时了! - durron597
    没错。最终,我最终使用了Java中的Rhino。 - mckamey
    1
    Rhino 1.7R的性能也很不错。在Oracle发布新的Java 8中的“Nashorn”之前,我也一直在使用它。 - ultra mother hacker

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接