Skip to content

Commit 4e01bfa

Browse files
committed
Add V8 engine base
1 parent 41cd019 commit 4e01bfa

File tree

12 files changed

+567
-1
lines changed

12 files changed

+567
-1
lines changed

Package.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,24 @@ let package = Package(
2727
.target(
2828
name: "CJavaScriptCore",
2929
dependencies: []),
30+
.target(
31+
name: "CV8",
32+
dependencies: []),
3033
.target(
3134
name: "JavaScriptCoreSwift",
3235
dependencies: ["CJavaScriptCore", "JavaScript"]),
36+
.target(
37+
name: "V8",
38+
dependencies: ["CV8", "JavaScript"]),
3339
.target(
3440
name: "JavaScript",
3541
dependencies: []),
3642
.testTarget(
3743
name: "JavaScriptCoreTests",
3844
dependencies: ["Test", "JavaScriptCoreSwift"]),
39-
]
45+
.testTarget(
46+
name: "V8Tests",
47+
dependencies: ["Test", "V8"]),
48+
],
49+
cxxLanguageStandard: .cxx11
4050
)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright 2017 Tris Foundation and the project authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License
6+
*
7+
* See LICENSE.txt in the project root for license information
8+
* See CONTRIBUTORS.txt for the list of the project authors
9+
*/
10+
11+
module CV8 [system] {
12+
header "wrappers.h"
13+
link "v8"
14+
export *
15+
}

Sources/CV8/include/wrappers.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2017 Tris Foundation and the project authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License
6+
*
7+
* See LICENSE.txt in the project root for license information
8+
* See CONTRIBUTORS.txt for the list of the project authors
9+
*/
10+
11+
#ifndef wrappers_h
12+
#define wrappers_h
13+
14+
#include <stdint.h>
15+
#include <stdbool.h>
16+
17+
#ifdef __cplusplus
18+
extern "C" {
19+
#endif
20+
21+
22+
void* initialize();
23+
void dispose(void* platform);
24+
void* createIsolate();
25+
void disposeIsolate(void* isolate);
26+
27+
void* createContext(void* isolate);
28+
void disposeContext(void* context);
29+
30+
void* evaluate(void* isolatePtr, void* contextPtr, const char* scriptPtr, void** exception);
31+
void disposeValue(void* pointer);
32+
33+
int getUtf8StringLength(void* isolatePtr, void* valuePtr);
34+
void copyUtf8String(void* isolatePtr, void* valuePtr, void* buffer, int count);
35+
36+
int64_t valueToInt(void* isolatePtr, void* valuePtr);
37+
38+
bool isNull(void* isolatePtr, void* valuePtr);
39+
bool isUndefined(void* isolatePtr, void* valuePtr);
40+
bool isBoolean(void* isolatePtr, void* valuePtr);
41+
bool isNumber(void* isolatePtr, void* valuePtr);
42+
bool isString(void* isolatePtr, void* valuePtr);
43+
bool isObject(void* isolatePtr, void* valuePtr);
44+
45+
46+
#ifdef __cplusplus
47+
}
48+
#endif
49+
50+
#endif /* wrappers_h */

