Created
April 2, 2019 15:16
-
-
Save dannvix/0f4d1afc41a44d47eeb14987542a355e to your computer and use it in GitHub Desktop.
Cross-context JavaScript function invocation with embedded Google V8
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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