Evaluating a String of JS
Using View::EvaluateScript()
The easiest way to evaluate a string of JavaScript in C++ is by using View::EvaluateScript()
///
/// Use LoadListener::OnDOMReady to wait for the DOM to load.
///
void MyApp::OnDOMReady(View* caller,
uint64_t frame_id,
bool is_main_frame,
const String& url) {
///
/// Execute a string of JavaScript
///
view->EvaluateScript("document.body.innerHTML = 'Ultralight rocks!';");
}
Handling Results
View::EvaluateScript()
can return the result from a script execution, if any.
The result is returned as a String.
///
/// Use LoadListener::OnDOMReady to wait for the DOM to load.
///
void MyApp::OnDOMReady(View* caller,
uint64_t frame_id,
bool is_main_frame,
const String& url) {
///
/// Evaluate a string of JavaScript, store result in 'result'
///
String result = view->EvaluateScript("1 + 1");
///
/// result should now contain "2"
///
}
Using JSEvaluateScript() Directly
View::EvaluateScript()
is really just a wrapper for JavaScriptCore's JSEvaluateScript()
. This API function offers lower-level control over script execution (exception handling, overriding this
object, etc.).
To use this API function we're going to need to create a JavaScript string with JSStringCreateWithUTF8CString()
and then pass it to JSEvaluateScript()
.
///
/// Use LoadListener::OnDOMReady to wait for the DOM to load.
///
void MyApp::OnDOMReady(View* caller,
uint64_t frame_id,
bool is_main_frame,
const String& url) {
///
/// Acquire the JS execution context for the current page.
///
auto scoped_context = caller->LockJSContext();
///
/// Typecast to the underlying JSContextRef.
///
JSContextRef ctx = (*scoped_context);
const char* script = "document.body.innerHTML = 'Ultralight rocks!';";
///
/// Create our string of JavaScript
///
JSStringRef str = JSStringCreateWithUTF8CString(script);
///
/// Execute it with JSEvaluateScript, ignoring other parameters for now
///
JSEvaluateScript(ctx, str, 0, 0, 0, 0);
///
/// Release our string (we only Release what we Create)
///
JSStringRelease(str);
}
Managing string lifetime with Retain / Release
The API follows a simple rule-- anything you "Create" you must "Release".
For example, in the above code snippet we called JSStringCreateWithUTF8CString
. This API function has the word Create
in it so we must release the created object with JSStringRelease()
to avoid a memory leak.
If you want to increase the ref-count (to retain the object in a C++ wrapper, for instance), you can call JSStringRetain()
.
The API provides a JSRetainPtr<>
for C++ that automatically manages lifetime for you. Just call adopt()
with any of the JSStringCreate
methods to create a managed string object.
#include <JavaScriptCore/JSRetainPtr.h>
///
/// Use LoadListener::OnDOMReady to wait for the DOM to load.
///
void MyApp::OnDOMReady(View* caller,
uint64_t frame_id,
bool is_main_frame,
const String& url) {
///
/// Acquire the JS execution context for the current page.
///
auto scoped_context = caller->LockJSContext();
///
/// Typecast to the underlying JSContextRef.
///
JSContextRef ctx = (*scoped_context);
const char* script = "document.body.innerHTML = 'Ultralight rocks!';";
///
/// Create our string of JavaScript, automatically managed by JSRetainPtr
///
JSRetainPtr<JSStringRef> str = adopt(
JSStringCreateWithUTF8CString(script));
///
/// Execute it with JSEvaluateScript, ignoring other parameters for now
///
JSEvaluateScript(ctx, str.get(), 0, 0, 0, 0);
}
Updated over 1 year ago