Hacker News new | past | comments | ask | show | jobs | submit login
New C# to Javascript compiler released (erik-kallen.se)
109 points by erik-kallen on Sept 3, 2012 | hide | past | web | favorite | 79 comments

As I see the author reads these comments, I'd just like to add that this makes me very excited. C# is my favourite language by far, combining some of the most powerful (mainstream) language features with some of the most powerful dev tools out there.

Having the ability to run the same code in the browser and on the server, in C#, is really a big thing for me.

I think the debugging problem stated in many comments here is overrated: If you're writing an app the size that seriously benefits from the modularity, the tool support and the type checking of a language like C#, you will have a relatively small amount of code directly touching the DOM. All of that other code can be simply unit tested in C#-o-world, straight from the dev environment. If you're writing C#, don't test and debug like it's JS!

Surely such an approach won't catch all bugs and the occasional leaky abstraction (or compiler bug), but it should get one pretty far. Some in-browser unit testing lib together with the fact that the generated JS is quite readable indeed, should help me get the rest of the way.

Can't wait to dive in!

After the initial curve of getting VC10 configured right, I did an inheritance test. It worked (copied base class prototype, called base constructor with this.) Minutes later I was happily converting C# code to nicely formatted JavaScript. Having spent the last two weeks converting JS to Dart (basically a one way process because you don't want to look at Dart->JS), I'd say this project is a winner and immediately usable. I'm positive there are C# features and libraries that don't convert well, or at all, but I'm not interested in those in the browser any way.

The very best of luck when it comes to debugging the code when it is running in the browser.

Maybe your experiences are different to mine but I avoid such abstractions wherever possible.

It has become fashionable to say things like "JavaScript ... is not well suited for developing large systems" - indeed so much so it often passes without comment but when it is JavaScript that will be run by the browser then JavaScript is what you should be writing.

"... but when it is JavaScript that will be run by the browser then JavaScript is what you should be writing."

So by that logic, one shouldn't be writing C# that targets the CLR either, but should rather be coding in MSIL directly. Mmm, no thanks!

Come on, we all know that isn't a logical equality.

Once the debugging tools are able to keep everything abstracted then you no longer need to dig down. Example is of course writing assembly.

Yeah there's no logical equality to machine code and C++ but still people use debuggers. I don't think this is something that cannot be solved.

But JavaScript is not (another daft meme) "the assembler of the web" as it is itself interpreted (or what have you) into byte code for execution.

The point is that one should limit the level of abstraction to one which sits in that comfort zone between code that is sensible to humans and code that is sensible to the machine running it and (perhaps more importantly) the available dev/debug tools.

No, one should limit the level of abstraction to the fastest one that is reliable enough to get the job done. There's nothing intrinsic about high abstraction layers that say they must suck for debugging what you need debugged. It just depends on what you need to do with it. If it gets your job done faster and it's reliable enough for your job, then why not? That's why higher abstractions are created in the first place.

In short, you can't instantly rule out this compiler without knowing exactly what you'd want to do with it. And exactly how good it would be at that specific problem.

Yes no limits to abstractions always works perfectly..

Check out this stack trace:


Now imagine that across three different languages.

Java has been said to be a DSL to convert XML configuration into stack traces. But what does this have to do with compiling C# to Javascript?

The abstraction is too deep. The stack trace above is an example of what too deep abstractions do to those who have to use them.

I don't agree that JavaScript being good enough for one person makes it good enough for everyone.

I don't agree that limitations should be placed on abstractions; I have no clue what's happening at the CPU level when a line of JavaScript or MSIL or bla bla executes. I don't need to know what's happening at all the layers of abstraction beneath the one I'm working on, and that helps me be productive.

There might be a pragmatic argument against using compile-to-JS languages _right now_, but with things like Google Chrome's Source Maps, this is a problem that is being solved if it hasn't been already.

Actually, debugging is quite simple. The generated script (unless minified) is very similar to the input code. Are you also against other options such as CoffeeScript? And do you think it is very hard to debug higher-level languages such as C, C# or Java because "if you are writing code to run on a processor, it is assembly you should be writing"?

The question is how similar? Coffeescript has come a long way in keeping symbols similar enough to be debuggable and not polluting the javascript namespace. Once the code grows to a certain size, tracing from line number in error to a line of code in your source becomes non-trivial.

Also, since this has been a constant pain for me when using Google Closure compiler, how do you anticipate this tool working with existing javascript libraries? Hypothetically, can I port a C# application ( a reasonable/simple one, not with crazy winforms and stuff)? Is there a spec you're adhering to?

