monflabs-jsplayground-pre v0.0.4
JsonScript
JsonScript is a language designed to run scripts and manipulate JSON data. It is heavily inspired by JavaScript but it is not not JavaScript. It is designed to integrate well with the underlying platform, which is here Java and the JVM.
Goals and non Goals
- Create a script language that is tighly integrated with the underlying platform. Make this language easy to use for both Java and JavaScript developers.
- Create a language designed to run large, long running programs.
Rather, it is a scripting language used to automate tasks in the underlying platform. For that reason, it doesn't feature modules or classes. Create a 100% compatible JavaScript interpreter. There are several available like Nashorn, Rhino, GraalVM or ES6Draft, just to name the major ones.
Differences With JavaScript
Types
Primitives vs Objects
JsonScript does not make a difference between primitive types and Objects, like in JavaScript. Therefore, everything is an object but certain objects, namely String, Number or Boolean also behave like primitives. This introduces some minor changes compared to JavaScript:
"a string"
andnew String("a string")
are identical.
Actually,new String(s)
returnss
.
Global Java identifiers
The java library makes the following globals, representing java classes or primitive types:
char
byte
short
int
long
float
double
boolean
String
BigInteger
BigDecimal
List
Map
Object
Array
Java
undefined and null, and NULL
undefined
does not exist in JsonScript, mainly because it does not exist in Java. It only handles the null
value.
Now, to efficiently deal with JSON access, we introduce a new null value called NULL
. Semantically, it works like null
but it propagates when accessing members, instead of raising a NullPointerException.
const n1 = null;
n1.a; // -> throws exception
const n2 = NULL;
n2.a; // -> resolves to NULL (propagated)
Currently, the NULL value is only returned by Array and Object when a member does not exist.
const o = {}
o.a; // -> NULL
o.a.b; // ->NULL
Type coercion
JsonScript enforces that the right types are used and doesn't do coercion, like automatically transforming values to String
or Number
. It throws errors when the right type is not used. For example, mysstring.charAt("2") fails as the string "2"
is not automatically converted to the number 2
, and thus generates an error.
It also validates the arguments with the method signature so mysstring.charAt()
and mysstring.charAt(1,2)
will both fail because the signature of the method is charAt(pos: int)
.
Use of prototypes
Prototypes methods are meant to be used for the types they are designed for, and they do not try to convert the argument to that type.
String.prototype.charAt.call( 123456, 1 ) will fail instead of returning 2.
Numbers
Numbers are real java numbers, inheriting from Number
. Internally, the script engine uses Integer
, Long
, Double
and even BigInteger
or BigDecimal
. This can affect the result of computations.
new
The new
operator works a bit differently from JavaScript to better target Java classes. The syntaxe is:new <expr>(<args>)
or for arrays:new <expr>[][<size>]
<expr>
is a a simple expr of the form name[.member ...]
. A typical use is the following:
const MyClass = Java.type("my.package.MyClass")
var o = new MyClass()
Note that new a.b()
doesn't reference the java class a.b
, but the member b
of the identifier a
.
String handling
Supports a subset of ES6 template strings: ${expressions}
within a back-ticked string. It does not support tagged strings.
Ex: `My name is ${NAME}
`
Dealing with JSON containers (Array and Object)
JsonScript maps the class Object
to Java JsonObject and Array
Java JsonArray. They are not meant to be generic maps of lists, but to deal with JSON data. To use more generic container, with a regular behavior, use Map
(maps to Java LinkedHashMap) or List
(maps Java ArrayList).
JsonScript also introduces the notion of a sequence. A sequence is used when querying an Array
or an Object
returns multiple values.
<<< TODO explain here >>>
Here is how operators work with Array:
.
or[]
When accessing a member of anArray
, the runtime browses the array content and accesses the member of each these entry in a sequence.
When an object or an array is accessed using[]
or.
, it always returns the value in the maps(s) and never the corresponding function. With one exception: when using the operator.
and when the member is immediately followed by a call()
:myobject.toString
ormyobject['toString']
return thetoString
value, ornull
myobject.toString()
calls the actualtoString()
method of the container
.*
or[*]
Return all the values of the left part flattenized...
Search for member through all the tree and return a sequence.- Sequence handling.
When a sequence is deferenced, when used in a expression, it is first dereferenced using the following pattern:- An empty sequence generates the
null
value. - A sequence containing one value generates this value
- A sequence containing multiple values generated an Array with all these values
- An empty sequence generates the
const a0 = []
const r0 = a0['a'] // Returns null
const a1 = [{ a: '1' }]
const r1 = a1['a'] // Returns '1'
const a2 = [{ a: '1' }, { a: '2' }]
const r2 = a2['a'] // Returns ['1','2']
Now, there is an ambiguity between the array content and the functions when accessed by name. For both JsonArray
& JsonObject
, the language distinguishes the functions from the object members when they are called right away:
container.memb // accesses the member 'memb'of the container
container.func() // accesses the function 'func' and calls it.
Exceptions are Java exceptions
JsonScript deals with native exceptions
with() statement
JsonScript supports the with()
statement, but its runtime behavior is different: the accessed members must be preceeded by a leading ".", like this:
const anObject = new MyObject()
with(anObject) {
console.log(.m()); // .m() is eqv to o anObject.m
}
with()
actually sets a context that is similar to the JsonArray
Standard Library
The standard library more or less mimics the standard JavaScript one for the JSON values (JsonObject, JsonArray, Number, Boolean, String, null). It is not a full emulation, but it keeps what makes sense in a non JavaScript environment, while some uncommon functions are not implemented.
console
log
& error
are implemented. When the first parameter is a message, then it is a Java String format, which is more complete than the JavaScript one.
JSON
parse(obj,reviver)
The reviver function must be null, else it generates an exception
JSON.stringify(obj,replacer,space)
The replacer function must be null, else it generates an exception
Toolbox For Salesforce Developers
Install: https://www.jdeploy.com/~monflabs-jsplayground
Publish:
1- Maven build.
2- Build and deploy package.
npx jdeploy package
npm publish