Files
2026-02-04 20:27:13 +08:00

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)
}