servo/
javascript_evaluator.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use base::id::WebViewId;
6use constellation_traits::EmbedderToConstellationMessage;
7use embedder_traits::{JSValue, JavaScriptEvaluationError, JavaScriptEvaluationId};
8use rustc_hash::FxHashMap;
9
10use crate::ConstellationProxy;
11
12struct PendingEvaluation {
13    callback: Box<dyn FnOnce(Result<JSValue, JavaScriptEvaluationError>)>,
14}
15
16pub(crate) struct JavaScriptEvaluator {
17    current_id: JavaScriptEvaluationId,
18    constellation_proxy: ConstellationProxy,
19    pending_evaluations: FxHashMap<JavaScriptEvaluationId, PendingEvaluation>,
20}
21
22impl JavaScriptEvaluator {
23    pub(crate) fn new(constellation_proxy: ConstellationProxy) -> Self {
24        Self {
25            current_id: JavaScriptEvaluationId(0),
26            constellation_proxy,
27            pending_evaluations: Default::default(),
28        }
29    }
30
31    fn generate_id(&mut self) -> JavaScriptEvaluationId {
32        let next_id = JavaScriptEvaluationId(self.current_id.0 + 1);
33        std::mem::replace(&mut self.current_id, next_id)
34    }
35
36    pub(crate) fn evaluate(
37        &mut self,
38        webview_id: WebViewId,
39        script: String,
40        callback: Box<dyn FnOnce(Result<JSValue, JavaScriptEvaluationError>)>,
41    ) {
42        let evaluation_id = self.generate_id();
43        self.constellation_proxy
44            .send(EmbedderToConstellationMessage::EvaluateJavaScript(
45                webview_id,
46                evaluation_id,
47                script,
48            ));
49        self.pending_evaluations
50            .insert(evaluation_id, PendingEvaluation { callback });
51    }
52
53    pub(crate) fn finish_evaluation(
54        &mut self,
55        evaluation_id: JavaScriptEvaluationId,
56        result: Result<JSValue, JavaScriptEvaluationError>,
57    ) {
58        (self
59            .pending_evaluations
60            .remove(&evaluation_id)
61            .expect("Received request to finish unknown JavaScript evaluation.")
62            .callback)(result)
63    }
64}