Calling a JS Function from C++
Let's say that we have a page with the following HTML/JS on it:
<html>
<head>
<script>
function ShowMessage(message)
{
document.getElementById('msg').innerHTML = message;
}
</script>
</head>
<body>
<div id="msg"></div>
</body>
</html>
Our goal is to call the JavaScript function ShowMessage()
from C++.
Calling the JS Function with EvaluateScript()
The easiest way to call ShowMessage()
from C++ is by evaluating a string of JavaScript.
///
/// 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) {
///
/// Call ShowMessage() by evaluating a string of JavaScript
///
caller->EvaluateScript("ShowMessage('Howdy!')");
}
Calling the JS Function with JSObjectCallAsFunction()
For greater performance and control, you can pass arguments directly to the Function object using JavaScriptCore's JSObjectCallAsFunction()
.
This API function also offers exception handling, overriding the this
object, and more.
#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);
// Get the ShowMessage function by evaluating a script. We could have
// also used JSContextGetGlobalObject() and JSObjectGetProperty() to
// retrieve this from the global window object as well.
// Create our string of JavaScript, automatically managed by JSRetainPtr
JSRetainPtr<JSStringRef> str = adopt(
JSStringCreateWithUTF8CString("ShowMessage"));
// Evaluate the string "ShowMessage"
JSValueRef func = JSEvaluateScript(ctx, str.get(), 0, 0, 0, 0);
// Check if 'func' is actually an Object and not null
if (JSValueIsObject(ctx, func)) {
// Cast 'func' to an Object, will return null if typecast failed.
JSObjectRef funcObj = JSValueToObject(ctx, func, 0);
// Check if 'funcObj' is a Function and not null
if (funcObj && JSObjectIsFunction(ctx, funcObj)) {
// Create a JS string from null-terminated UTF8 C-string, store it
// in a smart pointer to release it when it goes out of scope.
JSRetainPtr<JSStringRef> msg =
adopt(JSStringCreateWithUTF8CString("Howdy!"));
// Create our list of arguments (we only have one)
const JSValueRef args[] = { JSValueMakeString(ctx, msg.get()) };
// Count the number of arguments in the array.
size_t num_args = sizeof(args) / sizeof(JSValueRef*);
// Create a place to store an exception, if any
JSValueRef exception = 0;
// Call the ShowMessage() function with our list of arguments.
JSValueRef result = JSObjectCallAsFunction(ctx, funcObj, 0,
num_args, args,
&exception);
if (exception) {
// Handle any exceptions thrown from function here.
}
if (result) {
// Handle result (if any) here.
}
}
}
}
Updated over 1 year ago
What’s Next