If you've read the Getting Started guide you will already be familiar with using V8 as a standalone virtual machine and with some key V8 concepts such as handles, scopes, and contexts. This document discusses these concepts further and introduces others that are key to embedding V8 within your own C++ application.
The V8
API provides functions for compiling and executing scripts, accessing C++
methods and data structures, handling errors, and enabling security checks.
Your application can use V8 just like any other C++ library. Your C++ code
accesses V8 through the V8 API by including the header include/v8.h.
The V8 Design Elements document provides background you may find useful when optimizing your application for V8.
This document is intended for C++ programmers who want to embed the V8 JavaScript engine within a C++ application. It will help you to make your own application's C++ objects and methods available to JavaScript, and to make JavaScript objects and functions available to your C++ application.
A handle provides a reference to a JavaScript object's location in the heap. The V8 garbage collector reclaims memory used by objects that can never again be accessed. During the garbage collection process the garbage collector often moves objects to different locations in the heap. When the garbage collector moves an object the garbage collector also updates all handles that refer to the object with the object's new location.
An object is considered garbage if it is inaccessible from JavaScript and there are no handles that refer to it. From time to time the garbage collector removes all objects considered to be garbage. V8's garbage collection mechanism is key to V8's performance. To learn more about it see V8 Design Elements.
There are two types of handles:
Local<SomeType> and can also be stored
in variables declared with the supertype Handle<SomeType>.Note: The handle stack is not part of
the C++ call stack, but the handle scopes are embedded in the C++ stack.
Handle scopes can only be stack-allocated, not allocated with new.
Persistent::New and
dispose with Persistent::Dispose A
persistent handle can be made weak, using Persistent::MakeWeak,
to trigger a callback from the garbage collector when the only references
to an object are from weak persistent handles.Persistent<SomeType> and can also
be
stored in variables declared with the supertype Handle<SomeType>.Of course, creating a handle every time you create an object can result in a lot of handles! This is where handle scopes are very useful. You can think of a handle scope as a container that holds lots of handles. When the handle scope's destructor is called all handles created within that scope are removed from the stack. As you would expect, this results in the objects to which the handles point being eligible for deletion from the heap by the garbage collector.
Returning to our very simple example, described in Getting
Started, in the following diagram you can see the handle-stack and
heap-allocated objects. Note that
Context::New() returns a persistent handle that is not on
the handle stack.

When the destructor, HandleScope::~HandleScope, is called
the handle scope is deleted. Objects referred to by handles within the
deleted handle scope are eligible for removal in the next garbage collection
if there are no other references to them. The garbage collector can also
remove the source_obj, and script_obj objects
from the heap as they are no longer referenced by any handles or otherwise
reachable from JavaScript. Since the context handle is a persistent
handle, it is not removed when the handle scope is exited. The only
way to remove the context handle is to explicitly call Dispose on
it.
Note: Throughout this document the term handle refers to a local handle, when discussing a persistent handle that term is used in full.
In V8, a context 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.
Why is this necessary? Because JavaScript provides a set of built-in utility
functions and objects that can be changed by JavaScript code. For example,
if two entirely unrelated JavaScript functions both changed the global
object in the same way then unexpected results are fairly likely to happen.
In terms of CPU time and memory, it might seem an expensive operation
to create a new execution context given the number of built-in objects
that must be built. However, V8's extensive caching ensures that, while
the first context you create is somewhat expensive, subsequent contexts
are much cheaper. This is because the first context needs to create the
built-in objects and parse the built-in JavaScript code
while subsequent contexts only have to create the built-in objects for
their context. With the V8 snapshot feature (activated with build option
snapshot=yes, which is the default) the time spent creating
the first context will be highly optimized as a snapshot includes a serialized
heap which contains already compiled code for the built-in JavaScript code.
Along with garbage collection, V8's extensive caching is also key to V8's
performance, for more information see V8
Design Elements.
When you have created a context you can enter and exit it any number of times. While you are in context A you can also enter a different context, B, which means that you replace A as the current context with B. When you exit B then A is restored as the current context. This is illustrated below:

