Skip to content

Commit 74b2e56

Browse files
Gustavo CasoGenevieve
authored andcommitted
Add SnapshotCreator API
Co-authored-by: Genevieve <[email protected]>
1 parent c0dbfd3 commit 74b2e56

File tree

7 files changed

+500
-7
lines changed

7 files changed

+500
-7
lines changed

context.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package v8go
88
// #include "v8go.h"
99
import "C"
1010
import (
11+
"errors"
1112
"runtime"
1213
"sync"
1314
"unsafe"
@@ -76,6 +77,27 @@ func NewContext(opt ...ContextOption) *Context {
7677
return ctx
7778
}
7879

80+
func NewContextFromSnapshot(iso *Isolate, snapshot_index int) (*Context, error) {
81+
ctxMutex.Lock()
82+
ctxSeq++
83+
ref := ctxSeq
84+
ctxMutex.Unlock()
85+
86+
createParams := iso.createParams
87+
if createParams == nil || createParams.startupData == nil {
88+
return nil, errors.New("Must create an isolate from a snapshot blob")
89+
}
90+
91+
ctx := &Context{
92+
ref: ref,
93+
ptr: C.NewContextFromSnapshot(iso.ptr, C.size_t(snapshot_index), C.int(ref)),
94+
iso: iso,
95+
}
96+
97+
ctx.register()
98+
return ctx, nil
99+
}
100+
79101
// Isolate gets the current context's parent isolate.An error is returned
80102
// if the isolate has been terninated.
81103
func (c *Context) Isolate() *Isolate {

context_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,22 @@ func TestContextExec(t *testing.T) {
3939
}
4040
}
4141

42+
func TestNewContextFromSnapshotErrorWhenIsolateHasNoStartupData(t *testing.T) {
43+
t.Parallel()
44+
45+
iso := v8.NewIsolate()
46+
defer iso.Dispose()
47+
48+
ctx, err := v8.NewContextFromSnapshot(iso, 1)
49+
50+
if ctx != nil {
51+
t.Errorf("error expected nil context got: %+v", ctx)
52+
}
53+
if err == nil {
54+
t.Error("error expected but was <nil>")
55+
}
56+
}
57+
4258
func TestJSExceptions(t *testing.T) {
4359
t.Parallel()
4460

isolate.go

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ type Isolate struct {
2525
cbSeq int
2626
cbs map[int]FunctionCallback
2727

28-
null *Value
29-
undefined *Value
28+
null *Value
29+
undefined *Value
30+
createParams *CreateParams
3031
}
3132

3233
// HeapStatistics represents V8 isolate heap statistics
@@ -44,20 +45,45 @@ type HeapStatistics struct {
4445
NumberOfDetachedContexts uint64
4546
}
4647

48+
type createOptions func(*CreateParams)
49+
50+
func WithStartupData(startupData *StartupData) createOptions {
51+
return func(params *CreateParams) {
52+
params.startupData = startupData
53+
}
54+
}
55+
56+
type CreateParams struct {
57+
startupData *StartupData
58+
}
59+
4760
// NewIsolate creates a new V8 isolate. Only one thread may access
4861
// a given isolate at a time, but different threads may access
4962
// different isolates simultaneously.
5063
// When an isolate is no longer used its resources should be freed
5164
// by calling iso.Dispose().
5265
// An *Isolate can be used as a v8go.ContextOption to create a new
5366
// Context, rather than creating a new default Isolate.
54-
func NewIsolate() *Isolate {
67+
func NewIsolate(opts ...createOptions) *Isolate {
5568
v8once.Do(func() {
5669
C.Init()
5770
})
71+
params := &CreateParams{}
72+
for _, opt := range opts {
73+
opt(params)
74+
}
75+
76+
var cOptions C.IsolateOptions
77+
78+
if params.startupData != nil {
79+
cOptions.snapshot_blob_data = (*C.char)(unsafe.Pointer(&params.startupData.data[0]))
80+
cOptions.snapshot_blob_raw_size = params.startupData.raw_size
81+
}
82+
5883
iso := &Isolate{
59-
ptr: C.NewIsolate(),
60-
cbs: make(map[int]FunctionCallback),
84+
ptr: C.NewIsolate(cOptions),
85+
cbs: make(map[int]FunctionCallback),
86+
createParams: params,
6187
}
6288
iso.null = newValueNull(iso)
6389
iso.undefined = newValueUndefined(iso)
@@ -146,6 +172,7 @@ func (i *Isolate) Dispose() {
146172
return
147173
}
148174
C.IsolateDispose(i.ptr)
175+
i.createParams = nil
149176
i.ptr = nil
150177
}
151178

snapshot_creator.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// Copyright 2021 the v8go contributors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
package v8go
6+
7+
// #include <stdlib.h>
8+
// #include "v8go.h"
9+
import "C"
10+
import (
11+
"errors"
12+
"unsafe"
13+
)
14+
15+
type FunctionCodeHandling int
16+
17+
const (
18+
FunctionCodeHandlingKlear FunctionCodeHandling = iota
19+
FunctionCodeHandlingKeep
20+
)
21+
22+
type StartupData struct {
23+
data []byte
24+
raw_size C.int
25+
}
26+
27+
type SnapshotCreator struct {
28+
ptr C.SnapshotCreatorPtr
29+
iso *Isolate
30+
defaultContextAdded bool
31+
}
32+
33+
func NewSnapshotCreator() *SnapshotCreator {
34+
v8once.Do(func() {
35+
C.Init()
36+
})
37+
38+
rtn := C.NewSnapshotCreator()
39+
40+
return &SnapshotCreator{
41+
ptr: rtn.creator,
42+
iso: &Isolate{ptr: rtn.iso},
43+
defaultContextAdded: false,
44+
}
45+
}
46+
47+
func (s *SnapshotCreator) GetIsolate() (*Isolate, error) {
48+
if s.ptr == nil {
49+
return nil, errors.New("v8go: Cannot get Isolate after creating the blob")
50+
}
51+
52+
return s.iso, nil
53+
}
54+
55+
func (s *SnapshotCreator) SetDeafultContext(ctx *Context) error {
56+
if s.defaultContextAdded {
57+
return errors.New("v8go: Cannot set multiple default context for snapshot creator")
58+
}
59+
60+
C.SetDefaultContext(s.ptr, ctx.ptr)
61+
s.defaultContextAdded = true
62+
ctx.ptr = nil
63+
64+
return nil
65+
}
66+
67+
func (s *SnapshotCreator) AddContext(ctx *Context) (int, error) {
68+
if s.ptr == nil {
69+
return 0, errors.New("v8go: Cannot add context to snapshot creator after creating the blob")
70+
}
71+
72+
index := C.AddContext(s.ptr, ctx.ptr)
73+
ctx.ptr = nil
74+
75+
return int(index), nil
76+
}
77+
78+
func (s *SnapshotCreator) Create(functionCode FunctionCodeHandling) (*StartupData, error) {
79+
if s.ptr == nil {
80+
return nil, errors.New("v8go: Cannot use snapshot creator after creating the blob")
81+
}
82+
83+
if !s.defaultContextAdded {
84+
return nil, errors.New("v8go: Cannot create a snapshot without a default context")
85+
}
86+
87+
rtn := C.CreateBlob(s.ptr, C.int(functionCode))
88+
89+
s.ptr = nil
90+
s.iso.ptr = nil
91+
92+
raw_size := rtn.raw_size
93+
data := C.GoBytes(unsafe.Pointer(rtn.data), raw_size)
94+
95+
C.SnapshotBlobDelete(rtn)
96+
97+
return &StartupData{data: data, raw_size: raw_size}, nil
98+
}
99+
100+
func (s *SnapshotCreator) Dispose() {
101+
if s.ptr != nil {
102+
C.DeleteSnapshotCreator(s.ptr)
103+
}
104+
}

0 commit comments

Comments
 (0)