Sources/CV8/wrappers.cpp

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/*
2+
* Copyright 2017 Tris Foundation and the project authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License
6+
*
7+
* See LICENSE.txt in the project root for license information
8+
* See CONTRIBUTORS.txt for the list of the project authors
9+
*/
10+
11+
#include <stdlib.h> // malloc, free
12+
#include <string.h> // memset, memcpy
13+
#include <libplatform/libplatform.h>
14+
#include <v8.h>
15+
16+
using namespace v8;
17+
18+
class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
19+
public:
20+
virtual void *Allocate(size_t length){
21+
void *data = AllocateUninitialized(length);
22+
return data == NULL ? data : memset(data, 0, length);
23+
}
24+
virtual void *AllocateUninitialized(size_t length) { return malloc(length); }
25+
virtual void Free(void *data, size_t) { free(data); }
26+
};
27+
28+
class GlobalValue {
29+
public:
30+
explicit GlobalValue(Isolate* isolate, Global<Value>* value):
31+
isolate_locker(isolate), isolate_scope(isolate), handle_scope(isolate),
32+
isolate(isolate), value(value) {
33+
}
34+
35+
explicit GlobalValue(void* isolate, void* value)
36+
: GlobalValue(reinterpret_cast<Isolate*>(isolate), reinterpret_cast<Global<Value>*>(value)) {
37+
}
38+
39+
~GlobalValue() { }
40+
41+
V8_INLINE Local<Value> operator*() const {
42+
return value->Get(isolate);
43+
}
44+
45+
V8_INLINE Local<Value> operator->() const {
46+
return value->Get(isolate);
47+
}
48+
49+
private:
50+
Locker isolate_locker;
51+
Isolate::Scope isolate_scope;
52+
HandleScope handle_scope;
53+
54+
Isolate* isolate;
55+
Global<Value>* value;
56+
57+
// Prevent copying of GlobalValue objects.
58+
GlobalValue(const GlobalValue&);
59+
GlobalValue& operator=(const GlobalValue&);
60+
};
61+
62+
extern "C" {
63+
ArrayBufferAllocator bufferAllocator;
64+
65+
const void* initialize() {
66+
V8::InitializeICU();
67+
auto platform = platform::CreateDefaultPlatform();
68+
V8::InitializePlatform(platform);
69+
V8::Initialize();
70+
return platform;
71+
}
72+
73+
void dispose(void* platform) {
74+
V8::Dispose();
75+
V8::ShutdownPlatform();
76+
delete reinterpret_cast<Platform*>(platform);;
77+
}
78+
79+
const void* createIsolate() {
80+
Isolate::CreateParams create_params;
81+
create_params.array_buffer_allocator = &bufferAllocator;
82+
return Isolate::New(create_params);
83+
}
84+
85+
void disposeIsolate(void* isolate) {
86+
reinterpret_cast<Isolate*>(isolate)->Dispose();
87+
}
88+
89+
void* createContext(void* isolatePtr) {
90+
auto isolate = reinterpret_cast<Isolate*>(isolatePtr);
91+
Locker isolateLocker(isolate);
92+
Isolate::Scope isolate_scope(isolate);
93+
HandleScope handle_scope(isolate);
94+
Local<Context> context = Context::New(isolate);
95+
return new Global<Context>(isolate, context);
96+
}
97+
98+
void disposeContext(void* context) {
99+
delete reinterpret_cast<Global<Context>*>(context);
100+
}
101+
102+
void* evaluate(void* isolatePtr, void* contextPtr, const char* scriptPtr, void** exception) {
103+
auto isolate = reinterpret_cast<Isolate*>(isolatePtr);
104+
auto globalContext = reinterpret_cast<Global<Context>*>(contextPtr);
105+
106+
Locker isolateLocker(isolate);
107+
TryCatch trycatch(isolate);
108+
Isolate::Scope isolate_scope(isolate);
109+
HandleScope handle_scope(isolate);
110+
Local<Context> context = globalContext->Get(isolate);
111+
Context::Scope context_scope(context);
112+
Local<String> source = String::NewFromUtf8(isolate, scriptPtr);
113+
Local<Script> script = Script::Compile(source);
114+
MaybeLocal<Value> result = script->Run(context);
115+
116+
if (result.IsEmpty()) {
117+
*exception = new Global<Value>(isolate, trycatch.Exception());
118+
return nullptr;
119+
}
120+
auto local = result.ToLocalChecked();
121+
return new Global<Value>(isolate, local);
122+
}
123+
124+
void disposeValue(void* pointer) {
125+
delete reinterpret_cast<Global<Value>*>(pointer);
126+
}
127+
128+
int64_t valueToInt(void* isolate, void* value) {
129+
GlobalValue scoped(isolate, value);
130+
return scoped->ToInteger()->IntegerValue();
131+
}
132+
133+
int getUtf8StringLength(void* isolate, void* value) {
134+
GlobalValue scoped(isolate, value);
135+
String::Utf8Value utf8(*scoped);
136+
return utf8.length();
137+
}
138+
139+
void copyUtf8String(void* isolate, void* value, void* buffer, int count) {
140+
GlobalValue scoped(isolate, value);
141+
String::Utf8Value utf8(*scoped);
142+
memcpy(buffer, *utf8, count);
143+
}
144+
145+
// MARK: type checks
146+
147+
bool isNull(void* isolate, void* value) {
148+
GlobalValue scoped(isolate, value);
149+
return scoped->IsNull();
150+
}
151+
152+
bool isUndefined(void* isolate, void* value) {
153+
GlobalValue scoped(isolate, value);
154+
return scoped->IsUndefined();
155+
}
156+
157+
bool isBoolean(void* isolate, void* value) {
158+
GlobalValue scoped(isolate, value);
159+
return scoped->IsBoolean();
160+
}
161+
162+
bool isNumber(void* isolate, void* value) {
163+
GlobalValue scoped(isolate, value);
164+
return scoped->IsNumber();
165+
}
166+
167+
bool isString(void* isolate, void* value) {
168+
GlobalValue scoped(isolate, value);
169+
return scoped->IsString();
170+
}
171+
172+
bool isObject(void* isolate, void* value) {
173+
GlobalValue scoped(isolate, value);
174+
return scoped->IsObject();
175+
}
176+
}

