impl {{ wrapper }} {
    /// Create a new bridge wrapping a JS object.
    ///
    /// Validates that the JS object provides all required methods.
    pub fn new(js_obj: wasm_bindgen::JsValue) -> Result<Self, String> {
{%- for method in required_methods %}
        if !js_sys::Reflect::has(&js_obj, &wasm_bindgen::JsValue::from_str("{{ method.js_name }}")).unwrap_or(false) {
            return Err(format!("JS object missing required method: {}", "{{ method.name }}"));
        }
{%- endfor %}

        let cached_name = {
            let key = wasm_bindgen::JsValue::from_str("name");
            js_sys::Reflect::get(&js_obj, &key)
                .ok()
                .and_then(|v| v.dyn_into::<js_sys::Function>().ok())
                .and_then(|f| f.apply(&js_obj, &js_sys::Array::new()).ok())
                .and_then(|v| v.as_string())
                .unwrap_or_else(|| "wasm_bridge".to_string())
        };

        Ok(Self {
            inner: js_obj,
            cached_name,
        })
    }
}
