# Globals
GraalJS is a pure JavaScript engine. This means that a few Global Objects (which are not standard but common) are missing. ES4X tried to add the missing features or Enhanced the defaults as follows:
# require()
The official spec does not define the function require()
, ES4X has it's own implementation as described in
commonjs.
# setTimeout()
The setTimeout()
method sets a timer which executes a function or specified piece of code once the timer expires.
This method is added to the global scope and uses Vert.x Timers
:
setTimeout(handler => {
console.log('Hello from the future!')
}, 2000);
# setInterval()
The setInterval()
method sets a timer which executes a function or specified piece of code repeatably the timer.
This method is added to the global scope and uses Vert.x Timers
:
setInterval(handler => {
console.log('Hello again from the future!')
}, 2000);
# setImmediate()
The setImmediate()
method executes a function or specified piece of code on the next event loop slot.
This method is added to the global scope and uses Vert.x executeOnContext()
:
setImmediate(handler => {
console.log('Hello again from the future!')
});
# clearTimeout()
Clears a timeout.
# clearInterval()
Clears a timeout.
# clearImmediate()
WARNING
This function is present to ensure many libraries don't break, BUT it has no effect due to the way callbacks are scheduled on the Vert.x Event Loop.
# process Object
The process object (popular by nodejs
) is also available on ES4X, however it has less properties:
{
env, // process environment variables (read only)
pid, // current process id
engine, // constant 'graaljs'
exit, // function that terminates the process with optional error code
nextTick, // enqueue a callback to be executed on the next event loop slot
// NOTE: this behavior is different from nodejs
on, // event emmiter function binding
stdout, // JVM System.out
stderr, // JVM System.err
stdin, // JVM System.in (WARNING this will block the event loop)
properties, // JVM System properties (read, write)
cwd // Function that returns the CWD
}
# console Object
Console is added by ES4X. This object has the typical API:
console.debug('Hello', 'World', '!')
console.info('Hello', 'World', '!')
console.log('Hello', 'World', '!')
console.warn('Hello', 'World', '!')
console.error('Hello', 'World', '!')
Stack traces (both JS and JVM) can be printed with:
try {
throw new Error('durp!')
} catch (e) {
console.trace(e);
}
# Async Error Tracing
Imagine the following piece of code:
function one() {
two(function(err) {
if(err) throw err;
console.log("two finished");
});
}
function two(callback) {
setTimeout(function () {
three(function(err) {
if(err) return callback(err);
console.log("three finished");
callback();
});
}, 0);
}
function three(callback)
{
setTimeout(function () {
four(function(err) {
if(err) return callback(err);
console.log("four finished");
callback();
});
}, 0);
}
function four(callback) {
setTimeout(function(){
callback(new Error());
}, 0);
}
one();
If you run this code you will see that your error has the following trace:
Error
at Timer.callback (example.js:34)
Which is not very useful if you need to debug.
In order to ease this there is a bundled module with ES4X that will stitch your exceptions together, every time you would handle a callback instead of passing the error directly you wrap it with a helper function.
var asyncError = require('async-error');
var fs = vertx.fileSystem();
function one() {
two(function (err) {
if (err) {
console.trace(err);
test.complete();
return;
}
console.log("two finished");
should.fail("Should not reach here");
});
}
function two(callback) {
setTimeout(function () {
three(function (err) {
if (err) {
setTimeout(function () {
callback(asyncError(err));
}, 0);
return;
}
console.log("three finished");
callback();
});
}, 0);
}
function three(callback) {
setTimeout(function () {
four(function (err) {
if (err) {
setTimeout(function () {
callback(asyncError(err));
}, 0);
return;
}
console.log("four finished");
callback();
});
}, 0);
}
function four(callback) {
setTimeout(function () {
fs.readFile("durpa/durp.txt", function (ar) {
if (ar.failed()) {
callback(asyncError(ar));
}
});
}, 0);
}
one();
Knowing that the file durpa/durp.txt
doesn't exist, now you would see:
Error: File not found!
at stacktraces/jserror.js:24:20
at stacktraces/jserror.js:40:20
at stacktraces/jserror.js:53:14
at stacktraces/jserror.js:53:25
at classpath:io/reactiverse/es4x/polyfill/global.js:25:18
If the error that is being propagated in a JS Error
object or:
io.vertx.core.file.FileSystemException: java.nio.file.NoSuchFileException: durpa/durp.txt
at <async>.<anonymous> (stacktraces/index.js:30)
at <async>.<anonymous> (stacktraces/index.js:46)
at <async>.<anonymous> (stacktraces/index.js:61)
at io.vertx.core.file.impl.FileSystemImpl$13.perform(FileSystemImpl.java:740)
at io.vertx.core.file.impl.FileSystemImpl$13.perform(FileSystemImpl.java:732)
at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$1(ContextImpl.java:275)
at io.vertx.core.impl.TaskQueue.run(TaskQueue.java:76)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.nio.file.NoSuchFileException: durpa/durp.txt
at sun.nio.fs.UnixException.translateToIOException(UnixException.java:86)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
at sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:214)
at java.nio.file.Files.newByteChannel(Files.java:361)
at java.nio.file.Files.newByteChannel(Files.java:407)
at java.nio.file.Files.readAllBytes(Files.java:3152)
at io.vertx.core.file.impl.FileSystemImpl$13.perform(FileSystemImpl.java:736)
... 7 more
If the error is a Java Throwable.
# Date
Many APIs from Vert.x return an Instant
as temporal type, in order to use it from JS an helper static function is
added to the Date
object:
let instant = someJVMInstant
let d = Date.fromInstant(instant)
# ArrayBuffer
Array buffers are a builtin type, however if interop is required, then a JVM ByteArray
should be passed to the
constructor and this allows accessing the underlying buffer without copies involved:
let javaBuffer = someJavaBuffer
let b = new ArrayBuffer(javaBuffer)
// the underlying buffer can be read using
b.nioByteBuffer