aboutsummaryrefslogtreecommitdiffstats
path: root/components/servo/javascript_evaluator.rs
diff options
context:
space:
mode:
authorNarfinger <Narfinger@users.noreply.github.com>2025-05-13 14:54:18 +0200
committerGitHub <noreply@github.com>2025-05-13 12:54:18 +0000
commit991be359a3b896c204778cd3f3b226e16f9435b8 (patch)
tree8dc9b81799a9afee02de84aed25c2901028a35e2 /components/servo/javascript_evaluator.rs
parent91c4c7b9982556bc11a39d47081984cbdfa6280e (diff)
downloadservo-991be359a3b896c204778cd3f3b226e16f9435b8.tar.gz
servo-991be359a3b896c204778cd3f3b226e16f9435b8.zip
libservo: Allow embedders to execute JavaScript scripts via the API (#35720)
This change adds a new `WebView` API `evaluate_javascript()`, which allows embedders to execute JavaScript code and wait for a reply asynchronously. Ongoing script execution is tracked by a libservo `JavaScriptEvaluator` struct, which maps an id to the callback passed to the `evaluate_javascript()` method. The id is used to track the script and its execution through the other parts of Servo. Testing: This changes includes `WebView` unit tests. --------- Signed-off-by: Narfinger <Narfinger@users.noreply.github.com> Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Diffstat (limited to 'components/servo/javascript_evaluator.rs')
-rw-r--r--components/servo/javascript_evaluator.rs65
1 files changed, 65 insertions, 0 deletions
diff --git a/components/servo/javascript_evaluator.rs b/components/servo/javascript_evaluator.rs
new file mode 100644
index 00000000000..41cb5539b05
--- /dev/null
+++ b/components/servo/javascript_evaluator.rs
@@ -0,0 +1,65 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use std::collections::HashMap;
+
+use base::id::WebViewId;
+use constellation_traits::EmbedderToConstellationMessage;
+use embedder_traits::{JSValue, JavaScriptEvaluationError, JavaScriptEvaluationId};
+
+use crate::ConstellationProxy;
+
+struct PendingEvaluation {
+ callback: Box<dyn FnOnce(Result<JSValue, JavaScriptEvaluationError>)>,
+}
+
+pub(crate) struct JavaScriptEvaluator {
+ current_id: JavaScriptEvaluationId,
+ constellation_proxy: ConstellationProxy,
+ pending_evaluations: HashMap<JavaScriptEvaluationId, PendingEvaluation>,
+}
+
+impl JavaScriptEvaluator {
+ pub(crate) fn new(constellation_proxy: ConstellationProxy) -> Self {
+ Self {
+ current_id: JavaScriptEvaluationId(0),
+ constellation_proxy,
+ pending_evaluations: Default::default(),
+ }
+ }
+
+ fn generate_id(&mut self) -> JavaScriptEvaluationId {
+ let next_id = JavaScriptEvaluationId(self.current_id.0 + 1);
+ std::mem::replace(&mut self.current_id, next_id)
+ }
+
+ pub(crate) fn evaluate(
+ &mut self,
+ webview_id: WebViewId,
+ script: String,
+ callback: Box<dyn FnOnce(Result<JSValue, JavaScriptEvaluationError>)>,
+ ) {
+ let evaluation_id = self.generate_id();
+ self.constellation_proxy
+ .send(EmbedderToConstellationMessage::EvaluateJavaScript(
+ webview_id,
+ evaluation_id,
+ script,
+ ));
+ self.pending_evaluations
+ .insert(evaluation_id, PendingEvaluation { callback });
+ }
+
+ pub(crate) fn finish_evaluation(
+ &mut self,
+ evaluation_id: JavaScriptEvaluationId,
+ result: Result<JSValue, JavaScriptEvaluationError>,
+ ) {
+ (self
+ .pending_evaluations
+ .remove(&evaluation_id)
+ .expect("Received request to finish unknown JavaScript evaluation.")
+ .callback)(result)
+ }
+}