Загрузка компилятора TypeScript в ClearScript, WScript — неопределенная, невыполнимая задача?

Я попытался использовать ClearScript для загрузки ссылки TypeScript для компиляции базового кода TypeScript.

К сожалению, при выполнении исходного кода компилятора TypeScript я получаю эту ошибку:

«WScript» не определен

Это программа LINQPad, которую я использовал, поместите dll ClearScript и файл файл компилятора TypeScript вместе с программой .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 и поэкспериментировать. DLL ClearScript создаются из немодифицированного источника, но если вы мне не доверяете, вы сможете воспроизвести их самостоятельно (если у вас их нет).

Он доступен здесь: Ссылка Dropbox на SO19023498.zip.

Что я пробовал:

  1. Сначала я попытался выполнить этот код:

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

    Это вызвало только эту ошибку: Automation server can't create object

    Я не видел WSH.WScript в реестре под HKEY_CLASSES_ROOT, так что может быть.

  2. Я попытался выяснить, как создать объект из .NET и установить его в контексте скрипта, но, видимо, я ищу не в том месте.


person Lasse V. Karlsen    schedule 26.09.2013    source источник
comment
Обратите внимание, что я не знаю, корректен ли вызов для компиляции машинописного кода, возможно, он возвращает результирующий код javascript, но программа завершается ошибкой до этого шага.   -  person Lasse V. Karlsen    schedule 26.09.2013
comment
Объект WScript нельзя создать, хотя его можно довольно легко эмулировать с помощью класса C#. Для сценария tsc.js также требуется ActiveXObject, который представляет собой JScript-изм, но его также можно смоделировать, если вы хотите использовать V8 (что, как я предполагаю, вы делаете, поскольку вы прилагаете усилия, чтобы установить библиотеки DLL ClearScript V8). Однако все это будет немного работы, поэтому я бы рекомендовал подход Элы ниже.   -  person BitCortex    schedule 26.09.2013


Ответы (3)


Через 4 года использования служб TypeScript 2.7 на https://rawgit.com/Microsoft/TypeScript/master/lib/typescriptServices.js теперь это двухстрочный код:

  • инициализируйте свой любимый JS-движок с помощью этого скрипта
  • загрузить строковое содержимое вашего ресурса *.ts
  • получить ссылку на функцию ts.transpile
  • подайте ему сценарий типа в виде строки и верните строку с переданным источником

Использование, например. ClearScript engine на C# с исходным кодом TS в строке src это будет:

dynamic transpile = engine.Evaluate("ts.transpile");
var js = transpile(src);
// now feed the string js into a different JS engine
person Zartag    schedule 15.02.2018
comment
Это лучшее решение! - person marco burrometo; 11.05.2018

После того, как я немного поиграл с ClearScript, идея запустить его на самом деле довольно крутая.

Чтобы ваш код работал хотя бы немного лучше: вместо использования tsc.js просто используйте typescript.js, который поставляется с SDK и должен быть в та же папка.

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

typescript.js — это простой компилятор javascript, в котором tsc использует WSH и другие объекты com...

Таким образом, вы также можете использовать двигатель V8!

Но в любом случае это означает, что вам придется написать код JavaScript, чтобы фактически обернуть функции TypeScript.TypeScriptCompiler.

Таким образом, это означает, что вам придется делать то же самое, как если бы вы использовали TypeScriptCompiler на своей пользовательской html-странице (как это делает игровая площадка). Пока я не смог найти никакой документации о том, как использовать компилятор... Но я нашел одну страницу, которая также пытается реализовать это 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, который также предоставляет вам все необходимые услуги компилятора.

person MichaC    schedule 26.09.2013
comment
Спасибо за это, я обязательно попробую это позже сегодня, я буду публиковать комментарии или что-то еще по мере необходимости, отражая то, что я узнаю. - person Lasse V. Karlsen; 26.09.2013
comment
Эла здесь на правильном пути. Сценарий typescript.js — это основной переносимый код TypeScript, и он отлично работает в V8. Однако приведенная выше оболочка компилятора выглядит устаревшей; например, TypeScriptCompiler не имеет метода addUnit() в последних выпусках. Приведенный выше код также использует объект «консоль», который должен быть где-то определен. - person BitCortex; 26.09.2013

Вот пример скелета с использованием текущей версии typescript.js. Обратите внимание, что API TypeScript переработан; насколько я могу судить, единственный официальный интерфейс находится в командной строке 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> {}"));
            }
        }
    }
}
person BitCortex    schedule 05.11.2013