Skip to content

Commit cc6e686

Browse files
committed
handle errors when calling NewContextFromSnapshot at V8 level
1 parent b66880e commit cc6e686

File tree

4 files changed

+69
-12
lines changed

4 files changed

+69
-12
lines changed

context.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ package v8go
88
// #include "v8go.h"
99
import "C"
1010
import (
11-
"errors"
1211
"runtime"
1312
"sync"
1413
"unsafe"
@@ -78,21 +77,22 @@ func NewContext(opt ...ContextOption) *Context {
7877
}
7978

8079
// NewContextFromSnapshot creates a new JavaScript context from the Isolate startup data;
81-
// If the Isolate has no startup data associated returns an error.
80+
// error will be of type `JSError` if not nil.
8281
func NewContextFromSnapshot(iso *Isolate, snapshot_index int) (*Context, error) {
8382
ctxMutex.Lock()
8483
ctxSeq++
8584
ref := ctxSeq
8685
ctxMutex.Unlock()
8786

88-
createParams := iso.createParams
89-
if createParams == nil || createParams.startupData == nil {
90-
return nil, errors.New("v8go: The isolate must have startupData associated with it")
87+
rtn := C.NewContextFromSnapshot(iso.ptr, C.size_t(snapshot_index), C.int(ref))
88+
89+
if rtn.context == nil {
90+
return nil, newJSError(rtn.error)
9191
}
9292

9393
ctx := &Context{
9494
ref: ref,
95-
ptr: C.NewContextFromSnapshot(iso.ptr, C.size_t(snapshot_index), C.int(ref)),
95+
ptr: rtn.context,
9696
iso: iso,
9797
}
9898

context_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,45 @@ func TestNewContextFromSnapshotErrorWhenIsolateHasNoStartupData(t *testing.T) {
5555
}
5656
}
5757

58+
func TestNewContextFromSnapshotErrorWhenIndexOutOfRange(t *testing.T) {
59+
t.Parallel()
60+
61+
snapshotCreator := v8.NewSnapshotCreator()
62+
snapshotCreatorIso, err := snapshotCreator.GetIsolate()
63+
fatalIf(t, err)
64+
65+
snapshotCreatorCtx := v8.NewContext(snapshotCreatorIso)
66+
defer snapshotCreatorCtx.Close()
67+
68+
snapshotCreatorCtx.RunScript(`const add = (a, b) => a + b`, "add.js")
69+
snapshotCreatorCtx.RunScript(`function run() { return add(3, 4); }`, "main.js")
70+
err = snapshotCreator.SetDefaultContext(snapshotCreatorCtx)
71+
fatalIf(t, err)
72+
73+
snapshotCreatorCtx2 := v8.NewContext(snapshotCreatorIso)
74+
defer snapshotCreatorCtx2.Close()
75+
76+
snapshotCreatorCtx2.RunScript(`const multiply = (a, b) => a * b`, "add.js")
77+
snapshotCreatorCtx2.RunScript(`function run() { return multiply(3, 4); }`, "main.js")
78+
index, err := snapshotCreator.AddContext(snapshotCreatorCtx2)
79+
fatalIf(t, err)
80+
81+
data, err := snapshotCreator.Create(v8.FunctionCodeHandlingClear)
82+
fatalIf(t, err)
83+
84+
iso := v8.NewIsolate(v8.WithStartupData(data))
85+
defer iso.Dispose()
86+
87+
ctx, err := v8.NewContextFromSnapshot(iso, index+1)
88+
89+
if ctx != nil {
90+
t.Errorf("expected nil context got: %+v", ctx)
91+
}
92+
if err == nil {
93+
t.Error("error expected but was <nil>")
94+
}
95+
}
96+
5897
func TestJSExceptions(t *testing.T) {
5998
t.Parallel()
6099

v8go.cc

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -668,28 +668,41 @@ ContextPtr NewContext(IsolatePtr iso,
668668
return ctx;
669669
}
670670

671-
ContextPtr NewContextFromSnapshot(IsolatePtr iso,
671+
RtnContext NewContextFromSnapshot(IsolatePtr iso,
672672
size_t snapshot_blob_index,
673673
int ref) {
674674
Locker locker(iso);
675675
Isolate::Scope isolate_scope(iso);
676676
HandleScope handle_scope(iso);
677677

678+
RtnContext rtn = {};
679+
678680
// For function callbacks we need a reference to the context, but because of
679681
// the complexities of C -> Go function pointers, we store a reference to the
680682
// context as a simple integer identifier; this can then be used on the Go
681683
// side to lookup the context in the context registry. We use slot 1 as slot 0
682684
// has special meaning for the Chrome debugger.
683685

684-
Local<Context> local_ctx =
685-
Context::FromSnapshot(iso, snapshot_blob_index).ToLocalChecked();
686+
Local<Context> local_ctx;
687+
MaybeLocal<Context> maybe_local_ctx =
688+
Context::FromSnapshot(iso, snapshot_blob_index);
689+
690+
if (!maybe_local_ctx.ToLocal(&local_ctx)) {
691+
RtnError error = {nullptr, nullptr, nullptr};
692+
error.msg = CopyString("Failed to create context from snapshot index: " +
693+
std::to_string(snapshot_blob_index));
694+
rtn.error = error;
695+
return rtn;
696+
}
697+
686698
local_ctx->SetEmbedderData(1, Integer::New(iso, ref));
687699

688700
m_ctx* ctx = new m_ctx;
689701
ctx->ptr.Reset(iso, local_ctx);
690702
ctx->iso = iso;
691703
ctx->startup_data = nullptr;
692-
return ctx;
704+
rtn.context = ctx;
705+
return rtn;
693706
}
694707

695708
void ContextFree(ContextPtr ctx) {

v8go.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,12 @@ typedef struct {
125125
} RtnValue;
126126

127127
typedef struct {
128-
const char* data;
128+
ContextPtr context;
129+
RtnError error;
130+
} RtnContext;
131+
132+
typedef struct {
133+
const char* string;
129134
int length;
130135
RtnError error;
131136
} RtnString;
@@ -190,7 +195,7 @@ extern void CPUProfileDelete(CPUProfile* ptr);
190195
extern ContextPtr NewContext(IsolatePtr iso_ptr,
191196
TemplatePtr global_template_ptr,
192197
int ref);
193-
extern ContextPtr NewContextFromSnapshot(IsolatePtr iso,
198+
extern RtnContext NewContextFromSnapshot(IsolatePtr iso,
194199
size_t snapshot_blob_index,
195200
int ref);
196201
extern void ContextFree(ContextPtr ptr);

0 commit comments

Comments
 (0)