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