Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split c files #75

Merged
merged 40 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
2eeab2e
Add clang-format file
stroiman Dec 1, 2024
cb9bb4b
Extract string copy to utils.cc/utils.h
stroiman Nov 30, 2024
5deabab
Extract Value type declarations to new file
stroiman Nov 30, 2024
deb6a5f
Extract Error struct to separate header
stroiman Nov 30, 2024
ed7c0ff
Move UnboundScript C++ declarations to new header
stroiman Nov 30, 2024
d8777e1
Move Isolate C++ declaration to isolate.h
stroiman Nov 30, 2024
ddb503c
Move Context C++ declaration to new header file
stroiman Nov 30, 2024
202b483
Move context macros
stroiman Dec 1, 2024
555777a
Move Context C++ definitions to context.cc
stroiman Nov 30, 2024
d67f837
Move Isolate C++ definitions to isolate.cc
stroiman Nov 30, 2024
b724a39
Move Error C++ declarations to errors.h
stroiman Nov 30, 2024
4f17294
Move Error C++ definitions to c++ file
stroiman Nov 30, 2024
3ea69bb
Move ScriptCompiler code
stroiman Dec 1, 2024
2e3a1fd
Move context macros to separate file
stroiman Dec 1, 2024
14f0f6b
Extract m_template definition to template.h
stroiman Dec 1, 2024
1df6f64
Move RtnValue definition to 'interop.h'
stroiman Dec 1, 2024
b1d5549
Move Context C++ definitions to context.cc
stroiman Dec 1, 2024
85abf6b
Remove `v8go.h` import from isolate.go
stroiman Dec 1, 2024
6b3b3f5
Move error type to errors.h
stroiman Dec 1, 2024
8b2eb8d
Move Value C++ Declarations
stroiman Dec 1, 2024
c450539
Don't include entire v8go.h from errors.go
stroiman Dec 1, 2024
45cf5a9
Move JSON C declarations to json.h
stroiman Dec 1, 2024
641dd7d
Move unbound_script func declarations to header
stroiman Dec 1, 2024
6929a9e
Move stuff to unbound_script
stroiman Dec 1, 2024
9d4d096
Move isolate macros to separate file
stroiman Dec 1, 2024
94701ad
Extract isolate macros
stroiman Dec 2, 2024
332cb0c
Extract value macros
stroiman Dec 2, 2024
ae897fa
Extract symbol declaration and definitions
stroiman Dec 2, 2024
15dc8f0
Extract forward declarations
stroiman Dec 2, 2024
6c27706
Move value forward declarations
stroiman Dec 2, 2024
025e923
Move RtnValue to errors.h
stroiman Dec 4, 2024
d328ff3
Add necessary includes to macro headers
stroiman Dec 4, 2024
733555a
Group v8 imports
stroiman Dec 4, 2024
72a060d
Include required imports from context-macros.h
stroiman Dec 4, 2024
47b6d9c
Remove unused include
stroiman Dec 4, 2024
b16abd3
Remove forward-declarations
stroiman Dec 4, 2024
99e0822
Make include paths explicit
stroiman Dec 4, 2024
e98f993
Fix includes in v8go.h
stroiman Dec 4, 2024
69bb5b1
Add stdint.h and stddef.h to value.h
stroiman Dec 4, 2024
b7d6fa8
Remove _almost_ empty file
stroiman Dec 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
BasedOnStyle: Chromium
18 changes: 18 additions & 0 deletions context-macros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#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"

#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
122 changes: 122 additions & 0 deletions context.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#include "context.h"
#include "context-macros.h"
#include "deps/include/v8-template.h"
tommie marked this conversation as resolved.
Show resolved Hide resolved
#include "interop.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) {
tommie marked this conversation as resolved.
Show resolved Hide resolved
// (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
54 changes: 54 additions & 0 deletions context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#ifndef V8GO_CONTEXT_H
#define V8GO_CONTEXT_H

