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:
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.
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.
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:
ts.transpile
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
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.
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> {}"));
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With