Skip to content

Instantly share code, notes, and snippets.

@josmardias
Forked from salomvary/settimeout-nashorn.js
Last active August 23, 2023 21:12
Show Gist options
  • Save josmardias/20493bd205e24e31c0a406472330515a to your computer and use it in GitHub Desktop.
Save josmardias/20493bd205e24e31c0a406472330515a to your computer and use it in GitHub Desktop.
setTimeout polyfill for Nashorn
// https://gist.github.com/josmardias/20493bd205e24e31c0a406472330515a
// at least one timeout needs to be set, larger then your code bootstrap
// or Nashorn will run forever
// preferably, put a timeout 0 after your code bootstrap
(function(context) {
'use strict';
var Timer = Java.type('java.util.Timer');
var Phaser = Java.type('java.util.concurrent.Phaser');
var timer = new Timer('jsEventLoop', false);
var phaser = new Phaser();
var timeoutStack = 0;
function pushTimeout() {
timeoutStack++;
}
function popTimeout() {
timeoutStack--;
if (timeoutStack > 0) {
return;
}
timer.cancel();
phaser.forceTermination();
}
var onTaskFinished = function() {
phaser.arriveAndDeregister();
};
context.setTimeout = function(fn, millis /* [, args...] */) {
var args = [].slice.call(arguments, 2, arguments.length);
var phase = phaser.register();
var canceled = false;
timer.schedule(function() {
if (canceled) {
return;
}
try {
fn.apply(context, args);
} catch (e) {
print(e);
} finally {
onTaskFinished();
popTimeout();
}
}, millis);
pushTimeout();
return function() {
onTaskFinished();
canceled = true;
popTimeout();
};
};
context.clearTimeout = function(cancel) {
cancel();
};
context.setInterval = function(fn, delay /* [, args...] */) {
var args = [].slice.call(arguments, 2, arguments.length);
var cancel = null;
var loop = function() {
cancel = context.setTimeout(loop, delay);
fn.apply(context, args);
};
cancel = context.setTimeout(loop, delay);
return function() {
cancel();
};
};
context.clearInterval = function(cancel) {
cancel();
};
})(this);
// (TEST) /usr/java/default/bin/jjs setTimeout-nashorn.js test.js
console.log(1)
t1 = setTimeout(function () {
console.log(4);
}, 300)
console.log(2)
t2 = setTimeout(function () {
console.log(3);
}, 200)
clearTimeout(t1)
// OUTPUT:
// 1
// 2
// 3
// (TEST) /usr/java/default/bin/jjs setTimeout-nashorn.js test2.js
console.log('start')
var i = 0;
t1 = setInterval(function () {
console.log('i-' + ++i);
}, 10)
t2 = setTimeout(function () {
clearInterval(t1)
console.log('end')
}, 100)
// OUTPUT:
// start
// i-1
// i-2
// i-3
// i-4
// i-5
// i-6
// i-7
// i-8
// end
@espen42
Copy link

espen42 commented Mar 1, 2019

Hi! Just wanted to let you know, I'm thinking of using this nice code in my own NPM package (as one of several side dependencies for rendering react from nashorn). I credited you early in the readme. Work in progress: https://www.npmjs.com/package/react4xp-runtime-nashornpolyfills

I'm still a bit new to the ancient ways of open-sourcing, so I hope this sounds okay and everything about the usage looks fine - please let me know if not.

Thanks! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment