Merge lp:~marcustomlinson/v8-cpp/v8runner into lp:v8-cpp

Proposed by Marcus Tomlinson
Status: Merged
Merged at revision: 11
Proposed branch: lp:~marcustomlinson/v8-cpp/v8runner
Merge into: lp:v8-cpp
Diff against target: 491 lines (+360/-14)
12 files modified
.bzrignore (+4/-0)
CMakeLists.txt (+5/-3)
deps/build-deps.sh (+30/-0)
src/CMakeLists.txt (+24/-3)
src/internal/require.h (+137/-0)
src/module.h (+23/-5)
src/run.h (+95/-0)
src/v8-cpp.h (+1/-0)
test/CMakeLists.txt (+7/-3)
test/addon.cpp (+1/-0)
v8runner/CMakeLists.txt (+9/-0)
v8runner/v8runner.cpp (+24/-0)
To merge this branch: bzr merge lp:~marcustomlinson/v8-cpp/v8runner
Reviewer Review Type Date Requested Status
Marcus Tomlinson Pending
Review via email: mp+263641@code.launchpad.net

Commit message

Added v8runner executable that runs a JS script and supports the "require()" keyword to load in V8 (incl. Node) modules.

To post a comment you must log in.
lp:~marcustomlinson/v8-cpp/v8runner updated
33. By Marcus Tomlinson

Retrieve dependencies on build rather than cmake

34. By Marcus Tomlinson

