Datatype Mapping

Introduction

Julia is strongly typed while JavaScript is loosely typed, and so care must be taken to best define rules for moving data between the two languages. There are two considerations.

  1. How to identify the most efficient type for a new variable and mechanism for its creation.
  2. How to avoid unnecessary object creation.

From JavaScript to Julia

Since Julia derives a good deal of its efficiency by being able to pass typing information to LLVM, as much typing information as possible is passed from JavaScript. Not only is the source type taken into consideration, but the value as well.

From JavaScript Primitive Types

JavaScript TypeJavaScript ValueJulia Type
nullnullVoid
Booleantrue or falseBool
NumberintegerInt64
Numbernot an integerFloat64
StringASCII or UTF8UTF8String
DateDateDateTime*
RegExpJavascipt regular expressionRegex

Date to DateTime*

Support for automatic conversion from Javascript's Date to Julia's DateTime has been added, however, the type DateTime was only added to Julia base in version 0.4, and so this feature is currently only supported when node-julia is installed against that version of Julia.

RegExp to Regex

Javascript regular expressions are converted to Julia regular expressions. The format of Javascript regex and Julia regex are similar but not exactly the same, though they are both based on PCRE. But although the format is different, the type of the constructing argument pattern is String which is passed exactly as specified.

From JavaScript Arrays

Passing JavaScript arrays to Julia presents a special problem. Because JavaScript does not differentiate arrays based on the type of the elements they contain, any sort of typing that Julia needs for optimizing would have to be inferred. Also, JavaScript multidimensional arrays are structured as arrays of arrays unlike Julia which again makes JavaScript arrays inefficient by comparison and conversion to equivalent Julia arrays tedious. And finally, if anything, JavaScript arrays are structured row-major while Julia arrays are column major.

Arrays passed to Julia are assumed to be regular.

Currently it is an error if the source array is irregular. To enforce this, the source array is examined, and if it is multidimensional, then all sibling arrays must have the same dimensions. For example this is a valid way to take the transpose of a 2x3 array

res = julia.exec('transpose',[[ 1, 2, 3 ], [ 4, 5, 6 ]]);
console.log('transpose is ',res);

which produces the following output

transpose is  [ { '0': 1, '1': 4 }, { '0': 2, '1': 5 }, { '0': 3, '1': 6 } ]

however, this is an error

console.log('transpose is ',julia.exec('transpose',[[ 1, 2, 3 ], [ 4, 5 ]]));

and produces the following exception

console.log('transpose is ',julia.exec('transpose',[[ 1, 2, 3 ], [ 4, 5 ]]));
                                  ^
Error: Malformed input array
    at Error (native)
    

since [ 1, 2, 3 ] has different length (3) than [ 4, 5 ] (2).

Arrays are assumed to be homogeneous.

Julia requires that the type of an array includes the element type and since Julia uses this information to select the method, and assuming the narrowest type will likely give rise to the most efficient method, the most narrow type is selected from all the elements as the Julia element type where Boolean is narrower than Integer is narrower than Number. In the case of Boolean appearing in array with Number, false is mapped to 0 and true is mapped to 1. It is currently an error for String to appear with anything other than String.

Type Any currently not supported.

Julia does all allow for heterogeneous Arrays by defining the umbrella type Any which is implicitly slow as the type must accompany the value. Thus this option is currently not available, but will be in an upcoming release.

Arrays of null

Arrays of null values are also allowed but share the same property as String; they can only exist alongside other null elements. Each element is mapped to the Julia value nothing.

Arrays of Native Arrays

To support speedy multidimensional arrays, mixed use of arrays and NativeArrays are allowed. The ultimate type will of this combination will be determined using homogeneity rules above see Buffer and Native Arrays for more information.

From Julia to JavaScript

This direction is easier to define since Julia types are more specific than those of JavaScript.

From Julia

The table below shows how the following Julia types are mapped to their corresponding JavaScript types.

Julia TypeJavaScript Type
Voidnull
BoolBoolean
Int8, Uint8, Int16, UInt16, Int32, UInt32Number
Float32, Float64Number
Int64, UInt64Number**
ASCIIString,UTF8StringString
SubStringString
DateTime*Date
RegexRegExp
DatatypeJRef***

Julia Int64 and UInt64 will be mapped to Number **

Julia Int64 and Uint64 will be mapped to Number but for numbers larger than 9007199254740992, there will be loss of precision since JavaScript Numbers are internally represented using double.

Other Julia Datatypes Mapped to JRef ***

Beyond the basic mapping, Julia composites are retuned as JRefs which are an opaque type that can be passed back to Julia as arguments to eval, exec, and Script.exec, see JRef ] for more information.

From Julia Arrays

JavaScript NativeArrays are used whenever possible. Thus when the Julia return type is an array of Integer or Float, even if multidimensional, the result will contain NativeArrays as the most derived children. This support is paired with allowing arrays of NativeArrays as input.