forked from buke/quickjs-go
/
runtime.go
110 lines (90 loc) · 2.6 KB
/
runtime.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package quickjs
/*
#include "bridge.h"
*/
import "C"
import (
"io"
"time"
)
// Runtime represents a Javascript runtime corresponding to an object heap. Several runtimes can exist at the same time but they cannot exchange objects. Inside a given runtime, no multi-threading is supported.
type Runtime struct {
ref *C.JSRuntime
loop *Loop // only one loop per runtime
}
// NewRuntime creates a new quickjs runtime.
func NewRuntime() Runtime {
rt := Runtime{ref: C.JS_NewRuntime(), loop: NewLoop()}
C.SetModuleLoader(rt.ref)
C.JS_SetCanBlock(rt.ref, C.int(1))
return rt
}
// RunGC will call quickjs's garbage collector.
func (r Runtime) RunGC() {
C.JS_RunGC(r.ref)
}
// Close will free the runtime pointer.
func (r Runtime) Close() {
C.JS_FreeRuntime(r.ref)
}
// SetMemoryLimit the runtime memory limit; if not set, it will be unlimit.
func (r Runtime) SetMemoryLimit(limit uint32) {
C.JS_SetMemoryLimit(r.ref, C.size_t(limit))
}
// SetGCThreshold the runtime's GC threshold; use -1 to disable automatic GC.
func (r Runtime) SetGCThreshold(threshold int64) {
C.JS_SetGCThreshold(r.ref, C.size_t(threshold))
}
// SetMaxStackSize will set max runtime's stack size; default is 255
func (r Runtime) SetMaxStackSize(stack_size uint32) {
C.JS_SetMaxStackSize(r.ref, C.size_t(stack_size))
}
// NewContext creates a new JavaScript context.
// enable BigFloat/BigDecimal support and enable .
// enable operator overloading.
func (r Runtime) NewContext() *Context {
ref := C.JS_NewContext(r.ref)
C.JS_AddIntrinsicBigFloat(ref)
C.JS_AddIntrinsicBigDecimal(ref)
C.JS_AddIntrinsicOperators(ref)
C.JS_EnableBignumExt(ref, C.int(1))
ctx := &Context{ref: ref, runtime: &r, modules: make(map[string][]byte)}
lock.Lock()
contexts[ref] = ctx
lock.Unlock()
return ctx
}
// ExecutePendingJob will execute all pending jobs.
func (r Runtime) ExecutePendingJob() (Context, error) {
var ctx Context
err := C.JS_ExecutePendingJob(r.ref, &ctx.ref)
if err <= 0 {
if err == 0 {
return ctx, io.EOF
}
return ctx, ctx.Exception()
}
return ctx, nil
}
// IsJobPending returns true if there is a pending job.
func (r Runtime) IsJobPending() bool {
return C.JS_IsJobPending(r.ref) == 1
}
// IsLoopJobPending returns true if there is a pending loop job.
func (r Runtime) IsLoopJobPending() bool {
return r.loop.isLoopPending()
}
func (r Runtime) ExecuteAllPendingJobs() error {
var err error
for r.loop.isLoopPending() || r.IsJobPending() {
// execute loop job
r.loop.run()
// excute promiIs
_, err := r.ExecutePendingJob()
if err == io.EOF {
err = nil
}
time.Sleep(time.Millisecond * 1) // prevent 100% CPU
}
return err
}