diff --git a/context.go b/context.go index b5cef21e4..d15adc84d 100644 --- a/context.go +++ b/context.go @@ -71,7 +71,7 @@ func NewContext(opt ...ContextOption) *Context { if createParams != nil && createParams.startupData != nil { ctx = &Context{ ref: ref, - ptr: C.NewContextFromSnapShot(opts.iso.ptr, createParams.startupData.ptr.index, C.int(ref)), + ptr: C.NewContextFromSnapShot(opts.iso.ptr, createParams.startupData.index, C.int(ref)), iso: opts.iso, } } else { diff --git a/isolate.go b/isolate.go index 51b06a407..be14b7dd3 100644 --- a/isolate.go +++ b/isolate.go @@ -73,18 +73,16 @@ func NewIsolate(opts ...createOptions) *Isolate { opt(params) } - var iso *Isolate + var cOptions C.IsolateOptions + if params.startupData != nil { - iso = &Isolate{ - ptr: C.NewIsolateWithCreateParams(params.startupData.ptr), - cbs: make(map[int]FunctionCallback), - createParams: params, - } - } else { - iso = &Isolate{ - ptr: C.NewIsolate(), - cbs: make(map[int]FunctionCallback), - } + cOptions.snapshot_blob = params.startupData.ptr + } + + iso := &Isolate{ + ptr: C.NewIsolate(cOptions), + cbs: make(map[int]FunctionCallback), + createParams: params, } iso.null = newValueNull(iso) iso.undefined = newValueUndefined(iso) diff --git a/snapshot_creator.go b/snapshot_creator.go index ee9a37905..777a3835d 100644 --- a/snapshot_creator.go +++ b/snapshot_creator.go @@ -9,7 +9,6 @@ package v8go import "C" import ( "errors" - "unsafe" ) type FunctionCodeHandling int @@ -20,7 +19,8 @@ const ( ) type StartupData struct { - ptr *C.SnapshotBlob + ptr *C.RtnSnapshotBlob + index C.size_t } func (s *StartupData) Dispose() { @@ -29,69 +29,57 @@ func (s *StartupData) Dispose() { } } -type snapshotCreatorOptions struct { - iso *Isolate - exitingBlob *StartupData -} - -type creatorOptions func(*snapshotCreatorOptions) - -func WithIsolate(iso *Isolate) creatorOptions { - return func(options *snapshotCreatorOptions) { - options.iso = iso - } -} - type SnapshotCreator struct { - ptr C.SnapshotCreatorPtr - *snapshotCreatorOptions + ptr C.SnapshotCreatorPtr + iso *Isolate + ctx *Context + index C.size_t } -func NewSnapshotCreator(opts ...creatorOptions) *SnapshotCreator { +func NewSnapshotCreator() *SnapshotCreator { v8once.Do(func() { C.Init() }) - options := &snapshotCreatorOptions{} - for _, opt := range opts { - opt(options) - } - - var cOptions C.SnapshotCreatorOptions + rtn := C.NewSnapshotCreator() - if options.iso != nil { - cOptions.iso = options.iso.ptr + return &SnapshotCreator{ + ptr: rtn.creator, + iso: &Isolate{ptr: rtn.iso}, } +} - return &SnapshotCreator{ - ptr: C.NewSnapshotCreator(cOptions), - snapshotCreatorOptions: options, +func (s *SnapshotCreator) GetIsolate() (*Isolate, error) { + if s.ptr == nil { + return nil, errors.New("v8go: Cannot get Isolate after creating the blob") } + + return s.iso, nil } -func (s *SnapshotCreator) Create(source, origin string, functionCode FunctionCodeHandling) (*StartupData, error) { +func (s *SnapshotCreator) AddContext(ctx *Context) error { if s.ptr == nil { - return nil, errors.New("v8go: Cannot use snapshot creator after creating the blob") + return errors.New("v8go: Cannot add context to snapshot creator after creating the blob") } - cSource := C.CString(source) - cOrigin := C.CString(origin) - defer C.free(unsafe.Pointer(cSource)) - defer C.free(unsafe.Pointer(cOrigin)) + s.index = C.AddContext(s.ptr, ctx.ptr) + s.ctx = ctx - rtn := C.CreateSnapshot(s.ptr, cSource, cOrigin, C.int(functionCode)) + return nil +} - if rtn.blob == nil { - return nil, newJSError(rtn.error) +func (s *SnapshotCreator) Create(functionCode FunctionCodeHandling) (*StartupData, error) { + if s.ptr == nil { + return nil, errors.New("v8go: Cannot use snapshot creator after creating the blob") } - s.ptr = nil + rtn := C.CreateBlob(s.ptr, s.ctx.ptr, C.int(functionCode)) - if s.snapshotCreatorOptions.iso != nil { - s.snapshotCreatorOptions.iso.ptr = nil - } + s.ptr = nil + s.ctx.ptr = nil + s.iso.ptr = nil - return &StartupData{ptr: rtn.blob}, nil + return &StartupData{ptr: rtn, index: s.index}, nil } func (s *SnapshotCreator) Dispose() { diff --git a/snapshot_creator_test.go b/snapshot_creator_test.go index de19321f0..20e1e5b5f 100644 --- a/snapshot_creator_test.go +++ b/snapshot_creator_test.go @@ -12,13 +12,23 @@ import ( func TestCreateSnapshot(t *testing.T) { snapshotCreator := v8.NewSnapshotCreator() + snapshotCreatorIso, err := snapshotCreator.GetIsolate() + fatalIf(t, err) + + snapshotCreatorCtx := v8.NewContext(snapshotCreatorIso) + defer snapshotCreatorCtx.Close() - data, err := snapshotCreator.Create("function run() { return 1 };", "script.js", v8.FunctionCodeHandlingKlear) + snapshotCreatorCtx.RunScript(`const add = (a, b) => a + b`, "add.js") + snapshotCreatorCtx.RunScript(`function run() { return add(3, 4); }`, "main.js") + err = snapshotCreator.AddContext(snapshotCreatorCtx) fatalIf(t, err) + data, err := snapshotCreator.Create(v8.FunctionCodeHandlingKlear) + fatalIf(t, err) + defer data.Dispose() + iso := v8.NewIsolate(v8.WithStartupData(data)) defer iso.Dispose() - defer data.Dispose() ctx := v8.NewContext(iso) defer ctx.Close() @@ -36,98 +46,39 @@ func TestCreateSnapshot(t *testing.T) { if err != nil { panic(err) } - if val.String() != "1" { + if val.String() != "7" { t.Fatal("invalid val") } } func TestCreateSnapshotErrorAfterSuccessfullCreate(t *testing.T) { snapshotCreator := v8.NewSnapshotCreator() + snapshotCreatorIso, err := snapshotCreator.GetIsolate() + fatalIf(t, err) + snapshotCreatorCtx := v8.NewContext(snapshotCreatorIso) + defer snapshotCreatorCtx.Close() - data, err := snapshotCreator.Create("function run() { return 1 };", "script.js", v8.FunctionCodeHandlingKlear) - defer data.Dispose() + snapshotCreatorCtx.RunScript(`const add = (a, b) => a + b`, "add.js") + snapshotCreatorCtx.RunScript(`function run() { return add(3, 4); }`, "main.js") + err = snapshotCreator.AddContext(snapshotCreatorCtx) + fatalIf(t, err) + + data, err := snapshotCreator.Create(v8.FunctionCodeHandlingKlear) fatalIf(t, err) + defer data.Dispose() - _, err = snapshotCreator.Create("function run2() { return 2 };", "script2.js", v8.FunctionCodeHandlingKlear) + _, err = snapshotCreator.GetIsolate() if err == nil { - t.Error("Creating snapshot should have fail") + t.Error("Getting Isolate should have fail") } -} -func TestCreateSnapshotFail(t *testing.T) { - snapshotCreator := v8.NewSnapshotCreator() - defer snapshotCreator.Dispose() - - _, err := snapshotCreator.Create("uidygwuiwgduw", "script.js", v8.FunctionCodeHandlingKlear) + err = snapshotCreator.AddContext(snapshotCreatorCtx) if err == nil { - t.Error("Creating snapshot should have fail") + t.Error("Adding context should have fail") } -} -func TestCreateSnapshotFailAndReuse(t *testing.T) { - snapshotCreator := v8.NewSnapshotCreator() - _, err := snapshotCreator.Create("uidygwuiwgduw", "script.js", v8.FunctionCodeHandlingKlear) + _, err = snapshotCreator.Create(v8.FunctionCodeHandlingKlear) if err == nil { t.Error("Creating snapshot should have fail") } - - data, err := snapshotCreator.Create("function run() { return 1 };", "script.js", v8.FunctionCodeHandlingKlear) - fatalIf(t, err) - - iso := v8.NewIsolate(v8.WithStartupData(data)) - defer iso.Dispose() - defer data.Dispose() - - ctx := v8.NewContext(iso) - defer ctx.Close() - - runVal, err := ctx.Global().Get("run") - if err != nil { - panic(err) - } - - fn, err := runVal.AsFunction() - if err != nil { - panic(err) - } - val, err := fn.Call(v8.Undefined(iso)) - if err != nil { - panic(err) - } - if val.String() != "1" { - t.Fatal("invalid val") - } -} - -func TestCreateSnapshotWithIsolateOption(t *testing.T) { - iso1 := v8.NewIsolate() - defer iso1.Dispose() - snapshotCreator := v8.NewSnapshotCreator(v8.WithIsolate(iso1)) - - data, err := snapshotCreator.Create("function run() { return 1 };", "script.js", v8.FunctionCodeHandlingKlear) - fatalIf(t, err) - - iso := v8.NewIsolate(v8.WithStartupData(data)) - defer iso.Dispose() - defer data.Dispose() - - ctx := v8.NewContext(iso) - defer ctx.Close() - - runVal, err := ctx.Global().Get("run") - if err != nil { - panic(err) - } - - fn, err := runVal.AsFunction() - if err != nil { - panic(err) - } - val, err := fn.Call(v8.Undefined(iso)) - if err != nil { - panic(err) - } - if val.String() != "1" { - t.Fatal("invalid val") - } } diff --git a/v8go.cc b/v8go.cc index bfc63de0d..c2fbb9b51 100644 --- a/v8go.cc +++ b/v8go.cc @@ -153,34 +153,19 @@ void Init() { return; } -IsolatePtr NewIsolateWithCreateParams(SnapshotBlob* snapshot_blob) { +IsolatePtr NewIsolate(IsolateOptions options) { Isolate::CreateParams params; - - StartupData* startup_data = - new StartupData{snapshot_blob->data, snapshot_blob->raw_size}; - - params.snapshot_blob = startup_data; params.array_buffer_allocator = default_allocator; - Isolate* iso = Isolate::New(params); - Locker locker(iso); - Isolate::Scope isolate_scope(iso); - HandleScope handle_scope(iso); - - iso->SetCaptureStackTraceForUncaughtExceptions(true); - - // Create a Context for internal use - m_ctx* ctx = new m_ctx; - ctx->ptr.Reset(iso, Context::New(iso)); - ctx->iso = iso; - ctx->startup_data = startup_data; - iso->SetData(0, ctx); - return iso; -} + StartupData* startup_data; + if (options.snapshot_blob != nullptr) { + startup_data = new StartupData{options.snapshot_blob->data, + options.snapshot_blob->raw_size}; + params.snapshot_blob = startup_data; + } else { + startup_data = nullptr; + } -IsolatePtr NewIsolate() { - Isolate::CreateParams params; - params.array_buffer_allocator = default_allocator; Isolate* iso = Isolate::New(params); Locker locker(iso); Isolate::Scope isolate_scope(iso); @@ -192,7 +177,7 @@ IsolatePtr NewIsolate() { m_ctx* ctx = new m_ctx; ctx->ptr.Reset(iso, Context::New(iso)); ctx->iso = iso; - ctx->startup_data = nullptr; + ctx->startup_data = startup_data; iso->SetData(0, ctx); return iso; @@ -293,81 +278,53 @@ RtnUnboundScript IsolateCompileUnboundScript(IsolatePtr iso, /********** SnapshotCreator **********/ -SnapshotCreatorPtr NewSnapshotCreator(SnapshotCreatorOptions options) { - if (options.iso) { - SnapshotCreator* creator = new SnapshotCreator(options.iso); - return creator; - } else { - SnapshotCreator* creator = new SnapshotCreator; - return creator; +RtnSnapshotCreator NewSnapshotCreator() { + RtnSnapshotCreator rtn = {}; + SnapshotCreator* creator = new SnapshotCreator; + Isolate* iso = creator->GetIsolate(); + { + HandleScope handle_scope(iso); + Local ctx = Context::New(iso); + creator->SetDefaultContext(ctx); } + + rtn.creator = creator; + rtn.iso = iso; + + return rtn; } void DeleteSnapshotCreator(SnapshotCreatorPtr snapshotCreator) { delete snapshotCreator; } -RtnSnapshotBlob CreateSnapshot(SnapshotCreatorPtr snapshotCreator, - const char* source, - const char* origin, - int function_code_handling) { - Isolate* iso = snapshotCreator->GetIsolate(); - size_t index; - RtnSnapshotBlob rtn = {}; - - { - bool fail = false; - HandleScope handle_scope(iso); - Local ctx = Context::New(iso); - TryCatch try_catch(iso); - Context::Scope context_scope(ctx); - - MaybeLocal maybeSrc = - String::NewFromUtf8(iso, source, NewStringType::kNormal); - MaybeLocal maybeOgn = - String::NewFromUtf8(iso, origin, NewStringType::kNormal); - Local src, ogn; - if (maybeSrc.ToLocal(&src) && maybeOgn.ToLocal(&ogn)) { - String::Utf8Value value(iso, src); - ScriptOrigin script_origin(ogn); - Local