It comes with metadata for jQuery and jQueryUI, so obviously those libs can be used. I know of people using Node as well (and I hope to include that import lib in the distribution at some point).

As for porting an existing C# application, it will probably not be trivial, but the back-end stuff is most likely possible (as long as it doesn't have external references). Personally, for my own stuff I tend to compile stuff like DTOs and helpers to both Javascript (running on the client) and regular MSIL (running on the server), but that code has been written with this intent from the beginning.

I prefer to regard working with this to be writing Javascript but with tooling from 2012 instead of 1995.

Well, he actually said "debugging code when it is running," which a lot of people find valuable. Of course you can debug anything in the looser sense of the term, but tools like debuggers make the process more productive.

And yes, many people are against Coffeescript too for precisely this reason.

You can use the Chrome debugger just as if you had written the Javascript directly.

I agree. Having had used GWT and other similar cross compiling to javascript type tools, it's often a huge problem in debugging than if you just write a short javascript code. No offense to the author but projects like these that try to fit a static language like Java/C# that run in their own managed environments into dynamic world of Javascript fail miserably.

I fear projects like these tend to attract programmers who know C#, Java but don't quite want to learn javascript and they don't even try to do it once they run out of runway in this tool. And, the code becomes undebuggable, bloated on the browser.

Nothing against other languages, they're amazing at what they do. But, javascript is, for better or worse, the language of browsers. And it's really powerful with established best practices to organize, debug code + great tools (thanks to Chrome Team @ Google and Mozilla).

From a programming languages/compilers standpoint, it definitely tickles my fancy :)

I program both C# and JS on an almost daily basis and am pretty well versed in both. I have to say that JS is great for adding scripting to pages but for large apps it's a nightmare (especially when coupled w/ the dom).

I think it would help the discussion if you could define a "large app" as far as JavaScript is concerned and why you think it is a "nightmare".

I'd call something with more than 100k LOC a large app. It can get messy even before then though. The main concerns I have with Javascript are:

1) Most frameworks try to make JS into a typical OOP language which tends to hurt performance and can make debugging a PITA.

2) In "one page apps" it can become difficult to map nodes to JS objects so things get cleaned up properly. You often see memory build ups even in jQuery because of html node wrappers and events that get cached but don't get cleaned up.

3) Static analysis. It's possible to get some level of static analysis if you use JSDoc but it's still very poor compared to something like C#. For example, you need to add tons of JSDoc code to make autocomplete somewhat usable. After using something like Resharper, you can really see how lack of good static analysis hurts.

4) Difficult to refactor large apps. Since the static analysis is poor, it's difficult to use tools to create dependency graphs, finding usages, etc... I really wish Js would just let you specify a type of an object like ActionScript 3 does. You can still use var if you want but 99% of the time an object has an expected type.

5) Lack of visibility keywords. This makes it hard to organize code into modules and prevent programmers from getting access to things they aren't supposed to. I'm sure there are entire debates on this point alone.

6) Performance. The browsers try to do tons of optimizations during runtime to speed up javascript. If you want to get the most out of JS, you really need to know about them (e.g. always initialize your class vars in the same order).

Really, really

GWT is not the answer, Dart is not the answer, not writing JS is not the answer (maybe CoffeeScript but I'm skeptical)

JS may have its warts, but in the end that's what browsers understand. That's what you'll have to know to debug things.

And the browser doesn't have to execute 2x, 3x the code, and use more memory as well

If you want something to help my perception is that it should be a thin shin (like CS) rather than "full bells and whistles" on top like GWT or Dart

Maybe that's where source maps come handy?


This sounds like a solution to a problem that probably shouldn't exist because there is a solution that shouldn't exist to start with which has caused a problem that doesn't need to occur.

The slightly overbearing complexity of the solution matches the linguistic complexity of the statement above :)

I don't see how these are significantly different than .PDBs which allow Windows developers to step through their source code when debugging compiled binaries.

It is similar to PDB files, which is fine but that is not the issue. The issue is that the abstraction is criminally tall. We're talking a tower of:

Process: C# --(compiler)--> Js --(parser)--> IL --(compiler)--> machine code/interpreter.

Type conversions: Static --> dynamic --> static --> none.

That's just too much to go wrong in my mind. I wouldn't touch it with a barge pole.

They do come in handy, if only they were supported everywhere. Right now it's just Chrome and a small number of tools.

>when it is JavaScript that will be run by the browser then JavaScript is what you should be writing.

