-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest.cc
302 lines (232 loc) · 10.1 KB
/
test.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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
//Test embedding V8 into C++ application
//bin2c -st -c -t char -n v8_natives_blob natives_blob.bin > natives_blob.cc
//bin2c -st -c -t char -n v8_snapshot_blob snapshot_blob.bin > snapshot_blob.cc
//g++ -std=c++11 -I"v8/include" test.cc -o test -Wl,--start-group \
v8/out/x64.release/obj.target/{tools/gyp/libv8_{base,libbase,external_snapshot,libplatform},third_party/icu/libicu{uc,i18n,data}}.a -Wl,--end-group \
-lrt -ldl -pthread
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "v8/include/libplatform/libplatform.h"
#include "v8/include/v8.h"
#define COMPILE_BLOBS 1
#ifdef COMPILE_BLOBS
#include "natives_blob.cc"
#include "snapshot_blob.cc"
#endif
using namespace v8;
class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
public:
virtual void* Allocate(size_t length) {
void* data = AllocateUninitialized(length);
return data == NULL ? data : memset(data, 0, length);
}
virtual void* AllocateUninitialized(size_t length) { return malloc(length); }
virtual void Free(void* data, size_t) { free(data); }
};
void Log(const char* event) {
printf("LOG: %s\n", event);
}
static void LogCallback(const FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() < 1) return;
HandleScope scope(args.GetIsolate());
Local<Value> arg = args[0];
String::Utf8Value value(arg);
Log(*value);
}
bool ExecuteScript(Isolate* isolate, Local<String> script) {
HandleScope handle_scope(isolate);
// We're just about to compile the script; set up an error handler to
// catch any exceptions the script might throw.
TryCatch try_catch(isolate);
Local<Context> context(isolate->GetCurrentContext());
// Compile the script and check for errors.
Local<Script> compiled_script;
if (!Script::Compile(context, script).ToLocal(&compiled_script)) {
String::Utf8Value error(try_catch.Exception());
Log(*error);
// The script failed to compile; bail out.
return false;
}
// Run the script!
Local<Value> result;
if (!compiled_script->Run(context).ToLocal(&result)) {
// The TryCatch above is still in effect and will have caught the error.
String::Utf8Value error(try_catch.Exception());
Log(*error);
// Running the script failed; bail out.
return false;
}
String::Utf8Value utf8(result);
printf("%s\n", *utf8);
return true;
}
bool ExecuteScript(Isolate* isolate, const char* s) {
//Create a string containing the JavaScript source code.
Local<String> source =
String::NewFromUtf8(isolate, s, NewStringType::kNormal).ToLocalChecked();
return ExecuteScript(isolate, source);
}
bool CheckFnExists(Isolate* isolate, const char* fnName) {
Local<Context> context(isolate->GetCurrentContext());
// fetch out the fnName function from the global object.
Local<String> process_name =
String::NewFromUtf8(isolate, fnName, NewStringType::kNormal)
.ToLocalChecked();
Local<Value> process_val;
// If there is no function, or if it is not a function
return context->Global()->Get(context, process_name).ToLocal(&process_val) && process_val->IsFunction();
}
Local<Function> GetFn(Isolate* isolate, const char* fnName) {
Local<Context> context(isolate->GetCurrentContext());
EscapableHandleScope handle_scope(isolate);
// The script compiled and ran correctly. Now we fetch out the
// Process function from the global object.
Local<String> process_name =
String::NewFromUtf8(isolate, fnName, NewStringType::kNormal)
.ToLocalChecked();
Local<Value> process_val;
// If there is no Process function, or if it is not a function,
// bail out
bool OK = context->Global()->Get(context, process_name).ToLocal(&process_val);
Local<Function> process_fun = Local<Function>::Cast(process_val);
return handle_scope.Escape(process_fun);
}
double GetNumber(Isolate* isolate, const char* globName, double defaultValue) {
Local<Context> context(isolate->GetCurrentContext());
EscapableHandleScope handle_scope(isolate);
Local<String> name = String::NewFromUtf8(isolate, globName, NewStringType::kNormal).ToLocalChecked();
Local<Value> val;
bool OK = context->Global()->Get(context, name).ToLocal(&val) && val->IsNumber();
if (OK) {
return val->NumberValue();
} else {
return defaultValue;
}
}
const char* GetString(Isolate* isolate, const char* globName, const char* defaultValue) {
Local<Context> context(isolate->GetCurrentContext());
EscapableHandleScope handle_scope(isolate);
Local<String> name = String::NewFromUtf8(isolate, globName, NewStringType::kNormal).ToLocalChecked();
Local<Value> val;
bool OK = context->Global()->Get(context, name).ToLocal(&val);// && val->IsNumber();
if (OK) {
String::Utf8Value* ret = new String::Utf8Value(val);
return **ret;
} else {
return defaultValue;
}
}
bool GetBoolean(Isolate* isolate, const char* globName) {
Local<Context> context(isolate->GetCurrentContext());
EscapableHandleScope handle_scope(isolate);
Local<String> name = String::NewFromUtf8(isolate, globName, NewStringType::kNormal).ToLocalChecked();
Local<Value> val;
bool OK = context->Global()->Get(context, name).ToLocal(&val);
if (OK) {
return val->BooleanValue();
} else {
return false;
}
}
void makeGlobalByteArray(Isolate* isolate, const char* globName, size_t size, void* data) {
Local<Context> context(isolate->GetCurrentContext());
EscapableHandleScope handle_scope(isolate);
Local<ArrayBuffer> buffer = ArrayBuffer::New(isolate, data, size);
Local<Uint8Array> jsbuffer = Uint8Array::New(buffer, 0, size);
Local<String> name = String::NewFromUtf8(isolate, globName, NewStringType::kNormal).ToLocalChecked();
Maybe<bool> OK = context->Global()->Set(context, name, jsbuffer);
}
int main(int argc, char* argv[]) {
// Initialize V8.
V8::InitializeICU();
#ifdef COMPILE_BLOBS
static StartupData natives;
natives.data = (const char*) v8_natives_blob;
natives.raw_size = sizeof(v8_natives_blob);
static StartupData snapshot;
snapshot.data = (const char*) v8_snapshot_blob;
snapshot.raw_size = sizeof(v8_snapshot_blob);
V8::SetNativesDataBlob(&natives);
V8::SetSnapshotDataBlob(&snapshot);
#else
V8::InitializeExternalStartupData(argv[0]);
#endif
Platform* platform = platform::CreateDefaultPlatform();
V8::InitializePlatform(platform);
V8::Initialize();
// Create a new Isolate and make it the current one.
ArrayBufferAllocator allocator;
Isolate::CreateParams create_params;
create_params.array_buffer_allocator = &allocator;
Isolate* isolate = Isolate::New(create_params);
{
Isolate::Scope isolate_scope(isolate);
// Create a stack-allocated handle scope.
HandleScope handle_scope(isolate);
//Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
//global->Set(String::NewFromUtf8(isolate, "print", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, LogCallback));
// Create a new context.
Local<Context> context = Context::New(isolate, NULL);
// Enter the context for compiling and running the hello world script.
Context::Scope context_scope(context);
context->Global()->Set(String::NewFromUtf8(isolate, "print", NewStringType::kNormal).ToLocalChecked(),
FunctionTemplate::New(isolate, LogCallback)->GetFunction());
size_t testSize = 1024;
char* testData = (char*) malloc(1024);
memset(testData, 0, 1);
testData[3] = 77;
makeGlobalByteArray(isolate, "testData", testSize, testData);
ExecuteScript(isolate,
"windowTitle = 'meow'; \
screenWidth = 800; \
testBool1 = true; \
testBool2 = false; \
var testBool3; \
print(testData.length); \
print(testData[3]); \
function process() { \
print('Hello, Log callback called from JavaScript!'); \
return 1 \
}; \
'Hello' + ', World!'"
);
double sw = GetNumber(isolate, "screenWidth", 640);
printf("SYSTEM: screenWidth=%f\n", sw);
const char* wt = GetString(isolate, "windowTitle", "V8 SDL2");
printf("SYSTEM: windowTitle=%s\n", wt);
printf("SYSTEM: true=%d\n", GetBoolean(isolate, "testBool1"));
printf("SYSTEM: false=%d\n", GetBoolean(isolate, "testBool2"));
printf("SYSTEM: undefined=%d\n", GetBoolean(isolate, "testBool3"));
printf("SYSTEM: undeclared=%d\n", GetBoolean(isolate, "testBool4"));
// Set up an exception handler before calling the Process function
TryCatch try_catch(isolate);
if (CheckFnExists(isolate, "process")) {
printf("JavaScript Function found: \"process\"\n");
} else {
printf("Error: no \"process\" function found\n");
return 1;
}
// Get function
Local<Function> process_fun = GetFn(isolate, "process");
// Invoke the process function, giving the global object as 'this'
// and one argument, the request.
const unsigned argc = 2;
Local<Value> argv[argc] = { Null(isolate), String::NewFromUtf8(isolate, "success") };
//Local<Function> process = v8::Local<v8::Function>::New(isolate, process_);
Local<Value> result;
if (!process_fun->Call(context, context->Global(), argc, argv).ToLocal(&result)) {
String::Utf8Value error(try_catch.Exception());
printf("Error: %s\n", *error);
return false;
} else {
return true;
}
}
// Dispose the isolate and tear down V8.
isolate->Dispose();
V8::Dispose();
V8::ShutdownPlatform();
delete platform;
return 0;
}