将TypeScript编译器加载到ClearScript中,“WScript未定义”,不可能完成任务?

时间:2013-09-26 08:48:20

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

我尝试使用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创建对象并将其设置到脚本上下文中,但我显然没有找到正确的位置。

3 个答案:

答案 0 :(得分:5)

在使用ClearScript玩一下后,实际上让它运行的想法非常酷。

让代码至少运行一点: 不要使用 tsc.js ,只需使用SDK附带的 typescript.js 即可,并且应位于同一文件夹中。

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

typescript.js是普通的javascript编译器,其中tsc使用WSH和其他com对象......

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

但无论如何,这意味着您必须编写一些JavaScript来实际包装TypeScript.TypeScriptCompiler函数。

所以这意味着你必须像在自定义html页面中使用TypeScriptCompiler一样(就像游乐场一样)。 到目前为止,我找不到任何关于如何使用编译器的文档...... 但我发现一个页面也试图实现这一点 http://10consulting.com/2012/10/12/introduction-to-typescript-presentation/ 如果你看一下演示文稿的来源,你会发现一个编译器类。

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包,它还为您提供所需的所有编译器服务。

答案 1 :(得分:4)

这是使用当前版本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> {}"));
            }
        }
    }
}

答案 2 :(得分:3)

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