
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
Header-only library to expose C++ classes and functions into V8 to use them in JavaScript code. v8pp requires a compiler with C++17 support. The library has been tested on:
The library has a set of tests that can be configured, built, and run with CMake:
~/v8pp$ mkdir out; cd out
~/v8pp/out$ cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON ..
~/v8pp/out$ make
~/v8pp/out$ ctest -V
The full list of project options can be listed with cmake command:
~/v8pp/out$ cmake -LH ..
Some of them could be:
// Build documentation BUILD_DOCUMENTATION:BOOL=OFF
// Build shared library BUILD_SHARED_LIBS:BOOL=ON
// Build and run tests BUILD_TESTING:BOOL=OFF
// Header-only library V8PP_HEADER_ONLY:BOOL=0
// v8::Isolate data slot number, used in v8pp for shared data V8PP_ISOLATE_DATA_SLOT:STRING=0
// v8pp plugin initialization procedure name V8PP_PLUGIN_INIT_PROC_NAME:STRING=v8pp_module_init
// v8pp plugin filename suffix V8PP_PLUGIN_SUFFIX:STRING=.dylib
// Use new V8 ABI with V8_COMPRESS_POINTERS and V8_31BIT_SMIS_ON_64BIT_ARCH V8_COMPRESS_POINTERS:BOOL=ON
v8pp supports V8 versions after 6.3 with v8::Isolate usage in API. There are 2 targets for binding:
v8pp::module, a wrapper class around v8::ObjectTemplatev8pp::class_, a template class wrapper around v8::FunctionTemplateBoth of them require a pointer to v8::Isolate instance. They allows to bind from C++ code such items as variables, functions, constants with a function set(name, item):
v8::Isolate* isolate;
int var;
int get_var() { return var + 1; }
void set_var(int x) { var = x + 1; }
struct X
{
X(int v, bool u) : var(v) {}
int var;
int get() const { return var; }
void set(int x) { var = x; }
};
// bind free variables and functions
v8pp::module mylib(isolate);
mylib
// set read-only attribute
.const_("PI", 3.1415)
// set variable available in JavaScript with name `var`
.var("var", var)
// set function get_var as `fun`
.function("fun", &get_var)
// set property `prop` with getter get_var() and setter set_var()
.property("prop", get_var, set_var);
// bind class
v8pp::class_<X> X_class(isolate);
X_class
// specify X constructor signature
.ctor<int, bool>()
// bind variable
.var("var", &X::var)
// bind function
.function("fun", &X::set)
// bind read-only property
.property("prop",&X::get);
// set class into the module template
mylib.class_("X", X_class);
// set bindings in global object as `mylib`
isolate->GetCurrentContext()->Global()->Set(
v8::String::NewFromUtf8(isolate, "mylib"), mylib.new_instance());
After that bindings will be available in JavaScript:
mylib.var = mylib.PI + mylib.fun();
var x = new mylib.X(1, true);
mylib.prop = x.prop + x.fun();
The library is suitable to make Node.js and io.js addons. See addons document.
void RegisterModule(v8::Local<v8::Object> exports)
{
v8pp::module addon(v8::Isolate::GetCurrent());
// set bindings...
addon
.function("fun", &function)
.class_("cls", my_class)
;
// set bindings as exports object prototype
exports->SetPrototype(addon.new_instance());
}
v8pp - a static library to add several global functions (load/require to the v8 JavaScript context. require() is a system for loading plugins from shared libraries.test - A binary for running JavaScript files in a context which has v8pp module loading functions provided.#include <iostream>
#include <v8pp/module.hpp>
namespace console {
void 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 str(args[i]);
std::cout << *str;
}
std::cout << std::endl;
}
v8::Local<v8::Value> init(v8::Isolate* isolate)
{
v8pp::module m(isolate);
m.function("log", &log);
return m.new_instance();
}
} // namespace console
V8PP_PLUGIN_INIT(v8::Isolate* isolate)
{
return console::init(isolate);
}
#include <v8pp/module.hpp>
#include <v8pp/class.hpp>
#include <fstream>
namespace file {
bool rename(char const* src, char const* dest)
{
return std::rename(src, dest) == 0;
}
class file_base
{
public:
bool is_open() const { return stream_.is_open(); }
bool good() const { return stream_.good(); }
bool eof() const { return stream_.eof(); }
void close() { stream_.close(); }
protected:
std::fstream stream_;
};
class file_writer : public file_base
{
public:
explicit file_writer(v8::FunctionCallbackInfo<v8::Value> const& args)
{
if (args.Length() == 1)
{
v8::String::Utf8Value str(args[0]);
open(*str);
}
}
bool open(char const* path)
{
stream_.open(path, std::ios_base::out);
return stream_.good();
}
void print(v8::FunctionCallbackInfo<v8::Value> const& args)
{
v8::HandleScope scope(args.GetIsolate());
for (int i = 0; i < args.Length(); ++i)
{
if (i > 0) stream_ << ' ';
v8::String::Utf8Value str(args[i]);
stream_ << *str;
}
}
void println(v8::FunctionCallbackInfo<v8::Value> const& args)
{
print(args);
stream_ << std::endl;
}
};
class file_reader : public file_base
{
public:
explicit file_reader(char const* path)
{
open(path);
}
bool open(const char* path)
{
stream_.open(path, std::ios_base::in);
return stream_.good();
}
v8::Local<v8::Value> getline(v8::Isolate* isolate)
{
if ( stream_.good() && ! stream_.eof())
{
std::string line;
std::getline(stream_, line);
return v8pp::to_v8(isolate, line);
}
else
{
return v8::Undefined(isolate);
}
}
};
v8::Local<v8::Value> init(v8::Isolate* isolate)
{
v8::EscapableHandleScope scope(isolate);
// file_base binding, no .ctor() specified, object creation disallowed in JavaScript
v8pp::class_<file_base> file_base_class(isolate);
file_base_class
.function("close", &file_base::close)
.function("good", &file_base::good)
.function("is_open", &file_base::is_open)
.function("eof", &file_base::eof)
;
// .ctor<> template arguments declares types of file_writer constructor
// file_writer inherits from file_base_class
v8pp::class_<file_writer> file_writer_class(isolate);
file_writer_class
.ctor<v8::FunctionCallbackInfo<v8::Value> const&>()
.inherit<file_base>()
.function("open", &file_writer::open)
.function("print", &file_writer::print)
.function("println", &file_writer::println)
;
// .ctor<> template arguments declares types of file_reader constructor.
// file_base inherits from file_base_class
v8pp::class_<file_reader> file_reader_class(isolate);
file_reader_class
.ctor<char const*>()
.inherit<file_base>()
.function("open", &file_reader::open)
.function("getln", &file_reader::getline)
;
// Create a module to add classes and functions to and return a
// new instance of the module to be embedded into the v8 context
v8pp::module m(isolate);
m.function("rename", &rename)
.class_("writer", file_writer_class)
.class_("reader", file_reader_class)
;
return scope.Escape(m.new_instance());
}
} // namespace file
V8PP_PLUGIN_INIT(v8::Isolate* isolate)
{
return file::init(isolate);
}
#include <v8pp/context.hpp>
v8pp::context context;
context.set_lib_path("path/to/plugins/lib");
// script can now use require() function. An application
// that uses v8pp::context must link against v8pp library.
v8::HandleScope scope(context.isolate());
context.run_file("some_file.js");
// Load the file module from the class binding example and the
// console module.
var file = require('file'),
console = require('console')
var writer = new file.writer("file")
if (writer.is_open()) {
writer.println("some text")
writer.close()
if (! file.rename("file", "newfile"))
console.log("could not rename file")
}
else console.log("could not open `file'")
console.log("exit")
// Memory for C++ class will remain when JavaScript object is deleted.
// Useful for classes you only wish to inject.
typedef v8pp::class_<my_class> my_class_wrapper;
v8::Local<v8::Value> val = my_class_wrapper::reference_external(isolate, &my_class::instance());
// Assuming my_class::instance() returns reference to class
// Memory for c++ object will be reclaimed by JavaScript using "delete" when
// JavaScript class is deleted.
typedef v8pp::class_<my_class> my_class_wrapper;
v8::Local<v8::Value> val = my_class_wrapper::import_external(isolate, new my_class);
The library uses several preprocessor macros, defined in v8pp/config.hpp file:
V8PP_ISOLATE_DATA_SLOT - A v8::Isolate data slot number, used to store v8pp internal dataV8PP_PLUGIN_INIT_PROC_NAME - Plugin initialization procedure name that should be exported from a v8pp plugin.V8PP_PLUGIN_SUFFIX - Plugin filename suffix that would be added if the plugin name used in require() doesn't end with it.V8PP_HEADER_ONLY - Use header-only implemenation, enabled by default.FAQs
C++ bindings for V8
We found that v8pp demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.