GraphiteEditor/Graphite · error
Function not found
Error message
Function not found
What it means
initialize_native_communication resolves window.initializeNativeCommunication on the JS global through js_sys::Reflect::get and panics when retrieval fails. That function is injected by the native CEF shell hosting the editor; outside that host — or before the bridge script has run — the global does not exist.
Source
Thrown at frontend/wrapper/src/native_communication.rs:79
serde_json::to_vec(&messages).ok()
}
#[cfg(all(feature = "editor", any(feature = "native", not(target_family = "wasm"))))]
pub fn decode_editor_command(data: &[u8]) -> Option<editor::messages::prelude::Message> {
match serde_json::from_slice::<crate::EditorCommand>(data) {
Ok(command) => Some(command.into()),
Err(e) => {
log::error!("Failed to deserialize editor command: {e}");
None
}
}
}
pub fn initialize_native_communication() {
let global = js_sys::global();
// Get the function by name
let func = js_sys::Reflect::get(&global, &JsValue::from_str("initializeNativeCommunication")).expect("Function not found");
let func = func.dyn_into::<js_sys::Function>().expect("Not a function");
// Call it
func.call0(&JsValue::NULL).expect("Function call failed");
}
pub fn send_message_to_cef(message: String) {
let global = js_sys::global();
// Get the function by name
let func = js_sys::Reflect::get(&global, &JsValue::from_str("sendNativeMessage")).expect("Function not found");
let func = func.dyn_into::<js_sys::Function>().expect("Not a function");
let array = Uint8Array::from(message.as_bytes());
let buffer = array.buffer();
// Call it with argument
func.call1(&JsValue::NULL, &JsValue::from(buffer)).expect("Function call failed");View on GitHub (pinned to c507b35645)
Solutions
- Load the JS bridge that defines initializeNativeCommunication before the wasm module instantiates
- Gate this init path to the CEF host (feature flag or runtime check) and no-op elsewhere
- Replace the expects with Reflect::get plus dyn_ref::<Function>() checks that log a warning when the bridge is absent
Example fix
// before
let func = js_sys::Reflect::get(&global, &JsValue::from_str("initializeNativeCommunication")).expect("Function not found");
// after
let Ok(found) = js_sys::Reflect::get(&global, &JsValue::from_str("initializeNativeCommunication")) else {
error!("native bridge not present; skipping CEF initialization");
return;
};
let Ok(func) = found.dyn_into::<js_sys::Function>() else {
error!("initializeNativeCommunication is not callable");
return;
}; Defensive patterns
Strategy: type-guard
Validate before calling
// host page, before loading the wasm bundle: // typeof window.initializeNativeCommunication === 'function'
Type guard
fn global_function(name: &str) -> Option<js_sys::Function> {
js_sys::Reflect::get(&js_sys::global(), &JsValue::from_str(name))
.ok()?
.dyn_ref::<js_sys::Function>()
.cloned()
} Prevention
- Define bridge globals in a synchronous script tag placed before the wasm bundle
- Feature-gate native communication so browser builds never call it
- Log the typeof of each expected bridge global during startup diagnostics
When it happens
Trigger: Loading the native-communication build in a plain browser; the host page script that defines the bridge not yet executed when the wasm start function runs; the native host renaming or omitting the injected global for this build.
Common situations: Testing a CEF-targeted build in a normal browser; script load order so the wasm instantiates first; version drift between the wrapper's expected global names and the native shell's injected API.
Related errors
- Not a function
- Function call failed
- Failed to spawn the CEF control thread
- The CEF control thread ended without a result
- Failed to connect to the main process bootstrap server
AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16).
Data as JSON: /api/errors/7a571ea98b503861.
Report an issue: GitHub.