Of course, source maps will soon make this point largely moot.

Haven't happened for the last 2 years we've been waiting for them.

You should run and debug the C# code, before you compile it to JS, that's how I understand the idea behind this project.

I don't see the problem.

- If I had written Javascript, I would have to debug the Javascript that is running in the browser.

- If a tool writes Javascript for me, I have to debug Javascript running in the browser.

A better wish would be: I hope that your tool outputs nicely formatted and easy to debug Javascript.

But it will not write JavaScript the way you would write it - and (avoiding arguments about personality in code) that JavaScript will be way harder to follow and debug.

I agree, but generating "harder to debug" output isn't really a big argument against generators.

The first argument is that "the style is different". I use a js generator language (not this one, I don't want to shift attention), and it does "nice" things that would be a pain for me to do manually... like setting up namespaces for code, spacing everything perfectly. Even if the output is not to your taste, at least you know that the style will be 100% consistent in style and implementation. I never have problems debugging.

The other argument is that "the generated code is complex/ugly". Unfortunately, "fast" code is often ugly. Static compilers can do some optimizations by default (e.g. optimized for loops), and you only need to worry about the "pretty" code at the higher level of abstraction. I doubt you will ever have to debug one of these optimizations, any decent compiler should get them right. You merely have to understand why they were used, which often makes you a better programmer to boot.

It's likely there would be less need for JavaScript debugging.

Looks impressive!

I'm curious how you're doing the parsing. I see that you reference both NRefactory (which reads C#) and Cecil (which reads IL) -- can you talk about how are each of these used and how you combine them?

Also, did you consider using Roslyn (Microsoft's official C# parser)? Obviously it's still beta, but once it's complete would it remove the need for Cecil and NRefactory completely?

Why would I want to use the proprietary Roslyn when I have a working solution with the open-source NRefactory and Cecil?

I can think of a dozen reasons off the top of my head. But if you prefer to avoid proprietary utilities that's understandable.

NRefactory itself depends on Cecil, so his translator might not use Cecil at all.

Wow! A great hack on hacker news! Thanks Erik. Don't let the griping grind you down.

Not entirely the same, but for those of us on Window, I prefer the look of http://jsil.org.

JSIL is also great, but its philosophy is that yo write .net code and run it in the browser, whereas Saltarelle's (and Script#'s) is that you write Javascript but with better tools. Also, the script that JSIL generates is very far from what you would write by hand, whereas that generated by Saltarelle/Script# can be distinguished from hand-written script primarily because the indentation is always correct and there is never an accidental loose comparison operator.

Could you not somehow reuse the JSIL code generator, and add things for the approach you took in Saltarelle (good integration with JQuery etc.)?

Another question, did you do any performance comparisons of Saltarelle? (to normal C# builds, to JSIL, or anything else?)

I think the tools fill different purposes, so integration with JSIL is absolutely a possibility in the future. I did not do any speed comparisons, I just translate what you write in C# to the equivalent script, so if you write a fast script it will be fast, if you write a slow script, it will be slow :)

Well, how you create data structures might matter for performance - if you turn C# structs into JS typed arrays for example and do the proper conversions, that could be much faster than simple JS objects or even arrays.

I don't see how you can really use this without already being very familiar with Javascript. While you're writing your code you'd need to be constantly aware of how the code will be translated to js (so you can use the correct attributes and define datatypes correctly), and you'd also need to be aware of avoiding. NET library classes that can't be used by the translated js. It seems easier to just learn to manage large js projects.

The reason I'm looking for either C# / Scala JS compiler is that I'm a static typing fan, I am an old school developer who likes IDEs and like discovering API by pressing ctrl+space, instead of mentally knowing it or constantly checking the API docs, I know it's against the trend, and not considered cool, but this gets me working software out the door. I'm much more productive and have much less bugs while writing old school, unpopular Java, and using the IDE's (eclipse) sugar features. Scala is now my favorite language (I really hope it was a little more new dev friendly, it can become very syntax overwhelming sometimes) as I can many of the functional features in Ruby / Python / JavaScript / Clojure, but still stay in Static Java land.

Another thing static typing gives me that I really wish I had in JavaScript, is (almost) worry free refactoring.

In Java, I can extract methods, constants, delegates, change method signatures, rename members, fix typos in code, and never to worry I copy pasted something wrong.

I have yet to find such a way to do it safely in JavaScript / CoffeScript or any other dynamically typed language. (feel free to point if I'm missing something, I said I'm not that a great of a developer)

So maybe I'm just not good enough as a developer, but I like IDEs to protect me, perhaps I'm not smart enough to use VIM / Emacs / TextMate, and I can't memorize APIs. Static typing + functional features make me the most productive. So C# / Scala / Java 8 javascript compilers are on the top of my wish list.

I hear you, but I can't agree. Maybe it's my background. For 13 years as a professional developer my primary languages were Perl and Javascript, using Vim and the Unix command-line as my IDE. For the past 1.5 years I've swapped C# for Perl and Visual Studio for my IDE (still have a vi emulator though.) Intellisense is definitely useful, but I find it gets in the way a lot... both literally by overlapping the code around the code I'm typing, and figuratively by trying to insert text while I type which causes me to double-type characters and backspace a lot. It does help with remembering (not learning) APIs, but that's one of my concerns about translating to js: Intellisense won't know which APIs are usable and which ones are not. If you're a C# developer who's dependent on Intellisense, it's going to mislead you here.

Regarding refactoring, it's hardly worry free for me. I always have to double check what VS is going to do when I use its refactoring tools, because sometimes it makes a significant mistake. Now, that's often caused by the way I wrote some code and I have to fix it up as part of my refactoring, but I would have discovered that while refactoring manually too, and if I trusted VS I wouldn't have discovered it at all. So VS helps a bit with the typing, but it's not much faster than I'd be without it. A lot of that is probably because I learned to refactor using vim, grep, sed, and other Unix command-line tools, so I have no problem doing large-scale refactoring changes touching thousands of lines over a 100k+ line codebase. Extracting a method is childs play in comparison, and I don't mind the extra few seconds it takes to do it manually exactly the way I want it.

There is definitely a need for better javascript editing tools. VS, with the right plugins, wouldn't be bad, but I'm not sure Intellisense can really cut it. When I'm putting some code into an MVC template or js file and I want to refer to a jQuery plugin I know is loaded by my layout template, there is no way for Intellisense to know about that plugin or its API, so it can't help me. In contrast if I load my app in Firefox and use Firebug's console and debugger, I can type in some code and it's able to show me the API in real-time because it's reflecting the live javascript objects as I type. That's the kind of intellisense I want.

I fully relate, I wish I had the same background, it would have made me probably a better developer, but I'm already hooked...

What I'm wondering is, why can't we have the browser then be our IDE, chrome already supports editing, just need to persist it to my code base

By the way, I strongly suggest using something like resharper, VS is great, but I found eclipse much better if you are looking for those tricks and shortcuts.

If you haven't tried it yet, I encourage anyone to get eclipse, put in some java code, and play with ctrl+1 magic shortcut (mark anything in code and let it do the work for you) it allows you to be more expressive and write code in a modular way, for example, I don't have to be a boolean logic master, or even a smart developer to extract negation up a boolean condition, and if I forgot a param / method, it will create it for me with the right signature, and if I see a piece of string I want to replace with a variable, it takes it for me and adds those dreadful " + ... + " in so I don't have to. does it makes you a zombie programmer? probably yes, does it make you smarter? probably not, but does it make you more productive? absolutely yes.

again, VS I think is nowhere near eclipse JDT in that end (without resharper at least)

I think this is why GWT, Dart, Scala, Hibernate / Seam, Spring all invest so much in eclipse,

most developers of this world (me included) are just not good enough hackers to do it the VIM / grep way... sad but true.

For statically typing Javascript, I strongly recommend Google's Closure toolset- it uses JS comments to statically type and validate your code, plus you can either run it compiled or uncompiled.


There are no editors that give you the nice intellisense bells and whistles, but static typing is by far the most important for me.

There were tools ones in eclipse that used comments / annotations to give you full "static" feeling with JavaScript... I wonder where did it go...

Here is a nice side project, static typed coffee script, with eclipse IDE support...

I really don't want to go back to GWT or move to Dart...

Scala's Javascript DSL is another hope I have, but it's still under development

but I find it gets in the way a lot... both literally by overlapping the code around the code I'm typing, and figuratively by trying to insert text while I type

I sometimes forget that this is the default, since my first step when installing VS.NET is to turn off all the automatic popping up and getting your way functionality. I think it's analogous to that "Torch Mode" setting that new TVs are on when they're in the showroom, demonstrating every feature they have at once so you see it all and are impressed. The VS.NET that I know doesn't do that. But I guess it would prefer to if you didn't reel it in.

Keep all the good stuff, but leave it behind CTRL+Space. You're four checkboxes away from having your cake and eating it too. And not having it leap up in between you and what you're trying to accomplish.

I think what you're saying is a given...

The author might assume it, but I think it needs to be explicitly stated. Tools like this are often sold as "You don't need to know X because you can now code in Y and translate automatically to X!" That never works out though because there are always leaky abstractions. (For this project, just take a look at the Attributes docs to see how leaky the abstractions are.)

I've had to work with a bunch of C, C++, Java, Perl, and C# developers who were good at backend stuff and just started to learn HTML, CSS, and Javascript, and they're mostly pretty awful at it until they give in and dedicate themselves to the frontend web developer platform and environment. Prior to that they'd grasp at tools like this one that seem to offer hope that they won't have to learn that nasty javascript.

I'm coming at it from a different perspective. I can't worry about what other programmers do. I need tools. I love JS but the tools for it could be better. I'm hoping C#->JS will be a great addition to the toolbox.

Wow, very cool. I like C#, and the DOM is actually specified with types, so statically-typed web dev with this would be awesome.

You can get the majority of this functionality with Closure Compiler though, without needing to abstract the entire language away.

That's true, but I don't really like the closure compiler's syntax.

I came across a similar project on /r/csharp last week. The project's called Blade, and is available here - https://github.com/vannatech/blade

Saltarelle is way more complete, though.

My largest criticism for projects like this is that I absolutely abhor running into compiler errors. When you don't fully trust the compiler, it suddenly becomes a suspect when code isn't working like you think it should.

Given decent source maps to allow debugging through the original code, I don't think solutions like this are terribly different than native Javascript. The primary difference though is that I trust the browser JS interpreters and VMs more than I trust many X->JS compilers.

We use an older version of Script# for a very large site at work. This looks like it might be worth trying to upgrade to.

But what I really want is a way to convert Silverlight to JS. I don't care whether it is source or binary level conversion, but it would be awesome to take projects we've written in silverlight and run them on any browser without a plugin.

I totally agree that JavaScript can easily end up being a huge mess especially when project grows. Using more strict language like C# can help on that. I have to try this, good job!

There are frameworks and best practices for organizing JavaScript heavy projects. I'm all for solutions to unify front and backend web application development so cheers to Erik for developing this, I've just never been a fan of cross language compilation.

Flash, silverlight, Java, native apps...

I don't really get this. Surely JavaScript and C# are so hugely different that any converted code would be horrific? Wouldn't it be simpler to just write JavaScript in JavaScript?

- Translating a statically-typed Object Oriented language to JS wouldn't produce hugely different (/horrific) code. From inheritance to lambdas, there are comparable features available in JS. Going from JS to C# might be harder though.

- It might be simpler to write JS, but I can imagine people wanting to see if type-safety has benefits.

That's right, it doesn't get horrific until you use goto or yield (which don't exist in Javascript so they have to be emulated).

Some browsers, and ES Harmony, have yield. You could add a compiler switch to use native support, although only Firefox seems to support this just now.

Curious to see how you managed the emulation - splitting up a function? Web workers? :)

for (;;), continue and switch.

Looks cool, but need more docs and samples (for each feature)!

Does this include a library for accessing Canvas ? Thanks.

good grief... just learn some fscking JavaScript already! It's not _that_ hard!

How does this compare to http://sharpkit.net (free for small and open source projects) Feature wise? SharpKit seems more complete (language support and has source map debugging support on Chrome). Also support for all popular JS libraries.

SharpKit is only free as long as you want to use it for projects that don't need it (the limit is like 2k lines or something). When I last tried it I was not very happy with the code it generated. Additionally, it uses the standard mscorlib so it is not unlikely that you will end up calling methods that are not implemented (which is the very problem the tool is designed to avoid). If it were open source, I would have contributed to SharpKit instead of rolling my own, but it is not.

When it comes to the language support, I think Saltarelle is slightly ahead, as it supports goto and yield (I don't count SharpKit's implementation of yield which translate 'yield return "x"' to '$yield.push("x")' and then returns the $yield array).

Thanks for the reply, This seems to be a very nice tool. I will definitely try it out. Though I don't think that I will switch unless debugging is implemented (via source maps) like SharpKit has. This is invaluable to me at times.

Thanks Erik! I haven't touched Script# due to the fact that development stalled and it (was) closed source.

Looking forward to seeing how this performs.

Script# is alive and well AFAIK. It is hosted on github, with about 9 commits from the primary author in the last week.


But all those commits are, unfortunately, tiny. Also the compiler is not open-source only the runtime library (which Saltarelle uses a modified copy of).

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact