From 3595294444ef0ad0e41f1a74cf597d4c2911be85 Mon Sep 17 00:00:00 2001 From: MiaoWoo Date: Thu, 27 Feb 2020 18:20:45 +0800 Subject: [PATCH] feat: add normal env task Signed-off-by: MiaoWoo --- packages/ployfill/src/task.ts | 141 ++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 packages/ployfill/src/task.ts diff --git a/packages/ployfill/src/task.ts b/packages/ployfill/src/task.ts new file mode 100644 index 00000000..1dacb917 --- /dev/null +++ b/packages/ployfill/src/task.ts @@ -0,0 +1,141 @@ +(function nashornEventLoopMain(context) { + 'use strict'; + + var Thread = Java.type('java.lang.Thread'); + var Phaser = Java.type('java.util.concurrent.Phaser'); + var ArrayDeque = Java.type('java.util.ArrayDeque'); + var HashMap = Java.type('java.util.HashMap'); + var TimeUnit = Java.type("java.util.concurrent.TimeUnit"); + var Runnable = Java.type('java.lang.Runnable'); + + var globalTimerId; + var timerMap; + var eventLoop; + var phaser = new Phaser(); + + // __NASHORN_POLYFILL_TIMER__ type is ScheduledExecutorService + var scheduler = context.__NASHORN_POLYFILL_TIMER__; + + resetEventLoop(); + + // console.log('main javasript thread ' + Thread.currentThread().getName()); + + function resetEventLoop() { + globalTimerId = 1; + if (timerMap) { + timerMap.forEach(function(key, value) { + value.cancel(true); + }) + } + timerMap = new HashMap(); + eventLoop = new ArrayDeque(); + } + + function waitForMessages() { + phaser.register(); + var wait = !(eventLoop.size() === 0); + phaser.arriveAndDeregister(); + return wait; + } + + function processNextMessages() { + var remaining = 1; + while (remaining) { + phaser.register(); + var message = eventLoop.removeFirst(); + remaining = eventLoop.size(); + phaser.arriveAndDeregister(); + + var fn = message.fn; + var args = message.args; + + try { + fn.apply(context, args); + } catch (e) { + console.trace(e); + console.trace(fn); + console.trace(args); + } + } + } + + context.nashornEventLoop = { + process: function() { + while (waitForMessages()) { + processNextMessages() + } + }, + reset: resetEventLoop + }; + + + function createRunnable(fn, timerId, args, repeated) { + return new Runnable({ + run: function() { + try { + var phase = phaser.register(); + eventLoop.addLast({ + fn: fn, + args: args + }); + } catch (e) { + console.trace(e); + } finally { + if (!repeated) timerMap.remove(timerId); + phaser.arriveAndDeregister(); + } + } + }) + } + + var setTimeout = function(fn, millis /* [, args...] */) { + var args = [].slice.call(arguments, 2, arguments.length); + + var timerId = globalTimerId++; + var runnable = createRunnable(fn, timerId, args, false); + + var task = scheduler.schedule(runnable, millis, TimeUnit.MILLISECONDS); + timerMap.put(timerId, task); + + return timerId; + }; + + var setImmediate = function(fn /* [, args...] */) { + var args = [].slice.call(arguments, 1, arguments.length); + // @ts-ignore + return setTimeout(fn, 0, args); + } + + var clearImmediate = function(timerId) { + clearTimeout(timerId); + } + + var clearTimeout = function(timerId) { + var task = timerMap.get(timerId); + if (task) { + task.cancel(true); + timerMap.remove(timerId); + } + }; + + var setInterval = function(fn, delay /* [, args...] */) { + var args = [].slice.call(arguments, 2, arguments.length); + var timerId = globalTimerId++; + var runnable = createRunnable(fn, timerId, args, true); + var task = scheduler.scheduleWithFixedDelay(runnable, delay, delay, TimeUnit.MILLISECONDS); + timerMap.put(timerId, task); + return timerId; + }; + + var clearInterval = function(timerId) { + clearTimeout(timerId); + }; + + context.setTimeout = setTimeout; + context.clearTimeout = clearTimeout; + context.setImmediate = setImmediate; + context.clearImmediate = clearImmediate; + context.setInterval = setInterval; + context.clearInterval = clearInterval; + // @ts-ignore +})(typeof global !== "undefined" && global || typeof self !== "undefined" && self || this); \ No newline at end of file