Skip to content

Instantly share code, notes, and snippets.

@rayburgemeestre
Last active January 11, 2017 08:15
Show Gist options
  • Save rayburgemeestre/c0abd528f6f67edbfe686d484c45ddbb to your computer and use it in GitHub Desktop.
Save rayburgemeestre/c0abd528f6f67edbfe686d484c45ddbb to your computer and use it in GitHub Desktop.
V8 stackoverflow question
/*
In my case, compile with:
/usr/bin/c++ --std=c++14 -I${PWD}/include testcase2.cpp -o testcase -L$PWD/lib $PWD/lib/libv8_base.a -lv8_libbase $PWD/lib/libv8_nosnapshot.a -lv8_libplatform $PWD/lib/libv8_libsampler.a -licui18n -licuuc -Wl,-rpath,$PWD/lib -pthread
Run with ./testcase
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "include/libplatform/libplatform.h"
#include "include/v8.h"
#include <iostream>
#include <string>
using namespace v8;
void construct_with_non_ec6_syntax(const FunctionCallbackInfo<Value>& args) {
Handle<Object> global = args.GetIsolate()->GetCurrentContext()->Global();
std::string newvecfunc = "some_non_ec6_class";
Handle<Value> value = global->Get(String::NewFromUtf8(args.GetIsolate(), newvecfunc.c_str(), String::kNormalString, newvecfunc.length()));
Local<Value> result;
if (value->IsFunction()) {
Handle<Function> func = Handle<Function>::Cast(value);
Handle<Value> args2[2];
args2[0] = Number::New(args.GetIsolate(), 111);
args2[1] = Number::New(args.GetIsolate(), 222);
result = func->CallAsConstructor(args.GetIsolate()->GetCurrentContext(), 2, args2).ToLocalChecked();
}
args.GetReturnValue().Set(result);
}
void construct_with_ec6_syntax(const FunctionCallbackInfo<Value>& args) {
Handle<Object> global = args.GetIsolate()->GetCurrentContext()->Global();
std::string newvecfunc = "some_ec6_class";
Handle<Value> value = global->Get(String::NewFromUtf8(args.GetIsolate(), newvecfunc.c_str(), String::kNormalString, newvecfunc.length()));
Local<Value> result;
if (value->IsFunction()) {
Handle<Function> func = Handle<Function>::Cast(value);
Handle<Value> args2[2];
args2[0] = Number::New(args.GetIsolate(), 111);
args2[1] = Number::New(args.GetIsolate(), 222);
result = func->CallAsConstructor(args.GetIsolate()->GetCurrentContext(), 2, args2).ToLocalChecked();
}
args.GetReturnValue().Set(result);
}
int main(int argc, char* argv[]) {
// Initialize V8.
V8::InitializeICUDefaultLocation(argv[0]);
V8::InitializeExternalStartupData(argv[0]);
Platform* platform = platform::CreateDefaultPlatform();
V8::InitializePlatform(platform);
V8::Initialize();
// Create a new Isolate and make it the current one.
Isolate::CreateParams create_params;
create_params.array_buffer_allocator = ArrayBuffer::Allocator::NewDefaultAllocator();
Isolate* isolate = Isolate::New(create_params);
{
Isolate::Scope isolate_scope(isolate);
HandleScope handle_scope(isolate);
Local<Context> context = Context::New(isolate);
Context::Scope context_scope(context);
// Expose a C++ function to V8
Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
auto ftpl = FunctionTemplate::New(isolate, construct_with_non_ec6_syntax);
global->Set(String::NewFromUtf8(isolate, "construct_with_non_ec6_syntax", NewStringType::kNormal).ToLocalChecked(), ftpl);
auto ftpl2 = FunctionTemplate::New(isolate, construct_with_ec6_syntax);
global->Set(String::NewFromUtf8(isolate, "construct_with_ec6_syntax", NewStringType::kNormal).ToLocalChecked(), ftpl2);
context = Context::New(isolate, NULL, global);
// Using non EC6 syntax
{
// Compile and run test function
Local<String> source = String::NewFromUtf8(isolate, "function some_non_ec6_class(x, y) { this.result = x + y; };", NewStringType::kNormal).ToLocalChecked();
Local<Script> script = Script::Compile(context, source).ToLocalChecked();
Local<Value> result = script->Run(context).ToLocalChecked();
// Invoke test function and print result
Local<String> source2 = String::NewFromUtf8(isolate, "t = construct_with_non_ec6_syntax(); t.result;", NewStringType::kNormal).ToLocalChecked();
Local<Script> script2 = Script::Compile(context, source2).ToLocalChecked();
Local<Value> result2 = script2->Run(context).ToLocalChecked();
String::Utf8Value utf8(result2);
printf("%s\n", *utf8); // prints 333.. which is OK! (111 + 222)
}
// Using EC6 syntax
{
// Compile and run test function
Local<String> source = String::NewFromUtf8(isolate, "class some_ec6_class { constructor(x, y) { this.result = x + y; } };", NewStringType::kNormal).ToLocalChecked();
Local<Script> script = Script::Compile(context, source).ToLocalChecked();
Local<Value> result = script->Run(context).ToLocalChecked();
// Invoke test function, will throw because `t` is undefined..
Local<String> source2 = String::NewFromUtf8(isolate, "t = construct_with_ec6_syntax(); t.result;", NewStringType::kNormal).ToLocalChecked();
Local<Script> script2 = Script::Compile(context, source2).ToLocalChecked();
Local<Value> result2 = script2->Run(context).ToLocalChecked();
String::Utf8Value utf8(result2);
printf("%s\n", *utf8); // should print 333 as well..?
}
}
isolate->Dispose();
V8::Dispose();
V8::ShutdownPlatform();
delete platform;
delete create_params.array_buffer_allocator;
return 0;
}
/**
* Running this program results in the following output;
* -----------------------------------------------------
* 333
* <unknown>:34: Uncaught TypeError: Cannot read property 'result' of undefined
*
* #
* # Fatal error in v8::ToLocalChecked
* # Empty MaybeLocal.
* #
*
* /bin/bash: line 1: 4287 Illegal instruction (core dumped) ./testcase
**/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment