-
Notifications
You must be signed in to change notification settings - Fork 21
Technical Design
WootzJs is built using Roslyn, Microsoft's managed compiler that represents the future of the C# compiler. This means we get to enjoy an always up-to-date parser that performs what is by far the most difficult task for creating a C# to Javascript cross-compiler -- converting a C# project into a fully symbolicated suite of syntax trees.
###Transformation### The transformation process is multiphase.
-
All methods with
yield
statements are compiled into iterator classes that implementIEnumerable
andIEnumerator
(and their generic versions if that's what the method returns). This is implemented using a state machine roughly similar to the output of the normal C# compiler. -
All expressions that instantiate new anonymous types are discovered. Their (distinct) types are compiled into Javascript.
-
Each type in the assembly is compiled using a visitor that knows how to convert every (applicable) C# syntax type into Javascript.
###Javascript Composition###
Each C# project is compiled into a single output .js file. The file is composed of several key parts:
-
Strict Mode - The first line of the file is always:
"use strict";
Strict mode makes errors easier to reason about, if for no other reason than that you never want
this
to spontaneously be thewindow
object. -
The next chunk defines the assembly related data. In particular, it creates an array to store all the type functions in the assembly. Also, it creates a function that will lazily create the
System.Reflection.Assembly
instance representing the assembly when using eithertypeof(T)
orAppDomain.CurrentDomain.GetAssemblies()
. This includes all the assembly level attributes you may have in yourAssemblyInfo.cs
file or elsewhere. -
The next section declares all the namespaces defined in your assembly. For example, if you have a namespace such as
namespace MyProduct.MyNamespace { ... }
, the compiler will generate:window.MyProduct = window.MyProduct || {}; MyProduct.MyNamespace = MyProduct.MyNamespace || {};
The namespace objects are created using
||
because assemblies often have at least portions of their namespaces that would otherwise collide with those in other assemblies. -
Finally, each type is sorted based on their dependency graph so that types with few dependencies (such as those that implicitly or explicitly derive from
object
) are placed before types with many dependencies. This ensures that a type's dependencies always come first.