ferridriver_script/bindings/
js_handle.rs1use ferridriver::JSHandle;
9use rquickjs::JsLifetime;
10use rquickjs::class::Trace;
11
12use crate::bindings::convert::{
13 FerriResultExt, extract_page_function, quickjs_arg_to_serialized, serialized_value_to_quickjs,
14};
15
16#[derive(JsLifetime, Trace)]
21#[rquickjs::class(rename = "JSHandle")]
22pub struct JSHandleJs {
23 #[qjs(skip_trace)]
24 inner: JSHandle,
25}
26
27impl JSHandleJs {
28 #[must_use]
29 pub fn new(inner: JSHandle) -> Self {
30 Self { inner }
31 }
32
33 #[must_use]
34 pub fn inner(&self) -> &JSHandle {
35 &self.inner
36 }
37}
38
39#[rquickjs::methods]
40impl JSHandleJs {
41 #[qjs(rename = "isDisposed")]
44 pub fn is_disposed(&self) -> bool {
45 self.inner.is_disposed()
46 }
47
48 #[qjs(rename = "dispose")]
52 pub async fn dispose(&self) -> rquickjs::Result<()> {
53 self.inner.dispose().await.into_js()
54 }
55
56 #[qjs(rename = "asElement")]
65 pub fn as_element<'js>(&self, ctx: rquickjs::Ctx<'js>) -> rquickjs::Result<rquickjs::Value<'js>> {
66 use rquickjs::class::Class;
67 use rquickjs::{IntoJs, Value};
68 match self.inner.as_element() {
69 Some(e) => {
70 let wrapper = crate::bindings::element_handle::ElementHandleJs::new(e);
71 let inst = Class::instance(ctx.clone(), wrapper)?;
72 inst.into_js(&ctx)
73 },
74 None => Ok(Value::new_null(ctx)),
75 }
76 }
77
78 #[qjs(rename = "jsonValue")]
84 pub async fn json_value<'js>(&self, ctx: rquickjs::Ctx<'js>) -> rquickjs::Result<rquickjs::Value<'js>> {
85 let v = self.inner.json_value().await.into_js()?;
86 serialized_value_to_quickjs(&ctx, &v)
87 }
88
89 #[qjs(rename = "getProperty")]
91 pub async fn get_property(&self, name: String) -> rquickjs::Result<JSHandleJs> {
92 let h = self.inner.get_property(&name).await.into_js()?;
93 Ok(JSHandleJs::new(h))
94 }
95
96 #[qjs(rename = "getProperties")]
101 pub async fn get_properties<'js>(&self, ctx: rquickjs::Ctx<'js>) -> rquickjs::Result<rquickjs::Value<'js>> {
102 let pairs = self.inner.get_properties().await.into_js()?;
103 let obj = rquickjs::Object::new(ctx.clone())?;
104 for (k, h) in pairs {
105 let handle_js = rquickjs::Class::instance(ctx.clone(), JSHandleJs::new(h))?;
106 obj.set(k, handle_js)?;
107 }
108 Ok(obj.into_value())
109 }
110
111 #[qjs(rename = "evaluate")]
115 pub async fn evaluate<'js>(
116 &self,
117 ctx: rquickjs::Ctx<'js>,
118 page_function: rquickjs::Value<'js>,
119 arg: rquickjs::function::Opt<rquickjs::Value<'js>>,
120 ) -> rquickjs::Result<rquickjs::Value<'js>> {
121 let (source, is_fn) = extract_page_function(&ctx, page_function)?;
122 let serialized = quickjs_arg_to_serialized(&ctx, arg.0)?;
123 let result = self.inner.evaluate(&source, serialized, is_fn).await.into_js()?;
124 serialized_value_to_quickjs(&ctx, &result)
125 }
126
127 #[qjs(rename = "evaluateHandle")]
129 pub async fn evaluate_handle<'js>(
130 &self,
131 ctx: rquickjs::Ctx<'js>,
132 page_function: rquickjs::Value<'js>,
133 arg: rquickjs::function::Opt<rquickjs::Value<'js>>,
134 ) -> rquickjs::Result<JSHandleJs> {
135 let (source, is_fn) = extract_page_function(&ctx, page_function)?;
136 let serialized = quickjs_arg_to_serialized(&ctx, arg.0)?;
137 let handle = self.inner.evaluate_handle(&source, serialized, is_fn).await.into_js()?;
138 Ok(JSHandleJs::new(handle))
139 }
140}