Saltar al contenido

Los argumentos inyectados

Hay argumentos que el frontend no envía: los pone el framework. Cuáles son, cómo los reconoce —por su tipo y no por su nombre—, y por qué esa distinción es una frontera de confianza y no una comodidad.

Las dos clases

Rust
#[tauri::command]async fn guardar_proyecto(    app: tauri::AppHandle,            // inyectado    window: tauri::WebviewWindow,     // inyectado    estado: tauri::State<'_, Sesion>, // inyectado    id: ProyectoId,                   // del frontend    contenido: String,                // del frontend) -> Result<(), ErrorPayload> { … }

Y la llamada correspondiente solo manda los dos últimos:

JS
await invoke('guardar_proyecto', { id, contenido });

La regla que lo gobierna: el framework mira los tipos. Si un argumento es de uno de los tipos que sabe inyectar, lo pone él; todo lo demás lo busca en el mensaje. No depende del nombre del parámetro, ni del orden, ni de ninguna anotación.

De ahí una consecuencia práctica: puedes ponerlos en el orden que quieras y llamarlos como quieras. La convención habitual es ponerlos primero y usar los nombres del tipo, para que se lea de un vistazo qué parte de la firma es contrato con el frontend y qué parte es contexto.

Qué se puede inyectar

El caso del canal es el más curioso: se declara como argumento inyectado y en realidad lo crea el frontend. Lo verás en el nivel 21; hasta entonces basta con saber que existe.

Por qué inyectar la ventana es una frontera

Es el punto del nivel y merece detenerse. Compara estas dos firmas:

Rust
// A · el frontend dice qué ventana es#[tauri::command]async fn cerrar_esta(app: tauri::AppHandle, etiqueta: String) -> Result<(), ErrorPayload> {    if let Some(w) = app.get_webview_window(&etiqueta) { w.close()?; }    Ok(())}// B · el framework dice qué ventana es#[tauri::command]async fn cerrar_esta(window: tauri::WebviewWindow) -> Result<(), ErrorPayload> {    Ok(window.close()?)}

Las dos hacen lo mismo cuando todo va bien. La diferencia aparece cuando algo va mal: en la primera, cualquier código que se ejecute en cualquier ventana puede cerrar cualquier otra, porque la etiqueta es un dato que el frontend elige. En la segunda no puede: el framework sabe de dónde vino el mensaje y no acepta discusión.

Es exactamente el criterio del nivel 14.4 —operaciones, no mecanismos— aplicado a la identidad: si el frontend puede decir quién es, no es identidad, es una sugerencia.

Lo que cuesta usarlos

Poco, y hay dos detalles que aparecen enseguida:

El estado lleva un tiempo de vida en la firma. Se escribe con un guion bajo y el compilador lo resuelve; en un comando asíncrono es obligatorio y su ausencia produce un error que no menciona comandos. Es el nivel 16.2.

El manejador de la aplicación se puede clonar y llevar a otro hilo. Esa es su gracia y la razón de que sea el argumento más útil de los tres: una tarea de fondo que necesite emitir un evento o leer una ruta se lleva una copia. Nivel 16.3.