Skip to content

Commit

Permalink
Merge pull request #75 from stroiman/split-c-files
Browse files Browse the repository at this point in the history
Splits C files into more manageable pieces.
  • Loading branch information
tommie authored Dec 4, 2024
2 parents 3e19593 + b7d6fa8 commit 9b006d0
Show file tree
Hide file tree
Showing 30 changed files with 1,035 additions and 658 deletions.
1 change: 1 addition & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
BasedOnStyle: Chromium
20 changes: 20 additions & 0 deletions context-macros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef V8GO_CONTEXT_MACROS_H
#define V8GO_CONTEXT_MACROS_H

#include "deps/include/v8-context.h"
#include "deps/include/v8-isolate.h"
#include "deps/include/v8-local-handle.h"
#include "deps/include/v8-locker.h"

#include "context.h"

#define LOCAL_CONTEXT(ctx) \
v8::Isolate* iso = ctx->iso; \
v8::Locker locker(iso); \
v8::Isolate::Scope isolate_scope(iso); \
v8::HandleScope handle_scope(iso); \
v8::TryCatch try_catch(iso); \
v8::Local<v8::Context> local_ctx = ctx->ptr.Get(iso); \
v8::Context::Scope context_scope(local_ctx);

#endif
121 changes: 121 additions & 0 deletions context.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#include "deps/include/v8-template.h"

#include "context-macros.h"
#include "template.h"
#include "unbound_script.h"
#include "value.h"

using namespace v8;

ContextPtr NewContext(IsolatePtr iso,
TemplatePtr global_template_ptr,
int ref) {
Locker locker(iso);
Isolate::Scope isolate_scope(iso);
HandleScope handle_scope(iso);

Local<ObjectTemplate> global_template;
if (global_template_ptr != nullptr) {
global_template = global_template_ptr->ptr.Get(iso).As<ObjectTemplate>();
} else {
global_template = ObjectTemplate::New(iso);
}

// For function callbacks we need a reference to the context, but because of
// the complexities of C -> Go function pointers, we store a reference to the
// context as a simple integer identifier; this can then be used on the Go
// side to lookup the context in the context registry. We use slot 1 as slot 0
// has special meaning for the Chrome debugger.
Local<Context> local_ctx = Context::New(iso, nullptr, global_template);
local_ctx->SetEmbedderData(1, Integer::New(iso, ref));

m_ctx* ctx = new m_ctx;
ctx->ptr.Reset(iso, local_ctx);
ctx->iso = iso;
return ctx;
}

void ContextFree(ContextPtr ctx) {
if (ctx == nullptr) {
return;
}
ctx->ptr.Reset();

for (auto it = ctx->vals.begin(); it != ctx->vals.end(); ++it) {
auto value = it->second;
value->ptr.Reset();
delete value;
}
ctx->vals.clear();

for (m_unboundScript* us : ctx->unboundScripts) {
us->ptr.Reset();
delete us;
}

delete ctx;
}

m_value* tracked_value(m_ctx* ctx, m_value* val) {
// (rogchap) we track values against a context so that when the context is
// closed (either manually or GC'd by Go) we can also release all the
// values associated with the context;
if (val->id == 0) {
val->id = ++ctx->nextValId;
ctx->vals[val->id] = val;
}

return val;
}

ValuePtr ContextGlobal(ContextPtr ctx) {
LOCAL_CONTEXT(ctx);
m_value* val = new m_value;
val->id = 0;

val->iso = iso;
val->ctx = ctx;
val->ptr = Global<Value>(iso, local_ctx->Global());

return tracked_value(ctx, val);
}

int ContextRetainedValueCount(ContextPtr ctx) {
return ctx->vals.size();
}

RtnValue RunScript(ContextPtr ctx, const char* source, const char* origin) {
LOCAL_CONTEXT(ctx);

RtnValue rtn = {};

MaybeLocal<String> maybeSrc =
String::NewFromUtf8(iso, source, NewStringType::kNormal);
MaybeLocal<String> maybeOgn =
String::NewFromUtf8(iso, origin, NewStringType::kNormal);
Local<String> src, ogn;
if (!maybeSrc.ToLocal(&src) || !maybeOgn.ToLocal(&ogn)) {
rtn.error = ExceptionError(try_catch, iso, local_ctx);
return rtn;
}

ScriptOrigin script_origin(ogn);
Local<Script> script;
if (!Script::Compile(local_ctx, src, &script_origin).ToLocal(&script)) {
rtn.error = ExceptionError(try_catch, iso, local_ctx);
return rtn;
}
Local<Value> result;
if (!script->Run(local_ctx).ToLocal(&result)) {
rtn.error = ExceptionError(try_catch, iso, local_ctx);
return rtn;
}
m_value* val = new m_value;
val->id = 0;
val->iso = iso;
val->ctx = ctx;
val->ptr = Global<Value>(iso, result);

rtn.value = tracked_value(ctx, val);
return rtn;
}
2 changes: 1 addition & 1 deletion context.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
package v8go