Note that the built-in utility functions and objects of each context are kept separate. You can optionally set a security token when you create a context. See the Security Model section for more information.
The motivation for using contexts in V8 was so that each window and iframe in a browser can have its own fresh JavaScript environment.
A template is a blueprint for JavaScript functions and objects in a context. You can use a template to wrap C++ functions and data structures within JavaScript objects so that they can be manipulated by JavaScript scripts. For example, Google Chrome uses templates to wrap C++ DOM nodes as JavaScript objects and to install functions in the global namespace. You can create a set of templates and then use the same ones for every new context you make. You can have as many templates as you require. However you can only have one instance of any template in any given context.
In JavaScript there is a strong duality between functions and objects. To create a new type of object in Java or C++ you would typically define a new class. In JavaScript you create a new function instead, and create instances using the function as a constructor. The layout and functionality of a JavaScript object is closely tied to the function that constructed it. This is reflected in the way V8 templates work. There are two types of templates:
GetFunction method
from within the context in which you wish to instantiate the JavaScript
function. You can also associate a C++ callback with a function template
which is called when the JavaScript function instance is invoked.The following code provides an example of creating a template for the global object and setting the built-in global functions.
// Create a template for the global object and set the
// built-in global functions.
Handle<ObjectTemplate> global = ObjectTemplate::New();
global->Set(String::New("log"), FunctionTemplate::New(LogCallback));
// Each processor gets its own context so different processors
// do not affect each other.
Persistent<Context> context = Context::New(NULL, global);
This example code is taken from JsHttpProcessor::Initializer in
the process.cc sample.
An accessor is a C++ callback that calculates and returns
a value when an object property is accessed by a JavaScript script.
Accessors are configured through an object template, using the SetAccessor method.
This method takes the name of the property with which it is associated
and two callbacks to run when a script attempts to read or write the
property.
The complexity of an accessor depends upon the type of data you are manipulating:
Let's say there are two C++ integer variables,
x and y that are to be made
available to JavaScript as global variables within a context. To do this,
you need to call C++ accessor functions whenever a script reads
or writes those variables. These accessor functions convert
a C++ integer to a JavaScript integer using Integer::New,
and convert
a JavaScript integer to a C++ integer using Int32Value.
An example is provided below:
Handle<Value> XGetter(Local<String> property,
const AccessorInfo& info) {
return Integer::New(x);
}
void XSetter(Local<String> property, Local<Value> value,
const AccessorInfo& info) {
x = value->Int32Value();
}
// YGetter/YSetter are so similar they are omitted for brevity
Handle<ObjectTemplate> global_templ = ObjectTemplate::New();
global_templ->SetAccessor(String::New("x"), XGetter, XSetter);
global_templ->SetAccessor(String::New("y"), YGetter, YSetter);
Persistent<Context> context = Context::New(NULL, global_templ);
Note that the object template in the code above is created at the same time as the context. The template could have been created in advance and then used for any number of contexts.
In the preceding example
the variables were static and global. What if the data being manipulated
is dynamic, as is true of the DOM tree in a browser? Let's imagine x and y are
object fields on the C++ class Point:
class Point {
public:
Point(int x, int y) : x_(x), y_(y) { }
int x_, y_;
}
To make any number of C++ point instances available
to JavaScript we need to create one JavaScript object
for each C++ point and make a connection between the JavaScript
object and the C++ instance. This is done with external values
and internal object fields.
First create an object template for the point wrapper object:
Handle<ObjectTemplate> point_templ = ObjectTemplate::New();
Each JavaScript point object keeps a reference to
the C++ object for which it is a wrapper with an internal
field. These fields are so named
because they cannot be accessed from within JavaScript,
they can only be accessed from C++ code. An object can have any number
of internal fields, the number of internal fields
is set on the object template as follows:
point_templ->SetInternalFieldCount(1);
Here the internal field count is set to 1 which means
the object has one internal
field, with an index of 0, that points to a C++ object.
Add the x and y accessors
to the template:
point_templ.SetAccessor(String::New("x"), GetPointX, SetPointX);
point_templ.SetAccessor(String::New("y"), GetPointY, SetPointY);
Next, wrap a C++ point by creating a new instance of the template and
then setting the internal field 0 to an external wrapper around
the point p.
Point* p = ...; Local<Object> obj = point_templ->NewInstance(); obj->SetInternalField(0, External::New(p));
The external object is simply a wrapper around a void*. External
objects can only be used to store reference values in internal fields. JavaScript
objects can not have references to C++ objects directly so the external
value is used as a "bridge" to go from
JavaScript into C++. In that sense external values are the opposite
of handles since handles lets C++ make references to JavaScript objects.
Here's the definition of the get and set accessors
for x, the y accessor
definitions are identical except y replaces x:
Handle<Value> GetPointX(Local<String> property,
const AccessorInfo &info) {
Local<Object> self = info.Holder();
Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
void* ptr = wrap->Value();
int value = static_cast<Point*>(ptr)->x_;
return Integer::New(value);
}
void SetPointX(Local<String> property, Local<Value> value,
const AccessorInfo& info) {
Local<Object> self = info.Holder();
Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
void* ptr = wrap->Value();
static_cast<Point*>(ptr)->x_ = value->Int32Value();
}
Accessors extract the reference to the point object that
was wrapped by the JavaScript object and then read and writes the associated
field. This way these generic accessors can be used on any number of wrapped
point objects.
You can also specify a callback for whenever a script accesses any object property. These are called interceptors. For efficiency, there are two types of interceptors:
document.theFormName.elementName.document.forms.elements[0].The sample process.cc, provided with the V8 source code,
includes an example of using interceptors. In the following code snippet SetNamedPropertyHandler specifies
the MapGet and MapSet interceptors:
Handle<ObjectTemplate> result = ObjectTemplate::New();
result->SetNamedPropertyHandler(MapGet, MapSet);
The MapGet interceptor is provided below:
Handle<Value> JsHttpRequestProcessor::MapGet(Local<String> name,
const AccessorInfo &info) {
// Fetch the map wrapped by this object.
map<string, string> *obj = UnwrapMap(info.Holder());
// Convert the JavaScript string to a std::string.
string key = ObjectToString(name);
// Look up the value if it exists using the standard STL idiom.
map<string, string>::iterator iter = obj->find(key);
// If the key is not present return an empty handle as signal.
if (iter == obj->end()) return Handle<Value>();
// Otherwise fetch the value and wrap it in a JavaScript string.
const string &value = (*iter).second;
return String::New(value.c_str(), value.length());
}
As with accessors, the specified callbacks are invoked whenever a property is accessed. The difference between accessors and interceptors is that interceptors handle all properties, while accessors are associated with one specific property.
The "same origin policy" (first introduced with Netscape Navigator 2.0) prevents a document or script loaded from one "origin" from getting or setting properties of a document from a different "origin". The term origin is defined here as a combination of domain name (www.example.com), protocol (http or https) and port (for example, www.example.com:81 is not the same as www.example.com). All three must match for two webpages to be considered to have the same origin. Without this protection, a malicious web page could compromise the integrity of another web page.
In V8 an "origin" is defined as a context. Access to any context
other than the one from which you are calling is not allowed by default. To
access a context other than the one from which you are calling, you need
to use security tokens or security callbacks. A security token
can be any value but is typically a symbol, a canonical string that does
not exist anywhere else. You can optionally specify a security token
with SetSecurityToken
when you set up a context. If you do not specify a security token V8 will
automatically generate one for the context you are creating.
When an attempt is made to access a global variable the V8 security system first checks the security token of the global object being accessed against the security token of the code attempting to access the global object. If the tokens match access is granted. If the tokens do not match V8 performs a callback to check if access should be allowed. You can specify whether access to an object should be allowed by setting the security callback on the object, using the SetAccessCheckCallbacks method on object templates. The V8 security system can then fetch the security callback of the object being accessed and call it to ask if another context is allowed to access it. This callback is given the object being accessed, the name of the property being accessed, the type of access (read, write, or delete for example) and returns whether or not to allow access.
This mechanism is implemented in Google Chrome so that if security tokens
do not match, a special callback is used to allow access only to the
following: window.focus(), window.blur(), window.close(), window.location, window.open(), history.forward(), history.back(),
and history.go().
V8 will throw an exception if an error occurs - for example, when a script or function attempts to read a property that does not exist, or if a function is called that is not a function.
V8 returns an empty handle if an operation did not succeed. It is therefore
important that your code checks a return value is not an empty handle
before continuing execution.
Check for an empty handle with the Handle class's
public member function IsEmpty().
You can catch exceptions with TryCatch, for example:
TryCatch trycatch; Handlev = script->Run(); if (v.IsEmpty()) { Handle<value> exception = trycatch.Exception(); String::AsciiValue exception_str(exception); printf("Exception: %s\n", *exception_str); // ... }
If the value returned is an empty
handle, and you do not have a TryCatch in
place, your code must bail out. If you do have a TryCatch the
exception is caught and your code is allowed to continue processing.
JavaScript is a class-free, object-oriented language, and as such, it uses prototypal inheritance instead of classical inheritance. This can be puzzling to programmers trained in conventional object-oriented languages like C++ and Java.
Class-based object-oriented languages, such as Java and C++, are founded on the concept of two distinct entities: classes and instances. JavaScript is a prototype-based language and so does not make this distinction: it simply has objects. JavaScript does not natively support the declaration of class hierarchies; however, JavaScript's prototype mechanism simplifies the process of adding custom properties and methods to all instances of an object. In JavaScript, you can add custom properties to objects. For example:
// Create an object "bicycle"
function bicycle(){
}
// Create an instance of bicycle called roadbike
var roadbike = new bicycle()
// Define a custom property, wheels, on roadbike
roadbike.wheels = 2
A custom property added this way only exists for that instance
of the object. If we create another instance of bicycle(), called mountainbike
for example, mountainbike.wheels would return undefined unless
the wheels property is explicitly added.
Sometimes this is exactly what is required, at other times
it would be helpful to add the custom property to all instances of an object
- all bicycles have wheels after all. This is where the prototype object
of JavaScript is very useful. To use the prototype object, reference
the keyword prototype on the object before adding the custom
property to it as follows:
// First, create the "bicycle" object
function bicycle(){
}
// Assign the wheels property to the object's prototype
bicycle.prototype.wheels = 2
All instances of bicycle() will now have the wheels property
prebuilt into them.
The same approach is used in V8 with templates. Each FunctionTemplate has
a PrototypeTemplate method which gives a template for the
function's prototype. You can set properties, and associate C++ functions
with those properties, on a PrototypeTemplate which
will then be present on all instances of the corresponding FunctionTemplate.
For example:
Handle<FunctionTemplate> biketemplate = FunctionTemplate::New();
biketemplate.PrototypeTemplate().Set(
String::New("wheels"),
FunctionTemplate::New(MyWheelsMethodCallback)
)
This causes all instances of biketemplate to have a wheels method
in their prototype chain which, when called, causes the C++ function MyWheelsMethodCallback to
be called.
V8's FunctionTemplate class provides the public member
function Inherit() which you can call when you want a function
template to inherit from another function template, as follows:
void Inherit(Handle<FunctionTemplate> parent);