-
Notifications
You must be signed in to change notification settings - Fork 122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Segmentation fault when converting vector of custom type using to_v8 #45
Comments
Hi @zangent, Thanks for reporting, your sample code is pretty clear. The cause of this issue is You are trying to convert unwrapped C++ objects created at line 82: /* Create a vector of MyObject */
std::vector<MyObject> vec = {
MyObject("test.cpp", "int main(){}"),
MyObject("test.hpp", "#pragma once")
}; but There are 2 ways to wrap a C++ object properly in
There is also a similar sample in the recent issue #39. I'm not sure how to prevent similar further issues, probably only by adding an assert in the |
I could be wrong here, but I figured that that was the point of doing this: /* Set up my MyObject class */
v8pp::class_<MyObject> v8_MyObject(isolate);
v8_MyObject
.ctor<std::string, std::string>()
.set("name", &MyObject::name)
.set("contents", &MyObject::contents); Do I also have to specialize v8pp::convert to get this to work? If so, that's fine, but it looked like I wouldn't need to after a glance at the source code. |
No, you don't have to. You either can use I think it's simpler to go the 2nd way for #include <iostream>
#include <vector>
#include <string>
#include <memory>
#include "v8pp/context.hpp"
#include "v8pp/module.hpp"
#include "v8pp/class.hpp"
#include "v8pp/object.hpp"
#include <libplatform/libplatform.h>
void console_log(v8::FunctionCallbackInfo<v8::Value> const& args)
{
v8::HandleScope handle_scope(args.GetIsolate());
for (int i = 0; i < args.Length(); ++i)
{
if (i > 0) std::cout << ' ';
v8::String::Utf8Value const str(args[i]);
std::cout << *str;
}
std::cout << std::endl;
}
struct MyObject {
MyObject(std::string n, std::string c) : name(n), contents(c) {}
std::string name;
std::string contents;
};
// specialize v8pp convert for MyObject struct
template<>
struct v8pp::convert<MyObject>
{
static bool is_valid(v8::Isolate* isolate, v8::Local<v8::Value> const& value)
{
return !value.IsEmpty() && value->IsObject();
}
static MyObject from_v8(v8::Isolate* isolate, v8::Local<v8::Value> const& value)
{
if (!is_valid(isolate, value)) throw std::runtime_error("expected Object");
auto object = value.As<v8::Object>();
std::string name, contents;
if (get_option(isolate, object, "name", name)
&& get_option(isolate, object, "contents", contents))
{
return MyObject(name, contents);
}
throw std::invalid_argument("expected {name, contents} object");
}
static v8::Local<v8::Object> to_v8(v8::Isolate* isolate, MyObject const& value)
{
auto object = v8::Object::New(isolate);
set_option(isolate, object, "name", value.name);
set_option(isolate, object, "contents", value.contents);
return object;
}
};
int main(int argc, const char * argv[])
{
/* Initialize V8. */
v8::V8::InitializeICU();
v8::V8::InitializeExternalStartupData(argv[0]);
std::unique_ptr<v8::Platform> platform(v8::platform::CreateDefaultPlatform());
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
try
{
/* Set up v8pp */
v8pp::context context;
v8::Isolate* isolate = context.isolate();
/* Open handle scope and obtain global object */
v8::HandleScope scope(isolate);
auto global = isolate->GetCurrentContext()->Global();
/* Set up `console.log` */
v8pp::module console(isolate);
console.set("log", &console_log);
v8pp::set_option(isolate, global, "console", console.new_instance());
/* Create a vector of MyObject */
std::vector<MyObject> vec = {
MyObject("test.cpp", "int main(){}"),
MyObject("test.hpp", "#pragma once")
};
/* Convert that vector to a V8 array, v8pp::convert<MyObject> is used instead of v8pp::class_<MyObject> */
auto js_array = v8pp::to_v8(isolate, vec);
/* Convert JS array back to vector of MyObject */
auto const vec2 = v8pp::from_v8<std::vector<MyObject>>(isolate, js_array);
//assert(vec2 == vec);
/* Attempt to pass the V8 array to the script as a global variable */
v8pp::set_option(isolate, global, "test_values", js_array);
/* Run some simple code that uses the vector */
context.run_script("for (let i = 0; i < test_values.length; i++)"
"console.log(test_values[i].name)", "<sample_code>");
}
catch (std::exception & ex)
{
std::cerr << ex.what() << std::endl;
return -1;
}
v8::V8::Dispose();
v8::V8::ShutdownPlatform();
} |
Ah, okay. I knew in the back of my mind that while templates were powerful, they weren't magic. Thanks for sorting this out! Edit: Also, thanks for making V8 development bearable; this library is going to keep me from having a stress heart attack! |
Thanks for using the library, I appreciate such a feedback from real users :) |
One more question, since I couldn't see anything about this myself. static v8::Local<v8::Object> to_v8(v8::Isolate* isolate, file_source_pair const& value) {
auto obj = v8::Object::New(isolate);
set_option(isolate, obj, "name", value.name);
set_option(isolate, obj, "contents", value.contents); is there any way to set a getter/setter here instead of a straight value? I know that in Thanks for your tremendous help, by the way. |
Well, as I understand you can use |
When I use v8pp::to_v8 on a vector containing a custom type (that has been registered as a v8pp::class_) I get a segmentation fault.
There's not much I can say about it, so I'll just provide some "simple" (nothing with V8 is simple, though) sample code that should demonstrate where the issue is. Here's the pastebin upload of it.
Thanks.
The text was updated successfully, but these errors were encountered: