-
Notifications
You must be signed in to change notification settings - Fork 21
JSNI: JavaScript Native Interface
Occasionally you may have need to have stricter control of some of the cross-compilation process. In particular, there are various Javascript constructs that are not expressible in C#. Using a helper class called Jsni
(located in System.Runtime.WootzJs
) it is possible to generate Javascript code that would otherwise be impossible using just normal C# syntax. These helpers are grouped into the following kinds:
-
Syntax Helper: An expression type has no analog in C#. Examples include
delete
,for..in
,.apply()
,.call()
,arguments
, regex literals, etc. -
Javascript Overrides: The expression type exists in Javascript, but the syntax has been co-opted to represent the vagaries of the expression type in terms of C#. For example,
new
usually calls the generated$ctor
constructor on the prototype A Javascript override will allow you to use the same syntax but have it expressed as though you were writing Javascript. For the case ofnew
, that means you can generate a nakednew Foo(...)
expression for any expression type representingFoo
. -
Global Functions: Javascript allows global functions; C# does not. Therefore, some global functions such as
parseInt
are accessible here. While these native Javascript implementations of global functions are available to you, they are generally surfaced elsewhere in the BCL. For example,parseInt
is howint.Parse
is implemented. For obvious portability reasons, you should use the BCL version whenever possilble, as it makes it more likely your C# code can be used elsewhere.
####Syntax Helpers####
-
Jsni.regex(pattern[, suffix])
: This allows you to create a Javascript regular expression literal. The result of invoking this method will be the javascript/pattern
(or/pattern/suffix
). -
Jsni.reference(stringliteral)
: Used to reference any arbitary Javascript identifier. The specified identifier is compiled directly into Javascript as an identifier. The specified string MUST be a C# string-literal as the reference must be determined at compile-time. If the expression is not a string literal, the build will fail. -
Jsni.instanceof(obj, type)
: The C#is
operator is implemented entirely using the internal C# type system. If you want to find out in Javascript terms whether an object is an instance of a particular type, then you can use this helper. The C# expressionJsni.instanceof(obj, type)
will generate the Javascriptobj instanceof type
.
####Javascript Overrides####
-
Jsni.new(expression)
: Normally when younew
a class in C#, it will go through several hops, assuming it to be a C# class with a constructor. UsingJsni.new
you can simply generate Javascript that will apply thenew
operator to any 'ol expression. The result ofJsni.new(Jsni.reference("Date"))
would benew Date()
. -
Lambdas: The syntax
x => x.Foo == "bar"
is compiled into a call to a special global function called$delegate
. This is very similar to EcmaScript5'sbind
function (for example, it capturesthis
such that invoking the delegate has athis
that a C# programmer would expect, rather thannull
orwindow
object which would happen otherwise). However, it also loads into the function the requisite data and methods to qualify as a C# delegate. (in addition tothis
, it qualifies as the specific delegate type it represents when interrogated withis
and.GetType()
.) However, if for whatever reason you want to emulate the Javascript syntax ofvar func = function(x, y) { return x + y; }
, you can use the multitude offunction
andprocedure
overloads (forFunc<...>
andAction<...>
respectively) inJsni
to render such a function. For example:The C# syntax:
var func = Jsni.function((x, y) => x + y);
Will generate into:
var func = function(x, y) { return x + y; };
-
Jsni.object(anonymoustypeexpression)
: Normally, when you have C# syntax likenew { Foo = "bar" }
, this anonymous type expression invokes the C#$ctor
for the generated anonymous type implied by the expression. This means the initializer invokes setter methods since the anonymous type is composed of properties. This is exactly what you want when operating within C#. But if you need to express a normal Javascript object literal (the syntactical equivalent to anonymous types) you'll need to use this helper. For example,Jsni.object(new { Foo = "bar" })
will generate to{ Foo: "bar" }
. Similar toJsni.reference
, you must pass an anonymous type expression to this method. Failure to do so will fail the build.
####Global Functions####
-
Jsni.parseInt(integerString)
: Standin for the parseInt() global Javascript function. -
Jsni.parseFloat(floatString)
: Standin for the parseFloat() global Javascript function. -
Jsni.isNaN(number)
: Standin for the isNan() global Javascript function.