create wiki

go home go home
  1. about
  2. code
  3. wiki
  4. blog

V8/Handles

From Create Wiki

Jump to: navigation, search

Handles sound like what they are, just like lollies in a lolly pop jar. — paraphrased from Truly Scrumptious, song from the wonderful Chitty Chitty Bang Bang

Contents

What Handles Are

Handles are something your code grabs on to when it references an object. They are much like pointers, but smarter. Unless you use a specific kind of Handle, they will destroy what they point to automatically when they are no longer needed.

For example:

{
    //start a handle scope
    HandleScope handle_scope;
 
    //create a handle
    Local<String> string = String::New("Hello, World");
 
    //the string "Hello, World" is now in memory
}
 
//magically, the string is no longer in memory!


It is, of course, not magic. It is actually quite simple. Whenever you create a Local handle, it gets added to the current handle scope. Handle scopes are just collections of handles.

When the handle scope goes out of scope, its destructor gets called, just like any other C++ object's destructor would be. At this point, it dereferences all of its handles.

Handles vs. Locals

You may notice that there are two very frequently used handle classes: Local and Handle. The two are pretty much the same. This is because Local is a subclass of Handle. The only overridden functions are the constructors, and other than that, the only additional function is Local::New. As such, it will often not matter which you use.

This is because the Handle or Local C++ object itself does not, in effect, point directly to the object, but to a form of underlying Handle. This underlying handle is only created at certain times, independently from the use of Local or Handle in your code.

Creation of Handles and Handle Emptiness

Although a new Handle object will of course be created whenever you use Handle or Local in your code, an actual reference to an object is only created under certain circumstances.

For example:

//create a handle
Local<String> string;
 
//string is empty. No actual handle has been created. Local is just
//a reference to a handle which may someday exist.
 
//For our purposes, let us assume it points at 0x0
 
//make string point to something
//String::New creates a new Local<String>, and returns the actual
//Local<String> in our scope. This Local<String> could be at 0x12345,
//and could point to a String at 0x67890
 
//we then assign string to that returned handle.
string = String::New("Hello");
 
//string now also points to the Local<String> at 0x12345, which points
//to a String at 0x67890
 
//the String::New command is what created the Local<String>.
//Although the C++ Local variable was created the instant we declared
//string, the actual Local object was not created until we called String::New


It might make more sense, therefore, to use the Handle type instead of the Local type for your values, since Local is only used to create the handle. For instance, this works just as well as the previous example:

//create a Handle
Handle<String> string;
 
//Create a new Local<String> by calling String::New, and assign string
//to that created handle.
string = String::New("Hello");


Which to use comes down to preference. Using Handle could be clearer as it can make the difference between Handle objects and the underlying actual handles they point to quite obvious. Using Locals, however, is good because it indicates that the values are local for our own reference. The generic Handle type can point to another type of handle as well (see Persistent Handles) so, and the visible distinction can help make things clearer.

Here, we try to use Local where applicable.

Escaping Scope

Sometimes, you need the a value to "escape" the current handle scope. This most often happens in functions. Consider:

Local<String> getString()
{
    //create a handle scope
    HandleScope handle_scope;
 
    //use String::New to create a local in the handle scope
    //and assign string to that handle.
    Local<String> string = String::New("Hello, World");
 
    //return the string
    return string;
 
    //and handle_scope goes away, along with our string Local belonging to it.
}
 
...in other code...
HandleScope handle_scope;
Local<String> string = getString();
 
//Oops! string is unusable.


The string is now invalid, because it was destroyed when getString's handle_scope finished. Thankfully, v8 offers a simple function just for this purpose:

Local<String> getString()
{
    //create a handle scope
    HandleScope handle_scope;
 
    //create a string Local and assign it to a handle named string
    Local<String> string = String::New("Hello, World");
 
    //return while telling handle_scope to transfer string to the previous
    //handle scope.
    return handle_scope.Close(string);
}


The Close function of the handle scope transfers the handle passed to it from the scope to the previous scope.

Persistent Handles

This is where it gets interesting. Unfortunately, I have to go to sleep sometime, so I'll write this later.

Personal tools