Merge lp:~marcustomlinson/v8-cpp/lp-1474858 into lp:v8-cpp
- lp-1474858
- Merge into trunk
Proposed by
Marcus Tomlinson
Status: | Merged |
---|---|
Merged at revision: | 22 |
Proposed branch: | lp:~marcustomlinson/v8-cpp/lp-1474858 |
Merge into: | lp:v8-cpp |
Diff against target: |
350 lines (+109/-57) 10 files modified
example/module.cpp (+1/-1) src/internal/class.h (+2/-2) src/internal/class_info.h (+3/-3) src/internal/function.h (+2/-2) src/internal/require.h (+69/-40) src/module.h (+2/-2) src/run.h (+8/-5) tests/errors/test.cpp (+20/-0) tests/run/scripts/test.js (+1/-1) tests/run/scripts/test2.js (+1/-1) |
To merge this branch: | bzr merge lp:~marcustomlinson/v8-cpp/lp-1474858 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Marcus Tomlinson | Pending | ||
Review via email: mp+264999@code.launchpad.net |
Commit message
Fixed require() to load modules relative to script path
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'example/module.cpp' | |||
2 | --- example/module.cpp 2015-07-08 06:20:26 +0000 | |||
3 | +++ example/module.cpp 2015-07-16 14:32:42 +0000 | |||
4 | @@ -136,5 +136,5 @@ | |||
5 | 136 | exports->SetPrototype(module.create_prototype()); | 136 | exports->SetPrototype(module.create_prototype()); |
6 | 137 | } | 137 | } |
7 | 138 | 138 | ||
9 | 139 | NODE_MODULE(addon, InitAll) | 139 | ///!NODE_MODULE(addon, InitAll) |
10 | 140 | V8CPP_MODULE(addon, InitAll) | 140 | V8CPP_MODULE(addon, InitAll) |
11 | 141 | 141 | ||
12 | === modified file 'src/internal/class.h' | |||
13 | --- src/internal/class.h 2015-06-23 08:40:22 +0000 | |||
14 | +++ src/internal/class.h 2015-07-16 14:32:42 +0000 | |||
15 | @@ -192,10 +192,10 @@ | |||
16 | 192 | { | 192 | { |
17 | 193 | return args.GetReturnValue().Set(instance(isolate).export_object(args)); | 193 | return args.GetReturnValue().Set(instance(isolate).export_object(args)); |
18 | 194 | } | 194 | } |
20 | 195 | catch (std::exception const& ex) | 195 | catch (std::exception const& e) |
21 | 196 | { | 196 | { |
22 | 197 | auto exception = | 197 | auto exception = |
24 | 198 | isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, ex.what()))); | 198 | isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, e.what()))); |
25 | 199 | args.GetReturnValue().Set(exception); | 199 | args.GetReturnValue().Set(exception); |
26 | 200 | } | 200 | } |
27 | 201 | }); | 201 | }); |
28 | 202 | 202 | ||
29 | === modified file 'src/internal/class_info.h' | |||
30 | --- src/internal/class_info.h 2015-07-02 09:52:54 +0000 | |||
31 | +++ src/internal/class_info.h 2015-07-16 14:32:42 +0000 | |||
32 | @@ -42,7 +42,7 @@ | |||
33 | 42 | 42 | ||
34 | 43 | using CastFunction = void* (*)(void*); | 43 | using CastFunction = void* (*)(void*); |
35 | 44 | 44 | ||
37 | 45 | void add_base_class(ClassInfo* info, CastFunction cast) | 45 | inline void add_base_class(ClassInfo* info, CastFunction cast) |
38 | 46 | { | 46 | { |
39 | 47 | auto it = std::find_if(base_classes_.begin(), base_classes_.end(), [info](BaseClassInfo const& base_class) | 47 | auto it = std::find_if(base_classes_.begin(), base_classes_.end(), [info](BaseClassInfo const& base_class) |
40 | 48 | { | 48 | { |
41 | @@ -55,7 +55,7 @@ | |||
42 | 55 | } | 55 | } |
43 | 56 | } | 56 | } |
44 | 57 | 57 | ||
46 | 58 | bool cast(void*& ptr, size_t type) const | 58 | inline bool cast(void*& ptr, size_t type) const |
47 | 59 | { | 59 | { |
48 | 60 | // Type already matches | 60 | // Type already matches |
49 | 61 | if (type == type_) | 61 | if (type == type_) |
50 | @@ -111,7 +111,7 @@ | |||
51 | 111 | } | 111 | } |
52 | 112 | 112 | ||
53 | 113 | protected: | 113 | protected: |
55 | 114 | static size_t register_class() | 114 | inline static size_t register_class() |
56 | 115 | { | 115 | { |
57 | 116 | static size_t next_index = 0; | 116 | static size_t next_index = 0; |
58 | 117 | return next_index++; | 117 | return next_index++; |
59 | 118 | 118 | ||
60 | === modified file 'src/internal/function.h' | |||
61 | --- src/internal/function.h 2015-07-16 13:04:34 +0000 | |||
62 | +++ src/internal/function.h 2015-07-16 14:32:42 +0000 | |||
63 | @@ -102,9 +102,9 @@ | |||
64 | 102 | { | 102 | { |
65 | 103 | forward_invoke<F>(args); | 103 | forward_invoke<F>(args); |
66 | 104 | } | 104 | } |
68 | 105 | catch (std::exception const& ex) | 105 | catch (std::exception const& e) |
69 | 106 | { | 106 | { |
71 | 107 | auto exception = isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, ex.what()))); | 107 | auto exception = isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, e.what()))); |
72 | 108 | args.GetReturnValue().Set(exception); | 108 | args.GetReturnValue().Set(exception); |
73 | 109 | } | 109 | } |
74 | 110 | } | 110 | } |
75 | 111 | 111 | ||
76 | === modified file 'src/internal/require.h' | |||
77 | --- src/internal/require.h 2015-07-16 08:05:48 +0000 | |||
78 | +++ src/internal/require.h 2015-07-16 14:32:42 +0000 | |||
79 | @@ -29,7 +29,6 @@ | |||
80 | 29 | 29 | ||
81 | 30 | using ModuleInitFunc = void(v8::Handle<v8::Object> exports); | 30 | using ModuleInitFunc = void(v8::Handle<v8::Object> exports); |
82 | 31 | ///!ModuleInitFunc* node_init_func_; | 31 | ///!ModuleInitFunc* node_init_func_; |
83 | 32 | ///!std::shared_ptr<std::string> v8cpp_script_path_; | ||
84 | 33 | 32 | ||
85 | 34 | struct NodeModule | 33 | struct NodeModule |
86 | 35 | { | 34 | { |
87 | @@ -62,27 +61,29 @@ | |||
88 | 62 | public: | 61 | public: |
89 | 63 | inline static void log(v8::FunctionCallbackInfo<v8::Value> const& args) | 62 | inline static void log(v8::FunctionCallbackInfo<v8::Value> const& args) |
90 | 64 | { | 63 | { |
91 | 64 | v8::Isolate* isolate = args.GetIsolate(); | ||
92 | 65 | |||
93 | 65 | for (int i = 0; i < args.Length(); ++i) | 66 | for (int i = 0; i < args.Length(); ++i) |
94 | 66 | { | 67 | { |
95 | 67 | if (args[i]->IsUint32()) | 68 | if (args[i]->IsUint32()) |
96 | 68 | { | 69 | { |
98 | 69 | std::cout << v8cpp::from_v8<unsigned int>(v8::Isolate::GetCurrent(), args[i]); | 70 | std::cout << v8cpp::from_v8<unsigned int>(isolate, args[i]); |
99 | 70 | } | 71 | } |
100 | 71 | else if (args[i]->IsInt32()) | 72 | else if (args[i]->IsInt32()) |
101 | 72 | { | 73 | { |
103 | 73 | std::cout << v8cpp::from_v8<int>(v8::Isolate::GetCurrent(), args[i]); | 74 | std::cout << v8cpp::from_v8<int>(isolate, args[i]); |
104 | 74 | } | 75 | } |
105 | 75 | else if (args[i]->IsNumber()) | 76 | else if (args[i]->IsNumber()) |
106 | 76 | { | 77 | { |
108 | 77 | std::cout << v8cpp::from_v8<float>(v8::Isolate::GetCurrent(), args[i]); | 78 | std::cout << v8cpp::from_v8<float>(isolate, args[i]); |
109 | 78 | } | 79 | } |
110 | 79 | else if (args[i]->IsBoolean()) | 80 | else if (args[i]->IsBoolean()) |
111 | 80 | { | 81 | { |
113 | 81 | std::cout << v8cpp::from_v8<bool>(v8::Isolate::GetCurrent(), args[i]); | 82 | std::cout << v8cpp::from_v8<bool>(isolate, args[i]); |
114 | 82 | } | 83 | } |
115 | 83 | else if (args[i]->IsString()) | 84 | else if (args[i]->IsString()) |
116 | 84 | { | 85 | { |
118 | 85 | std::cout << v8cpp::from_v8<std::string>(v8::Isolate::GetCurrent(), args[i]); | 86 | std::cout << v8cpp::from_v8<std::string>(isolate, args[i]); |
119 | 86 | } | 87 | } |
120 | 87 | } | 88 | } |
121 | 88 | std::cout << std::endl; | 89 | std::cout << std::endl; |
122 | @@ -90,50 +91,78 @@ | |||
123 | 90 | } | 91 | } |
124 | 91 | }; | 92 | }; |
125 | 92 | 93 | ||
127 | 93 | inline v8::Local<v8::Object> require(std::string const& module_path) | 94 | class Require |
128 | 94 | { | 95 | { |
131 | 95 | ///!node_init_func_ = nullptr; | 96 | public: |
132 | 96 | std::string script_path; ///! = v8cpp_script_path_ ? *v8cpp_script_path_ : ""; | 97 | explicit Require(std::string const& script_path) |
133 | 98 | : script_path_(script_path) {} | ||
134 | 97 | 99 | ||
139 | 98 | // Try append ".node" to module_path | 100 | inline static void require(v8::FunctionCallbackInfo<v8::Value> const& args) |
136 | 99 | std::string suffixed_module_path = script_path + module_path + ".node"; | ||
137 | 100 | auto module = dlopen(suffixed_module_path.c_str(), RTLD_LAZY); | ||
138 | 101 | if (!module) | ||
140 | 102 | { | 101 | { |
145 | 103 | // Didn't work, now try append ".so" to module_path | 102 | v8::Isolate* isolate = args.GetIsolate(); |
146 | 104 | suffixed_module_path = script_path + module_path + ".so"; | 103 | v8::EscapableHandleScope scope(isolate); |
147 | 105 | module = dlopen(suffixed_module_path.c_str(), RTLD_LAZY); | 104 | |
148 | 106 | if (!module) | 105 | try |
149 | 107 | { | 106 | { |
153 | 108 | // Still didn't work, just try module_path as is | 107 | Require* this_ = internal::import_value<Require*>(args.Data()); |
154 | 109 | suffixed_module_path = script_path + module_path; | 108 | |
155 | 110 | module = dlopen(suffixed_module_path.c_str(), RTLD_LAZY); | 109 | std::string module_path = from_v8<std::string>(isolate, args[0], ""); |
156 | 110 | if (module_path.empty()) | ||
157 | 111 | { | ||
158 | 112 | throw std::runtime_error("require() call missing string argument"); | ||
159 | 113 | } | ||
160 | 114 | |||
161 | 115 | ///!node_init_func_ = nullptr; | ||
162 | 116 | |||
163 | 117 | // Try append ".node" to module_path | ||
164 | 118 | std::string suffixed_module_path = this_->script_path_ + module_path + ".node"; | ||
165 | 119 | auto module = dlopen(suffixed_module_path.c_str(), RTLD_LAZY); | ||
166 | 111 | if (!module) | 120 | if (!module) |
167 | 112 | { | 121 | { |
169 | 113 | throw std::runtime_error("dlopen failed: " + std::string(dlerror())); | 122 | // Didn't work, now try append ".so" to module_path |
170 | 123 | suffixed_module_path = this_->script_path_ + module_path + ".so"; | ||
171 | 124 | module = dlopen(suffixed_module_path.c_str(), RTLD_LAZY); | ||
172 | 125 | if (!module) | ||
173 | 126 | { | ||
174 | 127 | // Still didn't work, just try module_path as is | ||
175 | 128 | suffixed_module_path = this_->script_path_ + module_path; | ||
176 | 129 | module = dlopen(suffixed_module_path.c_str(), RTLD_LAZY); | ||
177 | 130 | if (!module) | ||
178 | 131 | { | ||
179 | 132 | throw std::runtime_error("dlopen failed: " + std::string(dlerror())); | ||
180 | 133 | } | ||
181 | 134 | } | ||
182 | 114 | } | 135 | } |
183 | 136 | |||
184 | 137 | v8::Local<v8::Object> exports = v8::Object::New(isolate); | ||
185 | 138 | |||
186 | 139 | ///!if (node_init_func_) | ||
187 | 140 | ///!{ | ||
188 | 141 | ///! node_init_func_(exports); | ||
189 | 142 | ///!} | ||
190 | 143 | ///!else | ||
191 | 144 | ///!{ | ||
192 | 145 | auto v8cpp_init_func = (ModuleInitFunc*)dlsym(module, "init_module"); | ||
193 | 146 | if (!v8cpp_init_func) | ||
194 | 147 | { | ||
195 | 148 | throw std::runtime_error("dlsym failed: " + std::string(dlerror())); | ||
196 | 149 | } | ||
197 | 150 | |||
198 | 151 | v8cpp_init_func(exports); | ||
199 | 152 | ///!} | ||
200 | 153 | |||
201 | 154 | args.GetReturnValue().Set(scope.Escape(exports)); | ||
202 | 155 | } | ||
203 | 156 | catch (std::exception const& e) | ||
204 | 157 | { | ||
205 | 158 | auto exception = isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, e.what()))); | ||
206 | 159 | args.GetReturnValue().Set(scope.Escape(exception)); | ||
207 | 115 | } | 160 | } |
208 | 116 | } | 161 | } |
209 | 117 | 162 | ||
229 | 118 | v8::Local<v8::Object> exports = v8::Object::New(v8::Isolate::GetCurrent()); | 163 | private: |
230 | 119 | 164 | std::string script_path_; | |
231 | 120 | ///! if (node_init_func_) | 165 | }; |
213 | 121 | ///! { | ||
214 | 122 | ///! node_init_func_(exports); | ||
215 | 123 | ///! } | ||
216 | 124 | ///! else | ||
217 | 125 | ///! { | ||
218 | 126 | auto v8cpp_init_func = (ModuleInitFunc*)dlsym(module, "init_module"); | ||
219 | 127 | if (!v8cpp_init_func) | ||
220 | 128 | { | ||
221 | 129 | throw std::runtime_error("dlsym failed: " + std::string(dlerror())); | ||
222 | 130 | } | ||
223 | 131 | |||
224 | 132 | v8cpp_init_func(exports); | ||
225 | 133 | ///! } | ||
226 | 134 | |||
227 | 135 | return exports; | ||
228 | 136 | } | ||
232 | 137 | 166 | ||
233 | 138 | } // namespace internal | 167 | } // namespace internal |
234 | 139 | } // namespace v8cpp | 168 | } // namespace v8cpp |
235 | 140 | 169 | ||
236 | === modified file 'src/module.h' | |||
237 | --- src/module.h 2015-06-18 12:32:56 +0000 | |||
238 | +++ src/module.h 2015-07-16 14:32:42 +0000 | |||
239 | @@ -53,12 +53,12 @@ | |||
240 | 53 | } | 53 | } |
241 | 54 | 54 | ||
242 | 55 | // Create an instance of this module in V8 | 55 | // Create an instance of this module in V8 |
244 | 56 | v8::Local<v8::Object> create_prototype() | 56 | inline v8::Local<v8::Object> create_prototype() |
245 | 57 | { | 57 | { |
246 | 58 | return object_template_->NewInstance(); | 58 | return object_template_->NewInstance(); |
247 | 59 | } | 59 | } |
248 | 60 | 60 | ||
250 | 61 | v8::Handle<v8::ObjectTemplate> object_template() | 61 | inline v8::Handle<v8::ObjectTemplate> object_template() |
251 | 62 | { | 62 | { |
252 | 63 | return object_template_; | 63 | return object_template_; |
253 | 64 | } | 64 | } |
254 | 65 | 65 | ||
255 | === modified file 'src/run.h' | |||
256 | --- src/run.h 2015-07-15 13:18:16 +0000 | |||
257 | +++ src/run.h 2015-07-16 14:32:42 +0000 | |||
258 | @@ -45,8 +45,6 @@ | |||
259 | 45 | delete instances; | 45 | delete instances; |
260 | 46 | isolate->SetData(0, nullptr); | 46 | isolate->SetData(0, nullptr); |
261 | 47 | isolate->Dispose(); | 47 | isolate->Dispose(); |
262 | 48 | |||
263 | 49 | ///!internal::v8cpp_script_path_.reset(); | ||
264 | 50 | }); | 48 | }); |
265 | 51 | 49 | ||
266 | 52 | // Create an isolate scope. | 50 | // Create an isolate scope. |
267 | @@ -67,13 +65,17 @@ | |||
268 | 67 | v8::Context::Scope context_scope(v8::Context::New(isolate.get())); | 65 | v8::Context::Scope context_scope(v8::Context::New(isolate.get())); |
269 | 68 | 66 | ||
270 | 69 | // Store the script filename for use in require() later | 67 | // Store the script filename for use in require() later |
271 | 68 | std::string script_path; | ||
272 | 70 | std::size_t found = filename.find_last_of("/"); | 69 | std::size_t found = filename.find_last_of("/"); |
273 | 71 | if (found != std::string::npos) | 70 | if (found != std::string::npos) |
274 | 72 | { | 71 | { |
276 | 73 | ///!internal::v8cpp_script_path_ = std::make_shared<std::string>(filename.substr(0, found) + "/"); | 72 | script_path = filename.substr(0, found) + "/"; |
277 | 74 | } | 73 | } |
278 | 75 | 74 | ||
280 | 76 | module.add_function("require", &internal::require); | 75 | v8::Handle<v8::Value> require = internal::export_value(isolate.get(), new internal::Require(script_path)); |
281 | 76 | module.object_template()->Set(isolate.get(), "require", | ||
282 | 77 | v8::FunctionTemplate::New(isolate.get(), internal::Require::require, require)); | ||
283 | 78 | |||
284 | 77 | module.add_class("console", console); | 79 | module.add_class("console", console); |
285 | 78 | } | 80 | } |
286 | 79 | v8::Local<v8::Context> context = v8::Context::New(isolate.get(), nullptr, module.object_template()); | 81 | v8::Local<v8::Context> context = v8::Context::New(isolate.get(), nullptr, module.object_template()); |
287 | @@ -82,7 +84,8 @@ | |||
288 | 82 | v8::Context::Scope context_scope(context); | 84 | v8::Context::Scope context_scope(context); |
289 | 83 | 85 | ||
290 | 84 | // Compile the script. | 86 | // Compile the script. |
292 | 85 | v8::Local<v8::Script> script = v8::Script::Compile(v8cpp::to_v8(isolate.get(), source), v8cpp::to_v8(isolate.get(), filename)); | 87 | v8::Local<v8::Script> script = v8::Script::Compile(v8cpp::to_v8(isolate.get(), source), |
293 | 88 | v8cpp::to_v8(isolate.get(), filename)); | ||
294 | 86 | 89 | ||
295 | 87 | // Run the script. | 90 | // Run the script. |
296 | 88 | if (script.IsEmpty()) | 91 | if (script.IsEmpty()) |
297 | 89 | 92 | ||
298 | === modified file 'tests/errors/test.cpp' | |||
299 | --- tests/errors/test.cpp 2015-07-08 09:29:21 +0000 | |||
300 | +++ tests/errors/test.cpp 2015-07-16 14:32:42 +0000 | |||
301 | @@ -22,6 +22,26 @@ | |||
302 | 22 | 22 | ||
303 | 23 | #include <gtest/gtest.h> | 23 | #include <gtest/gtest.h> |
304 | 24 | 24 | ||
305 | 25 | TEST(Test, empty_module_path) | ||
306 | 26 | { | ||
307 | 27 | try | ||
308 | 28 | { | ||
309 | 29 | v8cpp::run_script("require()"); | ||
310 | 30 | } | ||
311 | 31 | catch (std::exception const& e) | ||
312 | 32 | { | ||
313 | 33 | EXPECT_STREQ(e.what(), "Uncaught Error: require() call missing string argument"); | ||
314 | 34 | } | ||
315 | 35 | try | ||
316 | 36 | { | ||
317 | 37 | v8cpp::run_script("require('')"); | ||
318 | 38 | } | ||
319 | 39 | catch (std::exception const& e) | ||
320 | 40 | { | ||
321 | 41 | EXPECT_STREQ(e.what(), "Uncaught Error: require() call missing string argument"); | ||
322 | 42 | } | ||
323 | 43 | } | ||
324 | 44 | |||
325 | 25 | TEST(Test, non_existent_module) | 45 | TEST(Test, non_existent_module) |
326 | 26 | { | 46 | { |
327 | 27 | try | 47 | try |
328 | 28 | 48 | ||
329 | === modified file 'tests/run/scripts/test.js' | |||
330 | --- tests/run/scripts/test.js 2015-07-15 13:18:16 +0000 | |||
331 | +++ tests/run/scripts/test.js 2015-07-16 14:32:42 +0000 | |||
332 | @@ -16,6 +16,6 @@ | |||
333 | 16 | * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> | 16 | * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
334 | 17 | */ | 17 | */ |
335 | 18 | 18 | ||
337 | 19 | var module = require("./test-run-module"); ///! ../ | 19 | var module = require("../test-run-module"); |
338 | 20 | var test_object = new module.TestClass(1, 2); | 20 | var test_object = new module.TestClass(1, 2); |
339 | 21 | test_object; | 21 | test_object; |
340 | 22 | 22 | ||
341 | === modified file 'tests/run/scripts/test2.js' | |||
342 | --- tests/run/scripts/test2.js 2015-07-15 13:18:16 +0000 | |||
343 | +++ tests/run/scripts/test2.js 2015-07-16 14:32:42 +0000 | |||
344 | @@ -21,5 +21,5 @@ | |||
345 | 21 | console.log(true, " > ", false); | 21 | console.log(true, " > ", false); |
346 | 22 | console.log("hello", " ", "there"); | 22 | console.log("hello", " ", "there"); |
347 | 23 | 23 | ||
349 | 24 | var module = require("./test-run-module"); ///! ../ | 24 | var module = require("../test-run-module"); |
350 | 25 | new module.TestClass(3, 4); | 25 | new module.TestClass(3, 4); |