firefox_webdriver/browser/tab/
script.rs

1//! JavaScript execution methods.
2
3use serde_json::Value;
4use tracing::debug;
5
6use crate::error::Result;
7use crate::protocol::{Command, ScriptCommand};
8
9use super::Tab;
10
11// ============================================================================
12// Tab - Script Execution
13// ============================================================================
14
15impl Tab {
16    /// Executes synchronous JavaScript in the page context.
17    ///
18    /// The script should use `return` to return a value.
19    ///
20    /// # Example
21    ///
22    /// ```ignore
23    /// let title = tab.execute_script("return document.title").await?;
24    /// ```
25    pub async fn execute_script(&self, script: &str) -> Result<Value> {
26        debug!(tab_id = %self.inner.tab_id, script_len = script.len(), "Executing script");
27
28        let command = Command::Script(ScriptCommand::Evaluate {
29            script: script.to_string(),
30            args: vec![],
31        });
32
33        let response = self.send_command(command).await?;
34
35        let value = response
36            .result
37            .as_ref()
38            .and_then(|v| v.get("value"))
39            .cloned()
40            .unwrap_or(Value::Null);
41
42        debug!(tab_id = %self.inner.tab_id, "Script executed");
43        Ok(value)
44    }
45
46    /// Executes asynchronous JavaScript in the page context.
47    ///
48    /// The script should return a Promise or use async/await.
49    pub async fn execute_async_script(&self, script: &str) -> Result<Value> {
50        debug!(tab_id = %self.inner.tab_id, script_len = script.len(), "Executing async script");
51
52        let command = Command::Script(ScriptCommand::EvaluateAsync {
53            script: script.to_string(),
54            args: vec![],
55        });
56
57        let response = self.send_command(command).await?;
58
59        let value = response
60            .result
61            .as_ref()
62            .and_then(|v| v.get("value"))
63            .cloned()
64            .unwrap_or(Value::Null);
65
66        debug!(tab_id = %self.inner.tab_id, "Async script executed");
67        Ok(value)
68    }
69}
70
71// ============================================================================
72// Helper Functions
73// ============================================================================
74
75/// Escapes a string for safe use in JavaScript.
76pub(crate) fn json_string(s: &str) -> String {
77    serde_json::to_string(s).unwrap_or_else(|_| format!("\"{}\"", s))
78}