116 lines
2.2 KiB
Go
116 lines
2.2 KiB
Go
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
|
//go:build script
|
|
// +build script
|
|
|
|
package js
|
|
|
|
import (
|
|
"rogchap.com/v8go"
|
|
"sync/atomic"
|
|
)
|
|
|
|
const maxContextsPerIsolate = 8 // TODO 根据系统内存动态调整
|
|
|
|
type Isolate struct {
|
|
rawIsolate *v8go.Isolate
|
|
|
|
contextPool *ContextPool
|
|
countUses uint32
|
|
|
|
isDisposed bool
|
|
}
|
|
|
|
func NewIsolate() (*Isolate, error) {
|
|
return NewIsolateWithContexts(maxContextsPerIsolate)
|
|
}
|
|
|
|
func NewIsolateWithContexts(contextSize int) (*Isolate, error) {
|
|
var isolate = &Isolate{
|
|
rawIsolate: v8go.NewIsolate(),
|
|
contextPool: NewContextPool(contextSize),
|
|
}
|
|
err := isolate.init()
|
|
if err != nil {
|
|
isolate.Dispose()
|
|
return nil, err
|
|
}
|
|
return isolate, nil
|
|
}
|
|
|
|
func (this *Isolate) init() error {
|
|
// 初始化context
|
|
for i := 0; i < this.contextPool.MaxSize(); i++ {
|
|
ctx, err := this.createContext()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
this.contextPool.Put(ctx)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (this *Isolate) OverUses() bool {
|
|
return atomic.LoadUint32(&this.countUses) > 4096
|
|
}
|
|
|
|
func (this *Isolate) GetContext() (*Context, error) {
|
|
atomic.AddUint32(&this.countUses, 1)
|
|
|
|
ctx := this.contextPool.Get()
|
|
if ctx != nil {
|
|
return ctx, nil
|
|
}
|
|
|
|
ctx, err := this.createContext()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return ctx, nil
|
|
}
|
|
|
|
func (this *Isolate) PutContext(ctx *Context) {
|
|
ctx.Done()
|
|
this.contextPool.Put(ctx)
|
|
}
|
|
|
|
func (this *Isolate) Compile(source string, origin string) (*Script, error) {
|
|
script, err := this.rawIsolate.CompileUnboundScript(source, origin, v8go.CompileOptions{
|
|
Mode: v8go.CompileModeDefault,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return NewScript(script), nil
|
|
}
|
|
|
|
func (this *Isolate) ContextPool() *ContextPool {
|
|
return this.contextPool
|
|
}
|
|
|
|
func (this *Isolate) RawIsolate() *v8go.Isolate {
|
|
return this.rawIsolate
|
|
}
|
|
|
|
func (this *Isolate) ThrowException(value *v8go.Value) *v8go.Value {
|
|
return this.rawIsolate.ThrowException(value)
|
|
}
|
|
|
|
func (this *Isolate) IsUsing() bool {
|
|
return this.contextPool.IsUsing()
|
|
}
|
|
|
|
func (this *Isolate) Dispose() {
|
|
if this.isDisposed {
|
|
return
|
|
}
|
|
this.isDisposed = true
|
|
|
|
this.contextPool.Close()
|
|
this.rawIsolate.Dispose()
|
|
}
|
|
|
|
func (this *Isolate) createContext() (*Context, error) {
|
|
return NewContext(v8go.NewContext(this.rawIsolate), this)
|
|
}
|