Sources/V8/JSContext.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2017 Tris Foundation and the project authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License
6+
*
7+
* See LICENSE.txt in the project root for license information
8+
* See CONTRIBUTORS.txt for the list of the project authors
9+
*/
10+
11+
import CV8
12+
import JavaScript
13+
14+
public class JSContext {
15+
let runtime: JSRuntime
16+
let context: UnsafeMutableRawPointer?
17+
18+
public init(_ runtime: JSRuntime = JSRuntime.global) {
19+
self.runtime = runtime
20+
self.context = CV8.createContext(runtime.isolate)
21+
}
22+
23+
deinit {
24+
CV8.disposeContext(context)
25+
}
26+
}
27+
28+
struct JSError: Error, CustomStringConvertible {
29+
let description: String
30+
}
31+
32+
extension JSContext: JavaScript.JSContext {
33+
public func evaluate(_ script: String) throws -> JSValue {
34+
var exception: UnsafeMutableRawPointer?
35+
guard let pointer = CV8.evaluate(runtime.isolate, context, script, &exception) else {
36+
guard let exception = exception else {
37+
fatalError("exception pointer is nil")
38+
}
39+
let value = JSValue(pointer: exception, isolate: runtime.isolate)
40+
throw JSError(description: value.description)
41+
}
42+
return JSValue(pointer: pointer, isolate: runtime.isolate)
43+
}
44+
}

Sources/V8/JSEngine.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright 2017 Tris Foundation and the project authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License
6+
*
7+
* See LICENSE.txt in the project root for license information
8+
* See CONTRIBUTORS.txt for the list of the project authors
9+
*/
10+
11+
import CV8
12+
import JavaScript
13+
14+
public class JSEngine: JavaScript.JSEngine {
15+
public typealias JSRuntime = V8.JSRuntime
16+
public static func createRuntime() -> JSRuntime {
17+
return JSRuntime()
18+
}
19+
}

Sources/V8/JSRuntime.swift

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2017 Tris Foundation and the project authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License
6+
*
7+
* See LICENSE.txt in the project root for license information
8+
* See CONTRIBUTORS.txt for the list of the project authors
9+
*/
10+
11+
import CV8
12+
import JavaScript
13+
14+
public class JSRuntime {
15+
let platform: UnsafeMutableRawPointer
16+
let isolate: UnsafeMutableRawPointer
17+
18+
public static var global: JSRuntime = {
19+
return JSRuntime()
20+
}()
21+
22+
public required init() {
23+
self.platform = initialize()
24+
self.isolate = createIsolate()
25+
}
26+
27+
deinit {
28+
disposeIsolate(isolate)
29+
dispose(platform)
30+
}
31+
}
32+
33+
extension JSRuntime: JavaScript.JSRuntime {
34+
public func createContext() -> JSContext {
35+
return JSContext(self)
36+
}
37+
}

0 commit comments

Comments
 (0)