Skip to content

Commit

Permalink
Add Exception type and New*Error constructors.
Browse files Browse the repository at this point in the history
  • Loading branch information
tommie committed Oct 13, 2021
1 parent d7fb5d5 commit 3a20035
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 0 deletions.
87 changes: 87 additions & 0 deletions exception.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright 2021 Roger Chapman and the v8go contributors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package v8go

import (
// #include <stdlib.h>
// #include "v8go.h"
"C"

"fmt"
"unsafe"
)

// NewRangeError creates a RangeError.
func NewRangeError(iso *Isolate, msg string) *Exception {
return newExceptionError(iso, C.ERROR_RANGE, msg)
}

// NewReferenceError creates a ReferenceError.
func NewReferenceError(iso *Isolate, msg string) *Exception {
return newExceptionError(iso, C.ERROR_REFERENCE, msg)
}

// NewSyntaxError creates a SyntaxError.
func NewSyntaxError(iso *Isolate, msg string) *Exception {
return newExceptionError(iso, C.ERROR_SYNTAX, msg)
}

// NewTypeError creates a TypeError.
func NewTypeError(iso *Isolate, msg string) *Exception {
return newExceptionError(iso, C.ERROR_TYPE, msg)
}

// NewWasmCompileError creates a WasmCompileError.
func NewWasmCompileError(iso *Isolate, msg string) *Exception {
return newExceptionError(iso, C.ERROR_WASM_COMPILE, msg)
}

// NewWasmLinkError creates a WasmLinkError.
func NewWasmLinkError(iso *Isolate, msg string) *Exception {
return newExceptionError(iso, C.ERROR_WASM_LINK, msg)
}

// NewWasmRuntimeError creates a WasmRuntimeError.
func NewWasmRuntimeError(iso *Isolate, msg string) *Exception {
return newExceptionError(iso, C.ERROR_WASM_RUNTIME, msg)
}

// NewError creates an Error, which is the common thing to throw from
// user code.
func NewError(iso *Isolate, msg string) *Exception {
return newExceptionError(iso, C.ERROR_GENERIC, msg)
}

func newExceptionError(iso *Isolate, typ C.ErrorTypeIndex, msg string) *Exception {
cmsg := C.CString(msg)
defer C.free(unsafe.Pointer(cmsg))
eptr := C.NewValueError(iso.ptr, typ, cmsg)
if eptr == nil {
panic(fmt.Errorf("invalid error type index: %d", typ))
}
return &Exception{&Value{ptr: eptr}}
}

// An Exception is a JavaScript exception.
type Exception struct {
*Value
}

// value implements Valuer.
func (e *Exception) value() *Value {
return e.Value
}

// Error implements error.
func (e *Exception) Error() string {
return e.String()
}

// String implements fmt.Stringer.
func (e *Exception) String() string {
s := C.ExceptionGetMessageString(e.ptr)
defer C.free(unsafe.Pointer(s))
return C.GoString(s)
}
44 changes: 44 additions & 0 deletions exception_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2021 Roger Chapman and the v8go contributors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package v8go_test

import (
"strings"
"testing"

v8 "rogchap.com/v8go"
)

func TestNewError(t *testing.T) {
t.Parallel()

tsts := []struct {
New func(*v8.Isolate, string) *v8.Exception
WantType string
}{
{v8.NewRangeError, "RangeError"},
{v8.NewReferenceError, "ReferenceError"},
{v8.NewSyntaxError, "SyntaxError"},
{v8.NewTypeError, "TypeError"},
{v8.NewWasmCompileError, "CompileError"},
{v8.NewWasmLinkError, "LinkError"},
{v8.NewWasmRuntimeError, "RuntimeError"},
{v8.NewError, "Error"},
}
for _, tst := range tsts {
t.Run(tst.WantType, func(t *testing.T) {
iso := v8.NewIsolate()
defer iso.Dispose()

got := tst.New(iso, "amessage")
if !got.IsNativeError() {
t.Error("IsNativeError returned false, want true")
}
if got := got.Error(); !strings.Contains(got, " "+tst.WantType+":") {
t.Errorf("Error(): got %q, want containing %q", got, tst.WantType)
}
})
}
}
53 changes: 53 additions & 0 deletions v8go.cc
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,48 @@ RtnValue NewValueBigIntFromWords(IsolatePtr iso,
return rtn;
}

