feat: support full nodejs event loop
Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
parent
4bb2337f39
commit
f31726e98b
@ -158,12 +158,14 @@ export class MiaoScriptConsole implements Console {
|
|||||||
var { fileName, lineNumber } = this.readSourceMap(trace.fileName, trace.lineNumber)
|
var { fileName, lineNumber } = this.readSourceMap(trace.fileName, trace.lineNumber)
|
||||||
if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] }
|
if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] }
|
||||||
} else {
|
} else {
|
||||||
|
if (!global.debug) {
|
||||||
for (let prefix in ignoreLogPrefix) {
|
for (let prefix in ignoreLogPrefix) {
|
||||||
if (className.startsWith(ignoreLogPrefix[prefix])) {
|
if (className.startsWith(ignoreLogPrefix[prefix])) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (color) {
|
if (color) {
|
||||||
cache.push(` §e->§c ${className}.${trace.methodName}(§4${fileName}:${lineNumber}§c)`)
|
cache.push(` §e->§c ${className}.${trace.methodName}(§4${fileName}:${lineNumber}§c)`)
|
||||||
} else {
|
} else {
|
||||||
|
@ -67,6 +67,7 @@ declare global {
|
|||||||
interface Core {
|
interface Core {
|
||||||
getClass(name: String): any
|
getClass(name: String): any
|
||||||
getProxyClass(): any
|
getProxyClass(): any
|
||||||
|
getJavaScriptTaskClass(): any
|
||||||
getInstance(): any
|
getInstance(): any
|
||||||
read(path: string): string
|
read(path: string): string
|
||||||
save(path: string, content: string): void
|
save(path: string, content: string): void
|
||||||
|
@ -5,13 +5,15 @@ const ThreadGroup = Java.type("java.lang.ThreadGroup")
|
|||||||
const AtomicInteger = Java.type("java.util.concurrent.atomic.AtomicInteger")
|
const AtomicInteger = Java.type("java.util.concurrent.atomic.AtomicInteger")
|
||||||
const ThreadPoolExecutor = Java.type('java.util.concurrent.ThreadPoolExecutor')
|
const ThreadPoolExecutor = Java.type('java.util.concurrent.ThreadPoolExecutor')
|
||||||
const LinkedBlockingQueue = Java.type("java.util.concurrent.LinkedBlockingQueue")
|
const LinkedBlockingQueue = Java.type("java.util.concurrent.LinkedBlockingQueue")
|
||||||
const TimeUnit = Java.type("java.util.concurrent.TimeUnit")
|
const TimeUnit = Java.type('java.util.concurrent.TimeUnit')
|
||||||
|
const DelayQueue = Java.type('java.util.concurrent.DelayQueue')
|
||||||
|
const JavaScriptTask = Java.type(base.getJavaScriptTaskClass().name)
|
||||||
|
|
||||||
const threadCount = new AtomicInteger(0)
|
const threadCount = new AtomicInteger(0)
|
||||||
const threadGroup = new ThreadGroup("@ccms/ployfill-micro-task")
|
const threadGroup = new ThreadGroup("@ccms/ployfill-micro-task")
|
||||||
const microTaskPool = new ThreadPoolExecutor(
|
const microTaskPool = new ThreadPoolExecutor(
|
||||||
10, 100, 60, Packages.java.util.concurrent.TimeUnit.SECONDS,
|
100, 200, 60, Packages.java.util.concurrent.TimeUnit.SECONDS,
|
||||||
new LinkedBlockingQueue(500),
|
new LinkedBlockingQueue(300),
|
||||||
(run: any) => new Thread(threadGroup, run, "@ccms/micro-task-" + threadCount.incrementAndGet()),
|
(run: any) => new Thread(threadGroup, run, "@ccms/micro-task-" + threadCount.incrementAndGet()),
|
||||||
new ThreadPoolExecutor.CallerRunsPolicy()
|
new ThreadPoolExecutor.CallerRunsPolicy()
|
||||||
)
|
)
|
||||||
@ -38,52 +40,105 @@ class Process extends EventEmitter {
|
|||||||
nextTick(func: Function) {
|
nextTick(func: Function) {
|
||||||
microTaskPool.execute(func)
|
microTaskPool.execute(func)
|
||||||
}
|
}
|
||||||
queueMicrotask(func: Function) {
|
|
||||||
microTaskPool.execute(func)
|
|
||||||
}
|
|
||||||
exit(code: number) {
|
exit(code: number) {
|
||||||
process.emit('exit', code)
|
process.emit('exit', code)
|
||||||
microTaskPool.shutdown()
|
microTaskPool.shutdown()
|
||||||
console.log('await microTaskPool termination...')
|
console.log('process exit await microTaskPool termination...')
|
||||||
microTaskPool.awaitTermination(5000, TimeUnit.MILLISECONDS)
|
microTaskPool.awaitTermination(5000, TimeUnit.MILLISECONDS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const timeoutCount = new AtomicInteger(0)
|
|
||||||
const timeoutTasks = []
|
class EventLoop {
|
||||||
function setTimeout(func: Function, time: number, ...args: any[]) {
|
private eventLoopMainThread = undefined
|
||||||
let taskId = timeoutCount.incrementAndGet()
|
private eventLoopTaskQueue = new DelayQueue()
|
||||||
timeoutTasks[taskId] = func
|
|
||||||
process.nextTick(() => {
|
constructor() {
|
||||||
Thread.sleep(time)
|
this.eventLoopMainThread = new Thread(() => {
|
||||||
if (timeoutTasks[taskId]) { func(...args) }
|
let task = undefined
|
||||||
})
|
try {
|
||||||
|
while ((task = this.eventLoopTaskQueue.take()) != undefined) {
|
||||||
|
try {
|
||||||
|
task.getTask()()
|
||||||
|
} catch (error) {
|
||||||
|
try {
|
||||||
|
process.emit('error', error)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
console.ex(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`EventLoop Thread isInterrupted exit! remainTask: ${this.eventLoopTaskQueue.size()}`)
|
||||||
|
this.eventLoopTaskQueue.clear()
|
||||||
|
this.eventLoopTaskQueue = undefined
|
||||||
|
this.timeoutCount = undefined
|
||||||
|
this.timeoutTasks = undefined
|
||||||
|
this.intervalCount = undefined
|
||||||
|
this.intervalTasks = undefined
|
||||||
|
this.eventLoopMainThread = undefined
|
||||||
|
}
|
||||||
|
}, "@ccms/node-shim/event-loop")
|
||||||
|
this.eventLoopMainThread.setDaemon(true)
|
||||||
|
process.on('exit', () => this.eventLoopMainThread.interrupt())
|
||||||
|
}
|
||||||
|
|
||||||
|
startEventLoop() {
|
||||||
|
this.eventLoopMainThread.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
private putDelayTask(callback: Function, ms: number) {
|
||||||
|
this.eventLoopTaskQueue.put(new JavaScriptTask(callback, ms))
|
||||||
|
}
|
||||||
|
|
||||||
|
private timeoutCount = new AtomicInteger(0)
|
||||||
|
private timeoutTasks = []
|
||||||
|
setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]) {
|
||||||
|
let taskId = this.timeoutCount.incrementAndGet()
|
||||||
|
this.timeoutTasks[taskId] = callback
|
||||||
|
console.trace(`create setTimeout task ${taskId} => ${callback}`)
|
||||||
|
this.putDelayTask(() => {
|
||||||
|
if (this.timeoutTasks[taskId]) {
|
||||||
|
callback(...args)
|
||||||
|
} else {
|
||||||
|
console.trace(`ignore setTimeout ${ms}ms task ${taskId} because it's cancelled!`)
|
||||||
|
}
|
||||||
|
}, ms)
|
||||||
return taskId
|
return taskId
|
||||||
}
|
}
|
||||||
function clearTimeout(taskId: number) {
|
clearTimeout(taskId: number) {
|
||||||
delete timeoutTasks[taskId]
|
delete this.timeoutTasks[taskId]
|
||||||
}
|
}
|
||||||
const intervalCount = new AtomicInteger(0)
|
|
||||||
const intervalTasks = []
|
private intervalCount = new AtomicInteger(0)
|
||||||
function setInterval(func: Function, time: number, ...args: any[]) {
|
private intervalTasks = []
|
||||||
let taskId = intervalCount.incrementAndGet()
|
setInterval(callback: (...args: any[]) => void, ms: number, ...args: any[]) {
|
||||||
intervalTasks[taskId] = func
|
let taskId = this.intervalCount.incrementAndGet()
|
||||||
process.nextTick(() => {
|
this.intervalTasks[taskId] = callback
|
||||||
Thread.sleep(time)
|
console.trace(`create setInterval ${ms}ms task ${taskId} => ${callback}`)
|
||||||
while (intervalTasks[taskId]) {
|
let intervalTask = () => {
|
||||||
func(...args)
|
if (this.intervalTasks[taskId]) {
|
||||||
Thread.sleep(time)
|
callback(...args)
|
||||||
|
this.putDelayTask(intervalTask, ms)
|
||||||
|
} else {
|
||||||
|
console.trace(`ignore setInterval task ${taskId} because it's cancelled!`)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
this.putDelayTask(intervalTask, ms)
|
||||||
return taskId
|
return taskId
|
||||||
}
|
}
|
||||||
function clearInterval(taskId: number) {
|
clearInterval(taskId: number) {
|
||||||
delete intervalTasks[taskId]
|
delete this.intervalTasks[taskId]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
global.setGlobal('process', new Process(), {})
|
global.setGlobal('process', new Process(), {})
|
||||||
|
const eventLoop = new EventLoop()
|
||||||
|
global.setGlobal('eventLoop', eventLoop, {})
|
||||||
|
eventLoop.startEventLoop()
|
||||||
global.setGlobal('queueMicrotask', (func: any) => microTaskPool.execute(func), {})
|
global.setGlobal('queueMicrotask', (func: any) => microTaskPool.execute(func), {})
|
||||||
global.setGlobal('setTimeout', setTimeout, {})
|
global.setGlobal('setTimeout', eventLoop.setTimeout.bind(eventLoop), {})
|
||||||
global.setGlobal('clearTimeout', clearTimeout, {})
|
global.setGlobal('clearTimeout', eventLoop.clearTimeout.bind(eventLoop), {})
|
||||||
global.setGlobal('setImmediate', (func: Function, ...args: any[]) => setTimeout(func, 0, ...args), {})
|
global.setGlobal('setImmediate', (callback: (...args: any[]) => void, ...args: any[]) => eventLoop.setTimeout(callback, 0, ...args), {})
|
||||||
global.setGlobal('clearImmediate ', clearTimeout, {})
|
global.setGlobal('clearImmediate ', eventLoop.clearTimeout.bind(eventLoop), {})
|
||||||
global.setGlobal('setInterval', setInterval, {})
|
global.setGlobal('setInterval', eventLoop.setInterval.bind(eventLoop), {})
|
||||||
global.setGlobal('clearInterval', clearInterval, {})
|
global.setGlobal('clearInterval', eventLoop.clearInterval.bind(eventLoop), {})
|
||||||
|
Loading…
Reference in New Issue
Block a user