【问题标题】:Loading the TypeScript compiler into ClearScript, "WScript is undefined", impossible task?将 TypeScript 编译器加载到 ClearScript 中,“WScript 未定义”,不可能的任务?
【发布时间】:2013-09-26 08:48:19
【问题描述】:

我尝试使用ClearScript 加载TypeScript 编译器以编译一些基本的TypeScript 代码。

不幸的是,在执行 TypeScript 编译器源时,我收到了这个错误:

'WScript' 未定义

这是我使用的 LINQPad 程序,将 ClearScript dll 和 TypeScript compiler file 放在 .linq 程序旁边:

void Main()
{
    using (var js = new Microsoft.ClearScript.Windows.JScriptEngine(Microsoft.ClearScript.Windows.WindowsScriptEngineFlags.DisableSourceManagement))
    {
        var typeScriptSource = File.ReadAllText(Path.Combine(Path.GetDirectoryName(Util.CurrentQueryPath), "tsc.js"));
        js.Execute(typeScriptSource);
        const string typeScriptCode = @"
            class Greeter {
                greeting: string;
                constructor(message: string) {
                    this.greeting = message;
                }
                greet() {
                    return ""Hello, "" + this.greeting;
                }
            }
            function test()
            {
                var greeter = Greeter(""world"");
                return greeter.greet();
            }
        ";
        js.Script.TypeScript.Compile(typeScriptCode);

        object result = js.Script.test();
        result.Dump();
    }
}

#region Copy ClearScript to correct location

static UserQuery()
{
    foreach (var filename in new[] { "ClearScriptV8-32.dll", "ClearScriptV8-64.dll", "v8-ia32.dll", "v8-x64.dll" })
    {
        try
        {
            string sourcePath = Path.Combine(Path.GetDirectoryName(Util.CurrentQueryPath), filename);
            string targetPath = Path.Combine(Path.GetDirectoryName(typeof(Util).Assembly.Location), filename);

            File.Copy(sourcePath, targetPath, true);
        }
        catch (IOException ex)
        {
            unchecked
            {
                const int fileInUseHresult = (int)0x80070020;
                if (ex.HResult != fileInUseHresult)
                    throw;
            }
        }
    }
}

#endregion

错误发生在这一行:

js.Execute(typeScriptSource);

我已经创建了一个包含所有内容的 .zip 文件,您需要 LINQPad 来加载 .linq 文件并进行实验。 ClearScript dll 是从未经修改的源创建的,但如果您不相信我,您应该能够自己复制它们(如果您没有它们的话)。

可在此处获得:Dropbox Link to SO19023498.zip

我尝试过的:

  1. 我尝试先执行这段代码:

    var WScript = new ActiveXObject("WSH.WScript");
    

    这只产生了这个错误:Automation server can't create object

    我没有在 HKEY_CLASSES_ROOT 下的注册表中看到 WSH.WScript,所以可能是这样。

  2. 我尝试弄清楚如何从 .NET 创建对象并将其设置到脚本上下文中,但我显然没有找到正确的位置。

【问题讨论】:

  • 请注意,我不知道编译打字稿代码的调用是否正确,也许它会返回生成的javascript代码,但程序在该步骤之前失败。
  • WScript 对象不可创建,尽管您可以使用 C# 类相当容易地模拟它。 tsc.js 脚本还需要 ActiveXObject,它是一种 JScript 主义,但如果您想使用 V8,也可以模拟出来(我假设您这样做,因为您正在费力安装 ClearScript 的 V8 DLL)。不过,这一切都需要一些工作,所以我会在下面推荐 Ela 的方法。

标签: c# .net typescript windows-scripting clearscript


【解决方案1】:

4 年后,在https://rawgit.com/Microsoft/TypeScript/master/lib/typescriptServices.js 使用 TypeScript 2.7 服务 它现在有点像两条线:

  • 用这个脚本初始化你最喜欢的 JS 引擎
  • 加载 *.ts 资源的字符串内容
  • 获取ts.transpile的函数引用
  • 将类型脚本作为字符串提供给它,然后用转译的源返回一个字符串

使用例如C# 中的 ClearScript engine 与字符串 src 中的 TS 源代码这将是:

dynamic transpile = engine.Evaluate("ts.transpile");
var js = transpile(src);
// now feed the string js into a different JS engine

