1use super::*;
4
5pub(crate) fn document_create_range(_it: &mut Interp, _t: Value, _a: &[Value]) -> Result<Value, Value> {
7 let r = Obj::plain();
8 {
9 let mut b = r.borrow_mut();
10 b.props.insert(
11 "selectNodeContents".into(),
12 nv("selectNodeContents", dom_noop),
13 );
14 b.props.insert("collapse".into(), nv("collapse", dom_noop));
15 b.props.insert(
16 "getBoundingClientRect".into(),
17 nv("getBoundingClientRect", |_, _, _| {
18 let rect = Obj::plain();
19 for k in &[
20 "top", "left", "bottom", "right", "width", "height", "x", "y",
21 ] {
22 rect.borrow_mut()
23 .props
24 .insert(k.to_string(), Value::Number(0.0));
25 }
26 Ok(Value::Object(rect))
27 }),
28 );
29 b.props.insert("startContainer".into(), Value::Null);
30 b.props.insert("endContainer".into(), Value::Null);
31 for m in [
36 "setStart",
37 "setEnd",
38 "setStartBefore",
39 "setStartAfter",
40 "setEndBefore",
41 "setEndAfter",
42 "selectNode",
43 "deleteContents",
44 "insertNode",
45 "surroundContents",
46 "detach",
47 ] {
48 b.props.insert(m.into(), nv(m, dom_noop));
49 }
50 b.props.insert(
51 "extractContents".into(),
52 nv("extractContents", |it: &mut Interp, _t: Value, _a: &[Value]| {
53 document_create_range(it, Value::Undefined, &[])
54 }),
55 );
56 b.props.insert(
57 "cloneContents".into(),
58 nv("cloneContents", |it: &mut Interp, _t: Value, _a: &[Value]| {
59 document_create_range(it, Value::Undefined, &[])
60 }),
61 );
62 b.props.insert(
63 "cloneRange".into(),
64 nv("cloneRange", |it: &mut Interp, _t: Value, _a: &[Value]| {
65 document_create_range(it, Value::Undefined, &[])
66 }),
67 );
68 b.props.insert(
69 "toString".into(),
70 nv("toString", |_, _, _| Ok(Value::str(""))),
71 );
72 b.props.insert(
73 "compareBoundaryPoints".into(),
74 nv("compareBoundaryPoints", |_, _, _| Ok(Value::Number(0.0))),
75 );
76 b.props
77 .insert("comparePoint".into(), nv("comparePoint", |_, _, _| Ok(Value::Number(0.0))));
78 b.props.insert(
79 "intersectsNode".into(),
80 nv("intersectsNode", |_, _, _| Ok(Value::Bool(false))),
81 );
82 b.props.insert(
83 "isPointInRange".into(),
84 nv("isPointInRange", |_, _, _| Ok(Value::Bool(false))),
85 );
86 b.props.insert("startOffset".into(), Value::Number(0.0));
87 b.props.insert("endOffset".into(), Value::Number(0.0));
88 b.props.insert("collapsed".into(), Value::Bool(true));
89 b.props.insert("commonAncestorContainer".into(), Value::Null);
90 }
91 Ok(Value::Object(r))
92}
93
94pub(crate) fn document_get_selection(_it: &mut Interp, _t: Value, _a: &[Value]) -> Result<Value, Value> {
95 let sel = Obj::plain();
96 {
97 let mut b = sel.borrow_mut();
98 b.props
99 .insert("removeAllRanges".into(), nv("removeAllRanges", dom_noop));
100 b.props.insert("addRange".into(), nv("addRange", dom_noop));
101 b.props.insert("removeRange".into(), nv("removeRange", dom_noop));
105 b.props.insert(
106 "toString".into(),
107 nv("toString", |_, _, _| Ok(Value::str(""))),
108 );
109 b.props.insert("rangeCount".into(), Value::Number(0.0));
110 b.props.insert("isCollapsed".into(), Value::Bool(true));
111 b.props.insert("collapse".into(), nv("collapse", dom_noop));
116 b.props.insert("collapseToStart".into(), nv("collapseToStart", dom_noop));
117 b.props.insert("collapseToEnd".into(), nv("collapseToEnd", dom_noop));
118 b.props.insert("extend".into(), nv("extend", dom_noop));
119 b.props.insert("empty".into(), nv("empty", dom_noop));
120 b.props
121 .insert("selectAllChildren".into(), nv("selectAllChildren", dom_noop));
122 b.props
123 .insert("setBaseAndExtent".into(), nv("setBaseAndExtent", dom_noop));
124 b.props
125 .insert("deleteFromDocument".into(), nv("deleteFromDocument", dom_noop));
126 b.props.insert(
127 "containsNode".into(),
128 nv("containsNode", |_, _, _| Ok(Value::Bool(false))),
129 );
130 b.props.insert(
131 "getRangeAt".into(),
132 nv("getRangeAt", |it: &mut Interp, _t: Value, a: &[Value]| {
133 Err(it.error(alloc::format!(
134 "Failed to execute 'getRangeAt' on 'Selection': The index provided ({}) is greater than the maximum bound (0).",
135 arg(a, 0).to_number() as i64
136 )))
137 }),
138 );
139 b.props.insert("anchorNode".into(), Value::Null);
140 b.props.insert("anchorOffset".into(), Value::Number(0.0));
141 b.props.insert("focusNode".into(), Value::Null);
142 b.props.insert("focusOffset".into(), Value::Number(0.0));
143 b.props.insert("type".into(), Value::str("None"));
144 }
145 Ok(Value::Object(sel))
146}
147
148pub(crate) fn document_get_elements_by_class_name(
149 it: &mut Interp,
150 _t: Value,
151 a: &[Value],
152) -> Result<Value, Value> {
153 let raw = arg(a, 0).to_js_string();
154 let sel_classes: Vec<String> = raw
155 .split_whitespace()
156 .map(|c| alloc::format!(".{}", c))
157 .collect();
158 let sel = if sel_classes.is_empty() {
159 alloc::format!(".__invalid_class__")
160 } else {
161 sel_classes.concat()
162 };
163 let items: Vec<Value> = it
164 .dom
165 .borrow()
166 .query_all(&sel)
167 .into_iter()
168 .map(|i| Value::Object(Obj::dom(i)))
169 .collect();
170 Ok(Value::Object(Obj::array(items)))
171}
172pub(crate) fn document_get_elements_by_tag_name(
173 it: &mut Interp,
174 _t: Value,
175 a: &[Value],
176) -> Result<Value, Value> {
177 let tag = arg(a, 0).to_js_string();
178 let items: Vec<Value> = it
179 .dom
180 .borrow()
181 .query_all(&tag)
182 .into_iter()
183 .map(|i| Value::Object(Obj::dom(i)))
184 .collect();
185 Ok(Value::Object(Obj::array(items)))
186}
187pub(crate) fn document_get_elements_by_tag_name_ns(
191 it: &mut Interp,
192 _t: Value,
193 a: &[Value],
194) -> Result<Value, Value> {
195 let tag = if a.len() >= 2 {
196 arg(a, 1).to_js_string()
197 } else {
198 arg(a, 0).to_js_string()
199 };
200 let items: Vec<Value> = it
201 .dom
202 .borrow()
203 .query_all(&tag)
204 .into_iter()
205 .map(|i| Value::Object(Obj::dom(i)))
206 .collect();
207 Ok(Value::Object(Obj::array(items)))
208}
209pub(crate) fn document_get_elements_by_name(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
213 let name = arg(a, 0).to_js_string();
214 let sel = alloc::format!("[name=\"{name}\"]");
215 let items: Vec<Value> = it
216 .dom
217 .borrow()
218 .query_all(&sel)
219 .into_iter()
220 .map(|i| Value::Object(Obj::dom(i)))
221 .collect();
222 Ok(Value::Object(Obj::array(items)))
223}
224
225pub(crate) fn document_exec_command(_it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
227 let cmd = arg(a, 0).to_js_string().to_ascii_lowercase();
228 match cmd.as_str() {
229 "copy" | "cut" | "paste" | "selectall" | "bold" | "italic" | "underline" | "delete" | "inserttext" => Ok(Value::Bool(true)),
230 _ => Ok(Value::Bool(false)),
231 }
232}
233
234pub(crate) fn doc_adopt_node(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
236 let node = arg(a, 0);
237 if matches!(node, Value::Object(_)) {
238 if let Ok(remove_fn) = it.get_property(&node, "remove") {
239 it.call_listener(&remove_fn, node.clone(), &[], "adoptNode: node.remove()");
240 }
241 Ok(node)
242 } else {
243 Ok(Value::Null)
244 }
245}
246
247pub(crate) fn doc_import_node(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
249 let node = arg(a, 0);
250 let deep = arg(a, 1).truthy();
251 if matches!(node, Value::Object(_)) {
252 if let Ok(clone_fn) = it.get_property(&node, "cloneNode") {
253 if let Ok(cloned) = it.call_value(&clone_fn, node.clone(), &[Value::Bool(deep)]) {
254 return Ok(cloned);
255 }
256 }
257 Ok(node)
258 } else {
259 Ok(Value::Null)
260 }
261}