Oops, fixed v8cpp_script_path_

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file '.bzrignore'
--- .bzrignore 2015-06-10 05:57:04 +0000
+++ .bzrignore 2015-07-02 11:58:46 +0000
@@ -1,1 +1,5 @@
1./CMakeLists.txt.user1./CMakeLists.txt.user
2./deps/.gclient
3./deps/.gclient_entries
4./deps/depot_tools
5./deps/v8
26
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2015-06-10 06:20:49 +0000
+++ CMakeLists.txt 2015-07-02 11:58:46 +0000
@@ -13,12 +13,14 @@
13 -fPIC13 -fPIC
14)14)
1515
16find_package(Node REQUIRED)
17
18include_directories(16include_directories(
19 ${NODE_INCLUDE_DIRS}
20 ${CMAKE_CURRENT_SOURCE_DIR}/src17 ${CMAKE_CURRENT_SOURCE_DIR}/src
18 ${CMAKE_CURRENT_SOURCE_DIR}/deps/v8/include
19)
20link_directories(
21 ${CMAKE_CURRENT_SOURCE_DIR}/deps/v8/out/native/obj.target/tools/gyp
21)22)
2223
23add_subdirectory(src)24add_subdirectory(src)
24add_subdirectory(test)25add_subdirectory(test)
26add_subdirectory(v8runner)
2527
=== added directory 'deps'
=== added file 'deps/build-deps.sh'
--- deps/build-deps.sh 1970-01-01 00:00:00 +0000
+++ deps/build-deps.sh 2015-07-02 11:58:46 +0000
@@ -0,0 +1,30 @@
1#!/bin/bash
2
3DIR=$(readlink -f $(dirname ${BASH_SOURCE[0]}))
4
5cd $DIR
6
7if ! [ -d "depot_tools" ]; then
8 git clone --depth 1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
9fi
10
11if ! [ -d "v8" ]; then
12 git clone --depth 1 --branch 3.28.73 https://chromium.googlesource.com/v8/v8.git
13fi
14
15export PATH=./depot_tools:"$PATH"
16gclient config --spec 'solutions = [
17 { "name" : "v8",
18 "url" : "https://chromium.googlesource.com/v8/v8.git",
19 "deps_file" : "DEPS",
20 "managed" : False,
21 "custom_deps" : {
22 },
23 "safesync_url": "",
24 },
25]
26cache_dir = None'
27gclient sync
28
29cd v8
30make -j3 native i18nsupport=off
031
=== modified file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 2015-06-10 05:57:04 +0000
+++ src/CMakeLists.txt 2015-07-02 11:58:46 +0000
@@ -4,7 +4,28 @@
4 *.h4 *.h
5)5)
66
7add_custom_target(7add_library(
8 source_files8 v8-cpp SHARED
9 SOURCES ${SRC_FILES}9 ${SRC_FILES}
10)
11
12set_target_properties(
13 v8-cpp PROPERTIES
14 LINKER_LANGUAGE CXX
15)
16
17target_link_libraries(
18 v8-cpp
19
20 v8_base
21 v8_libbase
22 v8_snapshot
23
24 dl
25 pthread
26)
27
28add_custom_command(
29 TARGET v8-cpp PRE_LINK
30 COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/../deps/build-deps.sh
10)31)
1132
=== added file 'src/internal/require.h'
--- src/internal/require.h 1970-01-01 00:00:00 +0000
+++ src/internal/require.h 2015-07-02 11:58:46 +0000
@@ -0,0 +1,137 @@
1/*
2 * Copyright (C) 2015 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com>
17 */
18
19#pragma once
20
21#include <dlfcn.h>
22#include <iostream>
23
24namespace v8cpp
25{
26namespace internal
27{
28
29using ModuleInitFunc = void(v8::Handle<v8::Object> exports);
30ModuleInitFunc* node_init_func_;
31std::string v8cpp_script_path_;
32
33struct NodeModule
34{
35 int nm_version;
36 unsigned int nm_flags;
37 void* nm_dso_handle;
38 const char* nm_filename;
39 ModuleInitFunc* nm_register_func;
40 //...
41};
42
43extern "C" void node_module_register(void* m)
44{
45 auto mp = static_cast<NodeModule*>(m);
46
47 // For now we only know that version 14 works here
48 if (mp->nm_version == 14)
49 {
50 node_init_func_ = mp->nm_register_func;
51 }
52 else
53 {
54 std::cerr << "node_module_register(): ignoring node module. nm_version " << mp->nm_version << " not supported"
55 << std::endl;
56 }
57}
58
59class Console
60{
61public:
62 inline static void log(v8::FunctionCallbackInfo<v8::Value> const& args)
63 {
64 for (int i = 0; i < args.Length(); ++i)
65 {
66 if (args[i]->IsInt32())
67 {
68 std::cout << v8cpp::from_v8<int>(v8::Isolate::GetCurrent(), args[i]) << std::endl;
69 }
70 if (args[i]->IsUint32())
71 {
72 std::cout << v8cpp::from_v8<unsigned int>(v8::Isolate::GetCurrent(), args[i]) << std::endl;
73 }
74 else if (args[i]->IsNumber())
75 {
76 std::cout << v8cpp::from_v8<float>(v8::Isolate::GetCurrent(), args[i]) << std::endl;
77 }
78 else if (args[i]->IsBoolean())
79 {
80 std::cout << v8cpp::from_v8<bool>(v8::Isolate::GetCurrent(), args[i]) << std::endl;
81 }
82 else if (args[i]->IsString())
83 {
84 std::cout << v8cpp::from_v8<std::string>(v8::Isolate::GetCurrent(), args[i]) << std::endl;
85 }
86 }
87 std::cout.flush();
88 }
89};
90
91inline v8::Local<v8::Object> require(std::string const& module_path)
92{
93 node_init_func_ = nullptr;
94 v8::Local<v8::Object> exports = v8::Object::New(v8::Isolate::GetCurrent());
95
96 // Try append ".node" to module_path
97 std::string suffixed_module_path = v8cpp_script_path_ + module_path + ".node";
98 auto module = dlopen(suffixed_module_path.c_str(), RTLD_LAZY);
99 if (!module)
100 {
101 // Didn't work, now try append ".so" to module_path
102 suffixed_module_path = v8cpp_script_path_ + module_path + ".so";
103 module = dlopen(suffixed_module_path.c_str(), RTLD_LAZY);
104 if (!module)
105 {
106 // Still didn't work, just try module_path as is
107 suffixed_module_path = v8cpp_script_path_ + module_path;
108 module = dlopen(suffixed_module_path.c_str(), RTLD_LAZY);
109 if (!module)
110 {
111 std::cerr << "dlopen failed: " << dlerror() << std::endl;
112 return exports;
113 }
114 }
115 }
116
117 if (node_init_func_)
118 {
119 node_init_func_(exports);
120 }
121 else
122 {
123 auto v8cpp_init_func = (ModuleInitFunc*)dlsym(module, "init_module");
124 if (!v8cpp_init_func)
125 {
126 std::cerr << "dlsym failed: " << dlerror() << std::endl;
127 return exports;
128 }
129
130 v8cpp_init_func(exports);
131 }
132
133 return exports;
134}
135
136} // namespace internal
137} // namespace v8cpp
0138
=== modified file 'src/module.h'
--- src/module.h 2015-06-11 05:51:30 +0000
+++ src/module.h 2015-07-02 11:58:46 +0000
@@ -32,7 +32,7 @@
32public:32public:
33 explicit Module(v8::Isolate* isolate)33 explicit Module(v8::Isolate* isolate)
34 : isolate_(isolate)34 : isolate_(isolate)
35 , object_(v8::ObjectTemplate::New(isolate))35 , object_template_(v8::ObjectTemplate::New(isolate))
36 {36 {
37 }37 }
3838
@@ -40,7 +40,7 @@
40 template <typename T>40 template <typename T>
41 Module& add_class(char const* name, Class<T>& cl)41 Module& add_class(char const* name, Class<T>& cl)
42 {42 {
43 object_->Set(to_v8(isolate_, name), cl.class_.proto_template()->GetFunction());43 object_template_->Set(to_v8(isolate_, name), cl.class_.proto_template()->GetFunction());
44 return *this;44 return *this;
45 }45 }
4646
@@ -48,19 +48,37 @@
48 template <typename F>48 template <typename F>
49 Module& add_function(char const* name, F func)49 Module& add_function(char const* name, F func)
50 {50 {
51 object_->Set(to_v8(isolate_, name), internal::export_function(isolate_, func));51 object_template_->Set(to_v8(isolate_, name), internal::export_function(isolate_, func));
52 return *this;52 return *this;
53 }53 }
5454
55 // Create an instance of this module in V855 // Create an instance of this module in V8
56 v8::Local<v8::Object> create_prototype()56 v8::Local<v8::Object> create_prototype()
57 {57 {
58 return object_->NewInstance();58 return object_template_->NewInstance();
59 }
60
61 v8::Handle<v8::ObjectTemplate> object_template()
62 {
63 return object_template_;
59 }64 }
6065
61private:66private:
62 v8::Isolate* isolate_;67 v8::Isolate* isolate_;
63 v8::Handle<v8::ObjectTemplate> object_;68 v8::Handle<v8::ObjectTemplate> object_template_;
64};69};
6570
71// Create a V8-cpp module by exposing it's init function
72#define V8CPP_MODULE(module_name, init_func)\
73extern "C"\
74{\
75 namespace v8cpp\
76 {\
77 void init_module(Handle<Object> exports)\
78 {\
79 init_func(exports);\
80 }\
81 }\
82}
83
66} // namespace v8cpp84} // namespace v8cpp
6785
=== added file 'src/run.h'
--- src/run.h 1970-01-01 00:00:00 +0000
+++ src/run.h 2015-07-02 11:58:46 +0000
@@ -0,0 +1,95 @@
1/*
2 * Copyright (C) 2015 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com>
17 */
18
19#pragma once
20
21#include <internal/require.h>
22
23#include <fstream>
24
25namespace v8cpp
26{
27
28template <typename T = v8::Handle<v8::Value>>
29T run_script(v8::Isolate* isolate, std::string const& source, std::string const& filename = "")
30{
31 // Create an isolate scope.
32 v8::Isolate::Scope isolate_scope(isolate);
33
34 // Create a stack-allocated handle scope.
35 v8::HandleScope handle_scope(isolate);
36
37 // Prepare console class
38 v8cpp::Class<internal::Console> console(isolate);
39 console
40 .set_constructor()
41 .add_method("log", &internal::Console::log);
42
43 // Create a new context that supports "require()" and "console".
44 v8cpp::Module module(isolate);
45 {
46 v8::Context::Scope context_scope(v8::Context::New(isolate));
47
48 // Store the script filename for use in require() later
49 internal::v8cpp_script_path_.clear();
50 std::size_t found = filename.find_last_of("/");
51 if (found != std::string::npos)
52 {
53 internal::v8cpp_script_path_ = filename.substr(0, found) + "/";
54 }
55
56 module.add_function("require", &internal::require);
57 module.add_class("console", console);
58 }
59 v8::Local<v8::Context> context = v8::Context::New(isolate, nullptr, module.object_template());
60
61 // Enter the context for compiling and running the script.
62 v8::Context::Scope context_scope(context);
63
64 // Compile the script.
65 v8::Local<v8::Script> script = v8::Script::Compile(v8cpp::to_v8(isolate, source), v8cpp::to_v8(isolate, filename));
66
67 // Run the script.
68 if (script.IsEmpty())
69 {
70 if (!filename.empty())
71 {
72 throw std::runtime_error("run_script(): Failed to compile script file: \"" + filename + "\"");
73 }
74 else
75 {
76 throw std::runtime_error("run_script(): Failed to compile script.");
77 }
78 }
79
80 return v8cpp::from_v8<T>(isolate, script->Run());
81}
82
83template <typename T = v8::Handle<v8::Value>>
84T run_script_file(v8::Isolate* isolate, std::string const& filename)
85{
86 std::ifstream stream(filename.c_str());
87 if (!stream)
88 {
89 throw std::runtime_error("run_script_file(): Failed to locate script file: \"" + filename + "\"");
90 }
91
92 std::istreambuf_iterator<char> begin(stream), end;
93 return run_script<T>(isolate, std::string(begin, end), filename);
94}
95}
096
=== modified file 'src/v8-cpp.h'
--- src/v8-cpp.h 2015-06-10 05:57:04 +0000
+++ src/v8-cpp.h 2015-07-02 11:58:46 +0000
@@ -20,3 +20,4 @@
20#include <class.h>20#include <class.h>
21#include <convert.h>21#include <convert.h>
22#include <module.h>22#include <module.h>
23#include <run.h>
2324
=== modified file 'test/CMakeLists.txt'
--- test/CMakeLists.txt 2015-06-10 05:57:04 +0000
+++ test/CMakeLists.txt 2015-07-02 11:58:46 +0000
@@ -1,9 +1,13 @@
1find_package(Node REQUIRED)
2
3include_directories(
4 ${NODE_INCLUDE_DIRS}
5)
6
1file(7file(
2 GLOB8 GLOB
3 TEST_FILES9 TEST_FILES
4 *.h10 *.h *.cpp *.js
5 *.cpp
6 *.js
7)11)
812
9configure_file(test.js test.js)13configure_file(test.js test.js)
1014
=== modified file 'test/addon.cpp'
--- test/addon.cpp 2015-06-22 16:40:30 +0000
+++ test/addon.cpp 2015-07-02 11:58:46 +0000
@@ -119,3 +119,4 @@
119}119}
120120
121NODE_MODULE(addon, InitAll)121NODE_MODULE(addon, InitAll)
122V8CPP_MODULE(addon, InitAll)
122123
=== added directory 'v8runner'
=== added file 'v8runner/CMakeLists.txt'
--- v8runner/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ v8runner/CMakeLists.txt 2015-07-02 11:58:46 +0000
@@ -0,0 +1,9 @@
1add_executable(
2 v8runner
3 v8runner.cpp
4)
5
6target_link_libraries(
7 v8runner
8 v8-cpp
9)
010
=== added file 'v8runner/v8runner.cpp'
--- v8runner/v8runner.cpp 1970-01-01 00:00:00 +0000
+++ v8runner/v8runner.cpp 2015-07-02 11:58:46 +0000
@@ -0,0 +1,24 @@
1#include <v8-cpp.h>
2
3using namespace v8;
4
5int main(int argc, char* argv[])
6{
7 // Check args.
8 if (argc != 2)
9 {
10 std::cerr << "usage: v8runner script.js" << std::endl;
11 return -1;
12 }
13
14 // Create a new isolate to run our script in.
15 Isolate* isolate = Isolate::New();
16
17 // Run script.
18 v8cpp::run_script_file(isolate, argv[1]);
19
20 // Clean up.
21 isolate->Dispose();
22
23 return 0;
24}

Subscribers

People subscribed via source and target branches

to all changes: