Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loading the TypeScript compiler into ClearScript, "WScript is undefined", impossible task?

I tried using ClearScript to load the TypeScript compiler in order to compile some basic TypeScript code.

Unfortunately, when executing the TypeScript compiler source I get this error:

'WScript' is undefined

This is the LINQPad program I've used, place the ClearScript dll's and the TypeScript compiler file alongside the .linq program:

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

The error occurs on this line:

js.Execute(typeScriptSource);

I have created a .zip file with everything, you need LINQPad to load the .linq file and experiment. The ClearScript dll's are created from the unmodified source but if you don't trust me you should be able to reproduce those yourself (if you don't have them that is).

It is available here: Dropbox Link to SO19023498.zip.

What I've tried:

  1. I tried executing this code first:

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

    This only produced this error: Automation server can't create object

    I did not see WSH.WScript in the registry under HKEY_CLASSES_ROOT so that might be it.

  2. I tried figuring out how to create the object from .NET and setting it into the script context, but I am apparently not looking in the right place.

like image 365
Lasse V. Karlsen Avatar asked Sep 26 '13 08:09

Lasse V. Karlsen


3 Answers

After 4 years, using the TypeScript 2.7 Services at https://rawgit.com/Microsoft/TypeScript/master/lib/typescriptServices.js it's kind of a two-liner now:

  • initialize your favorite JS engine with this script
  • load the string contents of your *.ts resource
  • get a function reference of ts.transpile
  • feed it the type script as a string and get back a string with the transpiled source

Using e.g. a ClearScript engine in C# with TS sourcecode in the string src this would be:

dynamic transpile = engine.Evaluate("ts.transpile");
var js = transpile(src);
// now feed the string js into a different JS engine
like image 58
Zartag Avatar answered Nov 07 '22 06:11

Zartag


After playing around a little bit with ClearScript, the idea is pretty cool actually to get it running.

To get your code at least a little bit more running: Instead of using the tsc.js, simply use the typescript.js which comes with the SDK and should be in the same folder.

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

typescript.js is the plain javascript compiler where tsc is using WSH and other com objects...

This way, you could also use the V8 engine!

But anyways, this means your would have to code some JavaScript to actually wrap the TypeScript.TypeScriptCompiler functions.

So this means you would have to do the same as if you would use the TypeScriptCompiler within your custom html page (like the playground does). I couldn't find any documentation of how to use the compiler so far though... But I found one page which also tries to implement this http://10consulting.com/2012/10/12/introduction-to-typescript-presentation/ If you look at the source of the presentation, you'll find a Compiler class.

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;

This looks pretty promising but unfortunately, if I try to use it with ClearScript it throws strange errors, maybe I'm doing something wrong...

At least, if I debug through the code, the js.Scripts.TypeScript is defined and contains all the TypeScript objects!

Anyways, I guess this should bring you a step further ;) let me know if you had success!

As an alternative, you could of cause use the command line tool to simply invoke the compiler instead of doing it from within the C# directly. I guess this should be way easier to implement... Or play around with the node.js package which also provides you all the compiler services you need.

like image 5
MichaC Avatar answered Nov 07 '22 05:11

MichaC


Here's a skeletal sample using the current version of typescript.js. Note that the TypeScript API is reverse-engineered; as far as I can tell the only official interface is at the tsc command line. Also keep in mind that this is a minimal sample that does no error handling or reporting:

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> {}"));
            }
        }
    }
}
like image 5
BitCortex Avatar answered Nov 07 '22 06:11

BitCortex