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

  1. Load the JS bridge that defines initializeNativeCommunication before the wasm module instantiates
  2. Gate this init path to the CEF host (feature flag or runtime check) and no-op elsewhere
  3. 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

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


AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16). Data as JSON: /api/errors/7a571ea98b503861. Report an issue: GitHub.