Language:

Categories

Getting Started

General Use

Tutorials

Changelogs

Licensing

Introduction to JavaScript Integration

It's easy to communicate with web-pages using JavaScript; here's a quick overview of the classes you'll need to use.

JSValue Class

The JSValue class is used as an intermediary to translate C++ types into Javascript variables and vice-versa. To get a better understanding of how this relationship works, here’s how types are mapped between Javascript and C++ using JSValue:

JavascriptC++
Numberdouble or int
Booleanbool
StringWebString (UTF-16)
ObjectJSObject
ArrayJSArray
NullJSValue::Null()
UndefinedJSValue::Undefined()

JSValue Type: Strings

You can get the string representation of any JSValue via JSValue::ToString. It is safe to call this on a JSValue of any type.

JSValue Type: Objects

Objects in Javascript are sort of like a “map” or “dictionary”. Every key has a “string” type and every value can be any number of types.

As specified in the table above, these Objects are modeled in C++ with the JSObject class.

There are two types of JSObjects, Local and Remote.

Local JSObjects

Local objects only have properties (no custom methods) and are primarily used for declaring data to pass to methods. Local objects can be created using the JSObject constructor:

JSObject my_object;
my_object.SetProperty(WSLit("name"), WSLit("Bob"));
my_object.SetProperty(WSLit("age"), 42)

Remote JSObjects

Remote objects live within the V8 engine in a separate process and can have both Properties and Methods.

For example, say you had an object ‘Person’ in JavaScript:

var Person = {
   name: 'Bob',
   age: 22,
};

You could then interact with this object in C++:

JSValue my_value = web_view->ExecuteJavascriptWithResult("Person");

if(my_value.IsObject()) {
  JSObject& person = my_value.ToObject();

  WebString name = person.GetProperty(WSLit("name")).ToString();
  // value of name is 'Bob'
     
  int age = person.GetProperty(WSLit("age")).ToInteger();
  // value of age is '22'
}
Lifetime of Remote Objects

All remote objects are reference-counted and collected by the V8 garbage collector. When you return an object to the main process via a JSObject proxy, this ref-count is incremented, and when the JSObject is destroyed, the ref-count is decremented.

You can think of remote JSObjects as a pointer to a V8 object on the page. Every time you make a copy of a JSObject (via its copy-constructor), only the reference (remote ID) is copied; a deep copy is not made.

When the V8 object goes away (usually due to a page navigation), the reference will no longer be valid and method calls may fail (see the section below). If you need an object to be persistent, you should create a Global JavaScript Object instead.

Handling Errors

Method calls on Remote objects are proxied to the child-process and execute synchronously but may fail for various reasons (see JSObject::last_error()).

JSValue foobar = my_object.GetProperty(WSLit("foobar"));
if (my_object.last_error() != kError_None) {
  // handle error here (if any)
}

JSValue Type: Arrays

On the C++ side, Arrays are modeled as a vector of JSValues (wrapped as JSArray).

So, for example, if you had the following array in Javascript:

var myArray = [1, 2, "three", 4, "five"];

You could access it in C++ like so:

JSValue my_value = web_view->ExecuteJavascriptWithResult("myArray");

if(my_value.IsArray()) {
   JSArray& myArray = myValue.ToArray();

   int first = myArray[0].ToInteger(); // value is '1'
   int second = myArray[1].ToInteger();  // value is '2'
   WebString third = myArray[2].ToString(); // value is 'three'
}

Directly Calling JavaScript Functions

You can call a Javascript function directly via JSObject::Invoke.

Say you had the following function in Javascript:

function addChatMessage(nickname, message) {
  chat = document.getElementById('chat');
  chat.innerText = nickname + ": " + message;
}

You can call it directly from C++ like so:

// Retrieve the global 'window' object from the page
JSValue window = web_view->ExecuteJavascriptWithResult(
  WSLit("window"), WSLit(""));
  
if (window.IsObject()) {
  JSArray args;
  args.push_back("Bob");
  args.push_back("Hello world!");

  window.ToObject().Invoke(WSLit("addChatMessage"), args);
}

Global JavaScript Objects

Sometimes you need objects to persist between pages (such as when exposing Application objects to a WebView). In such cases, you should use Global Javascript Objects.

See this article for more information on Global JavaScript Objects.

Declaring Custom Method Callbacks

Another nifty feature of remote Javascript objects is that you can declare custom methods to be handled in C++ and invoke them from JavaScript.

See this article for more information on Custom JavaScript Methods.