【讨论】:

    【解决方案2】:

    在对 ClearScript 进行了一些尝试之后,这个想法实际上非常酷,可以让它运行起来。

    要让您的代码至少运行得更多一点: 不使用 tsc.js,只需使用 SDK 附带的 typescript.js,并且应该在同一个文件夹中。

    var typeScriptSource = File.ReadAllText("typescript.js");
    

    typescript.js 是 tsc 使用 WSH 和其他 com 对象的纯 javascript 编译器...

    这样,你也可以使用V8引擎!

    但无论如何,这意味着您必须编写一些 JavaScript 代码才能真正包装 TypeScript.TypeScriptCompiler 函数。

    因此,这意味着您必须像在自定义 html 页面中使用 TypeScriptCompiler 一样(就像 Playground 那样)。 到目前为止,我找不到任何有关如何使用编译器的文档... 但我发现一页也试图实现这一点 http://10consulting.com/2012/10/12/introduction-to-typescript-presentation/ 如果您查看演示文稿的源代码,您会发现 Compiler 类。

    Compiler.prototype.compile = function (src) {
        var outfile = {
            source: "",
            Write: function (s) {
                this.source += s;
            },
            WriteLine: function (s) {
                this.source += s + "\n";
            },
            Close: function () { }
        };
    
        var compiler = new TypeScript.TypeScriptCompiler(outfile);
    
        try {
            compiler.parser.errorRecovery = true;
            compiler.setErrorCallback(function (start, len, message, block) {
                console.log('Compilation error: ', message, '\n Code block: ', block, ' Start position: ', start, ' Length: ', len);
            });
            compiler.addUnit(Compiler.libfile, 'lib.d.ts');
            compiler.addUnit(src, '');
    
            compiler.typeCheck();
    
            compiler.emit(false, function createFile(fileName) {
                console.log(outfile);
                return outfile;
            });
    
            console.log('compiled: ' + outfile.source);
            return outfile.source;
        } catch (e) {
            console.log('Fatal error: ', e);
        }
        return '';
    };
    return Compiler;
    

    这看起来很有希望,但不幸的是,如果我尝试将它与 ClearScript 一起使用,它会引发奇怪的错误,也许我做错了什么......

    至少,如果我通过代码进行调试,js.Scripts.TypeScript 已定义并包含所有 TypeScript 对象!

    无论如何,我想这应该会让你更进一步;)如果你成功了,请告诉我!

    作为替代方案,您当然可以使用命令行工具来简单地调用编译器,而不是直接在 C# 中执行它。我想这应该更容易实现......或者使用 node.js 包,它还为您提供所需的所有编译器服务。

    【讨论】:

    • 谢谢你,我今天晚些时候一定会试试这个,我会根据需要发布 cmets 或其他内容来反映我的发现。
    • Ela 在这里是正确的。 typescript.js 脚本是核心的可移植 TypeScript 代码,它在 V8 中完美运行。但是,上面的 Compiler 包装器看起来已经过时了。例如,TypeScriptCompiler 在最近的下降中没有 addUnit() 方法。上面的代码还使用了必须在某处定义的“控制台”对象。
    【解决方案3】:

    这是一个使用当前版本的typescript.js 的骨架样本。请注意,TypeScript API 是逆向工程的;据我所知,唯一的官方界面在tsc 命令行。另请注意,这是一个不进行错误处理或报告的最小示例:

    using System;
    using System.IO;
    using Microsoft.ClearScript;
    using Microsoft.ClearScript.V8;
    
    namespace Test
    {
        public class TypeScriptCompiler
        {
            private readonly dynamic _compiler;
            private readonly dynamic _snapshot;
            private readonly dynamic _ioHost;
    
            public TypeScriptCompiler(ScriptEngine engine)
            {
                engine.Evaluate(File.ReadAllText("typescript.js"));
                _compiler = engine.Evaluate("new TypeScript.TypeScriptCompiler");
                _snapshot = engine.Script.TypeScript.ScriptSnapshot;
                _ioHost = engine.Evaluate(@"({
                    writeFile: function (path, contents) { this.output = contents; }
                })");
            }
    
            public string Compile(string code)
            {
                _compiler.addSourceUnit("foo.ts", _snapshot.fromString(code));
                _compiler.pullTypeCheck();
                _compiler.emitUnit("foo.ts", _ioHost);
                return _ioHost.output;
            }
        }
    
        public static class TestApplication
        {
            public static void Main()
            {
                using (var engine = new V8ScriptEngine())
                {
                    var compiler = new TypeScriptCompiler(engine);
                    Console.WriteLine(compiler.Compile("class Foo<T> {}"));
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-27
      • 1970-01-01
      • 1970-01-01
      • 2011-09-28
      • 2023-01-18
      • 1970-01-01
      • 2020-08-11
      相关资源
      最近更新 更多