forked from rogchap/v8go
-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
context.cc
121 lines (100 loc) · 3.17 KB
/
context.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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;
}