#include "interop.h"
#include "isolate.h"

#ifdef __cplusplus

#include <unordered_map>
#include <vector>
#include "deps/include/v8-persistent-handle.h"
#include "value.h"

namespace v8 {
class Context;
} // namespace v8

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

#endif

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
48 changes: 48 additions & 0 deletions errors.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "errors.h"
#include <sstream>
#include "deps/include/v8-exception.h"
#include "deps/include/v8-message.h"
#include "deps/include/v8-primitive.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
41 changes: 41 additions & 0 deletions errors.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#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 enum {
ERROR_RANGE = 1,
ERROR_REFERENCE,
ERROR_SYNTAX,
ERROR_TYPE,
ERROR_WASM_COMPILE,
ERROR_WASM_LINK,
ERROR_WASM_RUNTIME,
ERROR_GENERIC,
} ErrorTypeIndex;

#ifdef __cplusplus
}
#endif
#endif
56 changes: 56 additions & 0 deletions forward-declarations.h
tommie marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#ifndef V8GO_FORWARD_DECLARATIONS_H
#define V8GO_FORWARD_DECLARATIONS_H

// Create "forward declarations" of structs and classes.
//
// When a type is defined, the compiler doesn't need to know the full
// definition of the contained types. But the compiler needs to know the _size_
// of those types. By creating forward declarations of used classes and structs,
// pointers to these can be used in header files; without including the full
// type definition, when all we need is a pointer; as the pointer has a well
// defined type.
//
// This can speed up compilation significantly, when used cleverly.

// It's not necessary to have forward declarations in a shared file; they can
// easily be redeclared where needed. Some of these are not _so_ trivial thouch,
// so types that are declared in may files may be extracted here.

#ifdef __cplusplus

// This block is visible when C++ code is compiled. Create the forward
// declarations in the namespace and class name they belong.

namespace v8 {
class Isolate;
};

typedef v8::Isolate v8Isolate;

extern "C" {

#else

// This block is visible when compiling Go code.

// Go code can't use C++ types and namespace, so their full type isn't declared,
// only as anonymous structs. Go only needs to know that it uses pointers to
// these types; but not the full definitions of those types.

typedef struct v8Isolate v8Isolate;

#endif

typedef struct m_ctx m_ctx;
typedef struct m_value m_value;

// Pointer types. Go code needs explicit pointer types to use pointers from
// C-code
typedef v8Isolate* IsolatePtr;
typedef m_ctx* ContextPtr;
typedef m_value* ValuePtr;

#ifdef __cplusplus
} // extern "C"
#endif
#endif
15 changes: 15 additions & 0 deletions interop.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef V8GO_INTEROP_H
#define V8GO_INTEROP_H

#include "errors.h"
#include "forward-declarations.h"

// A go-friendly return type combining value and error.
// Maybe this really belongs in value.h, but seems to be used from multiple
// places.
typedef struct {
ValuePtr value;
RtnError error;
} RtnValue;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider moving this to errors.h. It only exists to add an error to a value, so I think it belongs in the realm of error handling (and this file is small, with a vague scope.)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I had trouble placing this. I didn't think it so much of as an error, but more like converting the result to idiomatic go.

But I wouldn't mind putting it in errors. I didn't look too much at what the "errors.h" really contains, as extracting the errors file was mostly the result of, if I move A, I also need to move B.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My problem is this file is too small and unfocused: no one will think of looking at this file to find RtnValue. A file that is about mapping error handling domains makes more sense to me. That said, it's not a strong opinion.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved it to errors.h for now. Maybe a sensible place will reveal itself later :)

I don't have a strong opinion either.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw, on "small files", there is also utils.h/utils.cc containing string copying functionality ...

Opinion on those?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think they're fine. Having one slush bucket is better than two, and probably unavoidable. :)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we remove the almost empty file?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Damn, I thought I did that.


#endif
Loading
Loading