ValuePtr NewValueError(IsolatePtr iso, ErrorTypeIndex idx, const char* message) {
ISOLATE_SCOPE_INTERNAL_CONTEXT(iso);
Local<Context> local_ctx = ctx->ptr.Get(iso);
Context::Scope context_scope(local_ctx);

Local<String> local_msg = String::NewFromUtf8(iso, message).ToLocalChecked();
Local<Value> v;
switch (idx) {
case ERROR_RANGE:
v = Exception::RangeError(local_msg);
break;
case ERROR_REFERENCE:
v = Exception::ReferenceError(local_msg);
break;
case ERROR_SYNTAX:
v = Exception::SyntaxError(local_msg);
break;
case ERROR_TYPE:
v = Exception::TypeError(local_msg);
break;
case ERROR_WASM_COMPILE:
v = Exception::WasmCompileError(local_msg);
break;
case ERROR_WASM_LINK:
v = Exception::WasmLinkError(local_msg);
break;
case ERROR_WASM_RUNTIME:
v = Exception::WasmRuntimeError(local_msg);
break;
case ERROR_GENERIC:
v = Exception::Error(local_msg);
break;
default:
return nullptr;
}
m_value* val = new m_value;
val->iso = iso;
val->ctx = ctx;
val->ptr = Persistent<Value, CopyablePersistentTraits<Value>>(iso, v);
return tracked_value(ctx, val);
}

const uint32_t* ValueToArrayIndex(ValuePtr ptr) {
LOCAL_VALUE(ptr);
Local<Uint32> array_index;
Expand Down Expand Up @@ -1030,6 +1072,17 @@ int ValueIsModuleNamespaceObject(ValuePtr ptr) {
return value->IsModuleNamespaceObject();
}

/********** Exception **********/

const char* ExceptionGetMessageString(ValuePtr ptr) {
LOCAL_VALUE(ptr);

Local<Message> local_msg = Exception::CreateMessage(iso, value);
Local<String> local_str = local_msg->Get();
String::Utf8Value utf8(iso, local_str);
return CopyString(utf8);
}

/********** Object **********/

#define LOCAL_OBJECT(ptr) \
Expand Down
15 changes: 15 additions & 0 deletions v8go.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ typedef m_ctx* ContextPtr;
typedef m_value* ValuePtr;
typedef m_template* TemplatePtr;

typedef enum {
ERROR_RANGE = 1,
ERROR_REFERENCE,
ERROR_SYNTAX,
ERROR_TYPE,
ERROR_WASM_COMPILE,
ERROR_WASM_LINK,
ERROR_WASM_RUNTIME,
ERROR_GENERIC,
} ErrorTypeIndex;

typedef struct {
const char* msg;
const char* location;
Expand Down Expand Up @@ -115,6 +126,7 @@ extern RtnValue NewValueBigIntFromWords(IsolatePtr iso_ptr,
int sign_bit,
int word_count,
const uint64_t* words);
extern ValuePtr NewValueError(IsolatePtr iso_ptr, ErrorTypeIndex idx, const char* message);
const char* ValueToString(ValuePtr ptr);
const uint32_t* ValueToArrayIndex(ValuePtr ptr);
int ValueToBoolean(ValuePtr ptr);
Expand Down Expand Up @@ -185,6 +197,9 @@ extern void ObjectSet(ValuePtr ptr, const char* key, ValuePtr val_ptr);
extern void ObjectSetIdx(ValuePtr ptr, uint32_t idx, ValuePtr val_ptr);
extern RtnValue ObjectGet(ValuePtr ptr, const char* key);
extern RtnValue ObjectGetIdx(ValuePtr ptr, uint32_t idx);

const char* ExceptionGetMessageString(ValuePtr ptr);

int ObjectHas(ValuePtr ptr, const char* key);
int ObjectHasIdx(ValuePtr ptr, uint32_t idx);
int ObjectDelete(ValuePtr ptr, const char* key);
Expand Down

0 comments on commit 3a20035

Please sign in to comment.