Motivation
I was writing a Node.Js addon and at some point I wanted to return a JavaScript object. The standard approach would have been to create a v8::Object
and define each property using Set (Handle< Value > key, Handle< Value > value, PropertyAttribute attribs=None)
method. However, since I already had my stringified object from a REST-API call, the best case would be just to parse the string to an object and return it.
V8 doesn’t directly expose a C++
utility interface to parse JSON string, but we know that most modern browsers provide the JSON
object in global context (i.e. window.JSON
), which also parses JSON string into objects. The idea is to access the global context of V8 and get a hold of JSON
object and finally call some methods on it.
Approach
The idea is simple: we get our hands on V8 global context. A context is is
an execution environment that allows separate, unrelated, JavaScript applications to run in a single instance of V8. You must explicitly specify the context in which you want any JavaScript code to be run.
Getting the global context is as easy as
Handle<Context> context = Context::GetCurrent();
Handle<Object> global = context->Global();
It can be seen (from Handle<Object>
), that the variable global
represents a JS object. This global object resembles window
object in browser and contains a number of useful utilities. For our use case here, we need to get the JSON
object first. This can easily be done using the v8::Object::Get
method:
Handle<Object> JSON = global->Get(String::New("JSON"))->ToObject();
You could replace "JSON"
with another property name that might be available in the global proxy object (e.g. Int8Array
). Note that a number of objects (such as Int8Array
) are already provided by v8
and there is no need to access them as above.
At this point JSON
is also an object just like global
. Now we don’t want access a property of type object, but function. This is done by accessing the property using Get
and casting it to a v8::Function
using Cast
method:
Local<Value> parse_prop = JSON->Get(String::New("parse"));
Handle<Function> JSON_parse = Handle<Function>::Cast(parse_prop);
Just like any other v8::Function
, JSON_parse
can simply be invoked using the Function::Call
:
std::string some_json_string = "{test: 1}";
JSON_parse->Call(JSON, 1, &some_json_string);
The first argument is the receiver, the second determines the number of arguments, and the third are the actual arguments.