// #include <stdlib.h>
// #include "v8go.h"
// #include "context.h"
import "C"
import (
"runtime"
Expand Down
61 changes: 61 additions & 0 deletions context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#ifndef V8GO_CONTEXT_H
#define V8GO_CONTEXT_H

#include "errors.h"
#include "isolate.h"

#ifdef __cplusplus

#include "deps/include/v8-persistent-handle.h"

#include <unordered_map>
#include <vector>
#include "value.h"

namespace v8 {
class Isolate;
class Context;
} // namespace v8

typedef v8::Isolate v8Isolate;
typedef struct m_unboundScript m_unboundScript;

struct m_ctx {
v8::Isolate* iso;
std::unordered_map<long, m_value*> vals;
std::vector<m_unboundScript*> unboundScripts;
v8::Persistent<v8::Context> ptr;
long nextValId;
};
typedef m_ctx* ContextPtr;

extern m_value* tracked_value(m_ctx* ctx, m_value* val);

extern "C" {
#else
typedef struct v8Isolate v8Isolate;
#endif
typedef v8Isolate* IsolatePtr;

typedef struct m_value m_value;
typedef m_value* ValuePtr;

typedef struct m_template m_template;
typedef m_template* TemplatePtr;

extern ContextPtr NewContext(IsolatePtr iso_ptr,
TemplatePtr global_template_ptr,
int ref);
extern int ContextRetainedValueCount(ContextPtr ctx);
extern ValuePtr ContextGlobal(ContextPtr ctx_ptr);
extern void ContextFree(ContextPtr ctx);
extern RtnValue RunScript(ContextPtr ctx_ptr,
const char* source,
const char* origin);

#ifdef __cplusplus
} // extern "C"

#endif

#endif
1 change: 1 addition & 0 deletions cpuprofile.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package v8go

/*
#include "v8go.h"
#include "errors.h"
*/
import "C"
import "time"
Expand Down
50 changes: 50 additions & 0 deletions errors.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include <sstream>

#include "deps/include/v8-exception.h"
#include "deps/include/v8-message.h"
#include "deps/include/v8-primitive.h"

#include "errors.h"
#include "utils.h"

using namespace v8;

RtnError ExceptionError(TryCatch& try_catch, Isolate* iso, Local<Context> ctx) {
HandleScope handle_scope(iso);

RtnError rtn = {nullptr, nullptr, nullptr};

if (try_catch.HasTerminated()) {
rtn.msg =
CopyString("ExecutionTerminated: script execution has been terminated");
return rtn;
}

String::Utf8Value exception(iso, try_catch.Exception());
rtn.msg = CopyString(exception);

Local<Message> msg = try_catch.Message();
if (!msg.IsEmpty()) {
String::Utf8Value origin(iso, msg->GetScriptOrigin().ResourceName());
std::ostringstream sb;
sb << *origin;
Maybe<int> line = try_catch.Message()->GetLineNumber(ctx);
if (line.IsJust()) {
sb << ":" << line.ToChecked();
}
Maybe<int> start = try_catch.Message()->GetStartColumn(ctx);
if (start.IsJust()) {
sb << ":"
<< start.ToChecked() + 1; // + 1 to match output from stack trace
}
rtn.location = CopyString(sb.str());
}

Local<Value> mstack;
if (try_catch.StackTrace(ctx).ToLocal(&mstack)) {
String::Utf8Value stack(iso, mstack);
rtn.stack = CopyString(stack);
}

return rtn;
}
2 changes: 1 addition & 1 deletion errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
package v8go

// #include <stdlib.h>
// #include "v8go.h"
// #include "errors.h"
import "C"
import (
"fmt"
Expand Down
49 changes: 49 additions & 0 deletions errors.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#ifndef V8GO_ERRORS_H
#define V8GO_ERRORS_H

typedef struct {
const char* msg;
const char* location;
const char* stack;
} RtnError;

#ifdef __cplusplus

#include "deps/include/v8-local-handle.h"

namespace v8 {
class Isolate;
class Context;
class TryCatch;
} // namespace v8

extern "C" {

extern RtnError ExceptionError(v8::TryCatch& try_catch,
v8::Isolate* iso,
v8::Local<v8::Context> ctx);
#endif

typedef struct m_value m_value;
typedef m_value* ValuePtr;

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 {
ValuePtr value;
RtnError error;
} RtnValue;

#ifdef __cplusplus
}
#endif
#endif
22 changes: 22 additions & 0 deletions isolate-macros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef V8GO_ISOLATE_MACROS_H
#define V8GO_ISOLATE_MACROS_H

#include "deps/include/v8-exception.h"
#include "deps/include/v8-isolate.h"
#include "deps/include/v8-locker.h"

#include "context.h"
#include "isolate.h"

static inline m_ctx* isolateInternalContext(v8::Isolate* iso) {
return static_cast<m_ctx*>(iso->GetData(0));
}

#define ISOLATE_SCOPE(iso) \
Locker locker(iso); \
Isolate::Scope isolate_scope(iso); \
HandleScope handle_scope(iso);

#define INTERNAL_CONTEXT(iso) m_ctx* ctx = static_cast<m_ctx*>(iso->GetData(0));

#endif
Loading

0 comments on commit 9b006d0

Please sign in to comment.