Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSIL vs Script# vs SharpKit

Tags:

I'm looking at Script#, JSIL and SharpKit as a tool to use to compile C# to Javascript, so I can program the client side functions of AJAX using C# in Visual Studio.

What are the pros and cons of each JSIL, Script# and SharpKit?

My project is a MVC4 project using razor engine and C#, if it matters.

like image 667
Kyle Avatar asked Jul 18 '12 17:07

Kyle


1 Answers

If you're looking to integrate directly with an MVC project, something like Script# or SharpKit or something is probably your best bet - I know for a fact that Script# has stuff built in to make that sort of integration easier, so I would start there.

If you do want to try using JSIL, it probably has the core features you need, but things that you might want - like visual studio integration, automated deployment, etc - are not there. At present it is primarily targeted at cross-compilation of applications, so it does a good job of that but not as good a job of other use cases.

I'll try to give a summary of reasons why you might want to consider JSIL over those other alternatives - I can't really comment on the pros and cons of those alternatives in depth since I haven't used them:


JSIL has extremely wide support for the features available in C# 4. Notable ones (either because other tools don't support them, or they're complicated) include:

dynamic, yield, Structs, ref / out, Delegates, Generics, Nullables, Interfaces, and Enums.

Some of the above, of course, don't have complete support - to get an idea of things that absolutely will work, you can look at the test cases - each one is a small self-contained .cs file that is tested to ensure that JSIL and native C# produce the same output.

The reason for this extensive support is that my goal is for JSIL to enable you to translate a completely unmodified C# application to working JS. For all the demos up on the JSIL site, this is true, and I have a few nearly finished ports of larger real games in the wings for which this is also true.


Another reason is that JSIL makes it relatively straightforward for your C# and your JavaScript to talk.

All your C# types and methods are exposed via an interface that is as javascript-friendly as possible. The JS versions have basic overload resolution and dispatch so that native C# interfaces are callable from script code as if they were native JS in most cases. You don't have to take any steps to specifically tag methods you wish to expose to JS, or give them special names, or anything like that unless you want to.

When you want to call out from C# to JS, you can do it a few ways:

  • JSIL.Verbatim.Expression lets you insert raw javascript directly into the translated version of a function.
  • JSIL.Builtins.Global can be combined with dynamic and var to write JavaScript-like code directly in your C# function bodies.
  • The JSReplacement attribute can be used to replace invocations of a C# function with a parameterized JavaScript expression.
  • All of the above features can be combined with JSIL's mechanism for altering type information, called Proxies, to allow you to alter the type information of libraries you use, even if you don't have source code, in order to map their methods to JavaScript you've written.
  • And finally, C# methods that aren't translated to JS produce an empty method called an External that you can then replace with JavaScript at runtime to make it work again. Any External methods that you haven't replaced produce clear warning message at runtimes so you know what's missing.

JSIL makes aggressive use of type information, along with metadata you provide, to try and safely optimize the JavaScript it generates for you. In some cases this can produce better equivalent JavaScript than you would have written by hand - the main area where this is true at present is code that uses structs, but it also can apply in other cases.

For example, in this code snippet, JSIL is able to statically determine that despite the number of struct copies implied by the code, none of the copies are actually necessary for the code to behave correctly. The resulting JavaScript ends up not having any unnecessary copies, so it runs much faster than what you'd get if you naively translated the semantics of the original C#. This is a nice middle ground between writing the naive struct-based thing (Vector2s everywhere!) and going completely nuts with named return value optimization by hand, which, as I've described in the past, is pretty error-prone.


Okay, now for some downsides. Don't consider this list exhaustive:

  • Large portions of the .NET BCL don't have implementations provided for you by JSIL. In the future this may be addressed by translating the entire Mono mscorlib to JavaScript, but I don't have that working well enough to advocate it as an immediate solution. (This is fine for games so far, since they don't use much of the BCL.) This issue is primarily due to the IP problems related to translating Microsoft's mscorlib - if I could do that legally, I'd be doing it right now - it worked the last time I tested it.
  • As mentioned above, no visual studio integration. JSIL is pretty easy to use - you can feed it a .sln file to get a bunch of .js outputs automatically, and configure it automatically with a configuration file next to the project - but it's nowhere near as polished or integrated as say, Script#.
  • No vendor or support staff. If you want a bug fixed yesterday or you're having issues, I'm pretty much your only bet at present (though there are a few prolific contributors helping make things better, and more are always welcome!)
  • JavaScript performance is a goddamn labyrinth full of invisible land mines. If you just want apps to work, you probably won't have any issues here, but if like me you're trying to make real games run fast in browsers, JavaScript will make your life hell and in some cases JSIL will make it worse. The only good thing I can say here is that I'm working on it. :)
  • JavaScript minifiers and optimizers like Closure are explicitly not supported, because they require your code generator to jump through a bunch of hoops. I could see this being a real blocker depending on how you intend to use your code.
  • The static analyzer is still kind of fragile and there are still gaps in the language support. Each big application I port using JSIL usually reveals one or two bugs in JSIL - not huge game breakers, but ones that definitely break a feature or make things run slow.

Hope this information is helpful! Thanks for your interest.

like image 128
Katelyn Gadd Avatar answered Oct 01 '22 01:10

Katelyn Gadd