Skip to content

Instantly share code, notes, and snippets.

@dannvix
Created April 2, 2019 15:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dannvix/0f4d1afc41a44d47eeb14987542a355e to your computer and use it in GitHub Desktop.
Save dannvix/0f4d1afc41a44d47eeb14987542a355e to your computer and use it in GitHub Desktop.
Cross-context JavaScript function invocation with embedded Google V8
#include "v8/libplatform/libplatform.h"
#include "v8/v8.h"
#include <iostream>
#pragma comment(lib, "v8_monolith")
int main() {
auto platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
v8::Isolate::CreateParams params;
params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
v8::Isolate *isolate = v8::Isolate::New(params);
v8::Persistent<v8::Function> isArrayBuffer;
auto const consoleLogCallback = [](auto const& args) {
std::cout << static_cast<char*>(
*v8::String::Utf8Value(args.GetIsolate(), args[0])) << std::endl;
};
auto const v8StringFromUtf8 = [isolate](char const * const str) {
return v8::String::NewFromUtf8(isolate, str,
v8::NewStringType::kNormal).ToLocalChecked();
};
auto const runRoutineInNewContext = [&platform, isolate](auto routine) {
v8::Isolate::Scope isolateScope(isolate);
v8::HandleScope handleScope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope contextScope(context);
routine(context);
while (v8::platform::PumpMessageLoop(platform.get(), isolate));
};
auto const getGlobalProperty = [&](auto &context, auto name) {
return context->Global()->GetRealNamedProperty(
context, v8StringFromUtf8(name)).ToLocalChecked();
};
// --- C o n t e x t # 1 ---
runRoutineInNewContext([&](auto &context) {
getGlobalProperty(context, "console").As<v8::Object>()
->Set(context, v8StringFromUtf8("log"),
v8::Function::New(isolate, consoleLogCallback));
v8::Script::Compile(context, v8StringFromUtf8(R"JS(
// (A)
function isArrayBuffer(x) {
console.log(x.constructor.toString()); // (1)
console.log(x.constructor === ArrayBuffer); // (2)
let y = new ArrayBuffer();
console.log(y.constructor.toString()); // (3)
console.log(y.constructor === ArrayBuffer); // (4)
}
)JS")).ToLocalChecked()->Run(context);
isArrayBuffer.Reset(isolate,
getGlobalProperty(context, "isArrayBuffer").As<v8::Function>());
});
// --- C o n t e x t # 2 ---
runRoutineInNewContext([&](auto &context) {
context->Global()->Set(context,
v8StringFromUtf8("isArrayBuffer"),
v8::Local<v8::Function>::New(isolate, isArrayBuffer));
v8::Script::Compile(context, v8StringFromUtf8(R"JS(
// (B)
isArrayBuffer(new ArrayBuffer());
)JS")).ToLocalChecked()->Run(context);
});
//
// ---- C o n s o l e O u t p u t ----
//
// (1) // function ArrayBuffer() { [native code] }
// (2) // false
// (3) // function ArrayBuffer() { [native code] }
// (4) // true
//
isolate->Dispose();
v8::V8::Dispose();
v8::V8::ShutdownPlatform();
delete params.array_buffer_allocator;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment