1use super::*;
4
5pub(crate) fn event_prevent_default(_it: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
12 if let Value::Object(o) = &this {
13 let cancelable = matches!(o.borrow().props.get("cancelable"), Some(Value::Bool(true)));
14 if cancelable {
15 let mut b = o.borrow_mut();
16 b.props.insert("defaultPrevented".into(), Value::Bool(true));
17 b.props.insert("returnValue".into(), Value::Bool(false));
21 }
22 }
23 Ok(Value::Undefined)
24}
25pub(crate) fn event_target_stop_propagation(_it: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
30 if let Value::Object(o) = &this {
31 o.borrow_mut().props.insert("cancelBubble".into(), Value::Bool(true));
32 }
33 Ok(Value::Undefined)
34}
35pub(crate) fn event_stop_immediate_propagation(_it: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
36 if let Value::Object(o) = &this {
37 let mut b = o.borrow_mut();
38 b.props.insert("_stopImmediate".into(), Value::Bool(true));
39 b.props.insert("cancelBubble".into(), Value::Bool(true));
40 }
41 Ok(Value::Undefined)
42}
43pub(crate) fn event_target_composed_path(_it: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
47 if let Value::Object(o) = &this {
48 if let Some(t) = o.borrow().props.get("target").cloned() {
49 if !matches!(t, Value::Undefined) {
50 return Ok(Value::Object(Obj::array(alloc::vec![t])));
51 }
52 }
53 }
54 Ok(Value::Object(Obj::array(alloc::vec::Vec::new())))
55}
56pub(crate) fn event_ctor(_it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
57 let event_type = arg(a, 0).to_js_string();
58 let options = arg(a, 1);
59 let (bubbles, cancelable, composed) = if let Value::Object(o) = &options {
60 let b = o.borrow();
61 (
62 b.props.get("bubbles").map(|v| v.truthy()).unwrap_or(false),
63 b.props
64 .get("cancelable")
65 .map(|v| v.truthy())
66 .unwrap_or(false),
67 b.props.get("composed").map(|v| v.truthy()).unwrap_or(false),
68 )
69 } else {
70 (false, false, false)
71 };
72 let ev = Obj::plain();
73 {
74 let mut b = ev.borrow_mut();
75 b.props.insert("type".into(), Value::str(&event_type));
76 b.props.insert("bubbles".into(), Value::Bool(bubbles));
77 b.props.insert("cancelable".into(), Value::Bool(cancelable));
78 b.props.insert("composed".into(), Value::Bool(composed));
82 b.props.insert("defaultPrevented".into(), Value::Bool(false));
83 b.props.insert("isTrusted".into(), Value::Bool(false));
86 b.props.insert("currentTarget".into(), Value::Null);
90 b.props.insert("eventPhase".into(), Value::Number(0.0));
91 b.props.insert("timeStamp".into(), Value::Number(next_perf_timestamp()));
96 b.props.insert("returnValue".into(), Value::Bool(true));
100 b.props.insert("cancelBubble".into(), Value::Bool(false));
101 b.props
102 .insert("preventDefault".into(), nv("preventDefault", event_prevent_default));
103 b.props.insert(
104 "stopPropagation".into(),
105 nv("stopPropagation", event_target_stop_propagation),
106 );
107 b.props.insert(
114 "stopImmediatePropagation".into(),
115 nv("stopImmediatePropagation", event_stop_immediate_propagation),
116 );
117 b.props.insert(
123 "composedPath".into(),
124 nv("composedPath", event_target_composed_path),
125 );
126 }
127 Ok(Value::Object(ev))
128}
129
130pub(crate) fn keyboard_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
136 let ev = event_ctor(it, t, a)?;
137 let options = arg(a, 1);
138 if let Value::Object(o) = &ev {
139 let mut b = o.borrow_mut();
140 b.props.insert("key".into(), obj_prop(&options, "key").unwrap_or_else(|| Value::str("")));
141 b.props.insert("code".into(), obj_prop(&options, "code").unwrap_or_else(|| Value::str("")));
142 b.props
143 .insert("keyCode".into(), obj_prop(&options, "keyCode").unwrap_or(Value::Number(0.0)));
144 b.props
145 .insert("which".into(), obj_prop(&options, "which").unwrap_or(Value::Number(0.0)));
146 b.props
147 .insert("location".into(), obj_prop(&options, "location").unwrap_or(Value::Number(0.0)));
148 b.props.insert(
149 "repeat".into(),
150 Value::Bool(obj_prop(&options, "repeat").map(|v| v.truthy()).unwrap_or(false)),
151 );
152 for k in ["ctrlKey", "shiftKey", "altKey", "metaKey"] {
153 b.props.insert(
154 k.into(),
155 Value::Bool(obj_prop(&options, k).map(|v| v.truthy()).unwrap_or(false)),
156 );
157 }
158 }
159 Ok(ev)
160}
161pub(crate) fn mouse_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
167 let ev = event_ctor(it, t, a)?;
168 let options = arg(a, 1);
169 if let Value::Object(o) = &ev {
170 let mut b = o.borrow_mut();
171 for k in ["clientX", "clientY", "screenX", "screenY", "movementX", "movementY"] {
172 b.props
173 .insert(k.into(), obj_prop(&options, k).unwrap_or(Value::Number(0.0)));
174 }
175 b.props.insert("button".into(), obj_prop(&options, "button").unwrap_or(Value::Number(0.0)));
176 b.props
177 .insert("buttons".into(), obj_prop(&options, "buttons").unwrap_or(Value::Number(0.0)));
178 b.props
179 .insert("relatedTarget".into(), obj_prop(&options, "relatedTarget").unwrap_or(Value::Null));
180 for k in ["ctrlKey", "shiftKey", "altKey", "metaKey"] {
181 b.props.insert(
182 k.into(),
183 Value::Bool(obj_prop(&options, k).map(|v| v.truthy()).unwrap_or(false)),
184 );
185 }
186 }
187 Ok(ev)
188}
189pub(crate) fn wheel_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
194 let ev = mouse_event_ctor(it, t, a)?;
195 let options = arg(a, 1);
196 if let Value::Object(o) = &ev {
197 let mut b = o.borrow_mut();
198 for k in ["deltaX", "deltaY", "deltaZ"] {
199 b.props
200 .insert(k.into(), obj_prop(&options, k).unwrap_or(Value::Number(0.0)));
201 }
202 b.props
203 .insert("deltaMode".into(), obj_prop(&options, "deltaMode").unwrap_or(Value::Number(0.0)));
204 }
205 Ok(ev)
206}
207pub(crate) fn touch_ctor(_it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
213 let options = arg(a, 0);
214 let o = Obj::plain();
215 {
216 let mut b = o.borrow_mut();
217 b.props.insert(
218 "identifier".into(),
219 obj_prop(&options, "identifier").unwrap_or(Value::Number(0.0)),
220 );
221 b.props
222 .insert("target".into(), obj_prop(&options, "target").unwrap_or(Value::Null));
223 for k in ["clientX", "clientY", "pageX", "pageY", "screenX", "screenY"] {
224 b.props.insert(k.into(), obj_prop(&options, k).unwrap_or(Value::Number(0.0)));
225 }
226 b.props
227 .insert("radiusX".into(), obj_prop(&options, "radiusX").unwrap_or(Value::Number(25.0)));
228 b.props
229 .insert("radiusY".into(), obj_prop(&options, "radiusY").unwrap_or(Value::Number(25.0)));
230 b.props.insert(
231 "rotationAngle".into(),
232 obj_prop(&options, "rotationAngle").unwrap_or(Value::Number(0.0)),
233 );
234 b.props
235 .insert("force".into(), obj_prop(&options, "force").unwrap_or(Value::Number(1.0)));
236 }
237 Ok(Value::Object(o))
238}
239pub(crate) fn touch_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
244 let ev = event_ctor(it, t, a)?;
245 let options = arg(a, 1);
246 if let Value::Object(o) = &ev {
247 let mut b = o.borrow_mut();
248 for k in ["touches", "targetTouches", "changedTouches"] {
249 b.props.insert(
250 k.into(),
251 obj_prop(&options, k).unwrap_or_else(|| Value::Object(Obj::array(alloc::vec![]))),
252 );
253 }
254 for k in ["ctrlKey", "shiftKey", "altKey", "metaKey"] {
255 b.props.insert(
256 k.into(),
257 Value::Bool(obj_prop(&options, k).map(|v| v.truthy()).unwrap_or(false)),
258 );
259 }
260 }
261 Ok(ev)
262}
263pub(crate) fn focus_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
268 let ev = event_ctor(it, t, a)?;
269 let options = arg(a, 1);
270 if let Value::Object(o) = &ev {
271 o.borrow_mut()
272 .props
273 .insert("relatedTarget".into(), obj_prop(&options, "relatedTarget").unwrap_or(Value::Null));
274 }
275 Ok(ev)
276}
277pub(crate) fn pointer_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
284 let ev = mouse_event_ctor(it, t, a)?;
285 let options = arg(a, 1);
286 if let Value::Object(o) = &ev {
287 let mut b = o.borrow_mut();
288 b.props
289 .insert("pointerId".into(), obj_prop(&options, "pointerId").unwrap_or(Value::Number(0.0)));
290 b.props.insert("width".into(), obj_prop(&options, "width").unwrap_or(Value::Number(1.0)));
291 b.props.insert("height".into(), obj_prop(&options, "height").unwrap_or(Value::Number(1.0)));
292 for k in ["pressure", "tangentialPressure", "tiltX", "tiltY", "twist"] {
293 b.props
294 .insert(k.into(), obj_prop(&options, k).unwrap_or(Value::Number(0.0)));
295 }
296 b.props
297 .insert("pointerType".into(), obj_prop(&options, "pointerType").unwrap_or_else(|| Value::str("")));
298 b.props.insert(
299 "isPrimary".into(),
300 Value::Bool(obj_prop(&options, "isPrimary").map(|v| v.truthy()).unwrap_or(false)),
301 );
302 }
303 Ok(ev)
304}
305pub(crate) fn input_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
310 let ev = event_ctor(it, t, a)?;
311 let options = arg(a, 1);
312 if let Value::Object(o) = &ev {
313 let mut b = o.borrow_mut();
314 b.props.insert("data".into(), obj_prop(&options, "data").unwrap_or(Value::Null));
315 b.props
316 .insert("inputType".into(), obj_prop(&options, "inputType").unwrap_or_else(|| Value::str("")));
317 b.props.insert(
318 "isComposing".into(),
319 Value::Bool(obj_prop(&options, "isComposing").map(|v| v.truthy()).unwrap_or(false)),
320 );
321 }
322 Ok(ev)
323}
324pub(crate) fn progress_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
330 let ev = event_ctor(it, t, a)?;
331 let options = arg(a, 1);
332 if let Value::Object(o) = &ev {
333 let mut b = o.borrow_mut();
334 b.props.insert(
335 "lengthComputable".into(),
336 Value::Bool(obj_prop(&options, "lengthComputable").map(|v| v.truthy()).unwrap_or(false)),
337 );
338 b.props.insert("loaded".into(), obj_prop(&options, "loaded").unwrap_or(Value::Number(0.0)));
339 b.props.insert("total".into(), obj_prop(&options, "total").unwrap_or(Value::Number(0.0)));
340 }
341 Ok(ev)
342}
343pub(crate) fn storage_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
351 let ev = event_ctor(it, t, a)?;
352 let options = arg(a, 1);
353 if let Value::Object(o) = &ev {
354 let mut b = o.borrow_mut();
355 b.props.insert("key".into(), obj_prop(&options, "key").unwrap_or(Value::Null));
356 b.props.insert("oldValue".into(), obj_prop(&options, "oldValue").unwrap_or(Value::Null));
357 b.props.insert("newValue".into(), obj_prop(&options, "newValue").unwrap_or(Value::Null));
358 b.props.insert("url".into(), obj_prop(&options, "url").unwrap_or_else(|| Value::str("")));
359 b.props
360 .insert("storageArea".into(), obj_prop(&options, "storageArea").unwrap_or(Value::Null));
361 }
362 Ok(ev)
363}
364pub(crate) fn pop_state_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
371 let ev = event_ctor(it, t, a)?;
372 let options = arg(a, 1);
373 if let Value::Object(o) = &ev {
374 let mut b = o.borrow_mut();
375 b.props.insert("state".into(), obj_prop(&options, "state").unwrap_or(Value::Null));
376 }
377 Ok(ev)
378}
379pub(crate) fn hash_change_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
386 let ev = event_ctor(it, t, a)?;
387 let options = arg(a, 1);
388 if let Value::Object(o) = &ev {
389 let mut b = o.borrow_mut();
390 b.props
391 .insert("oldURL".into(), obj_prop(&options, "oldURL").unwrap_or_else(|| Value::str("")));
392 b.props
393 .insert("newURL".into(), obj_prop(&options, "newURL").unwrap_or_else(|| Value::str("")));
394 }
395 Ok(ev)
396}
397pub(crate) fn page_transition_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
401 let ev = event_ctor(it, t, a)?;
402 let options = arg(a, 1);
403 if let Value::Object(o) = &ev {
404 o.borrow_mut().props.insert(
405 "persisted".into(),
406 Value::Bool(obj_prop(&options, "persisted").map(|v| v.truthy()).unwrap_or(false)),
407 );
408 }
409 Ok(ev)
410}
411pub(crate) fn composition_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
416 let ev = event_ctor(it, t, a)?;
417 let options = arg(a, 1);
418 if let Value::Object(o) = &ev {
419 o.borrow_mut()
420 .props
421 .insert("data".into(), obj_prop(&options, "data").unwrap_or_else(|| Value::str("")));
422 }
423 Ok(ev)
424}
425pub(crate) fn clipboard_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
432 let ev = event_ctor(it, t, a)?;
433 let options = arg(a, 1);
434 if let Value::Object(o) = &ev {
435 o.borrow_mut()
436 .props
437 .insert("clipboardData".into(), obj_prop(&options, "clipboardData").unwrap_or(Value::Null));
438 }
439 Ok(ev)
440}
441pub(crate) fn animation_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
447 let ev = event_ctor(it, t, a)?;
448 let options = arg(a, 1);
449 if let Value::Object(o) = &ev {
450 let mut b = o.borrow_mut();
451 b.props.insert(
452 "animationName".into(),
453 obj_prop(&options, "animationName").unwrap_or_else(|| Value::str("")),
454 );
455 b.props
456 .insert("elapsedTime".into(), obj_prop(&options, "elapsedTime").unwrap_or(Value::Number(0.0)));
457 b.props.insert(
458 "pseudoElement".into(),
459 obj_prop(&options, "pseudoElement").unwrap_or_else(|| Value::str("")),
460 );
461 }
462 Ok(ev)
463}
464pub(crate) fn transition_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
469 let ev = event_ctor(it, t, a)?;
470 let options = arg(a, 1);
471 if let Value::Object(o) = &ev {
472 let mut b = o.borrow_mut();
473 b.props.insert(
474 "propertyName".into(),
475 obj_prop(&options, "propertyName").unwrap_or_else(|| Value::str("")),
476 );
477 b.props
478 .insert("elapsedTime".into(), obj_prop(&options, "elapsedTime").unwrap_or(Value::Number(0.0)));
479 b.props.insert(
480 "pseudoElement".into(),
481 obj_prop(&options, "pseudoElement").unwrap_or_else(|| Value::str("")),
482 );
483 }
484 Ok(ev)
485}
486pub(crate) fn drag_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
493 let ev = mouse_event_ctor(it, t, a)?;
494 let options = arg(a, 1);
495 if let Value::Object(o) = &ev {
496 o.borrow_mut()
497 .props
498 .insert("dataTransfer".into(), obj_prop(&options, "dataTransfer").unwrap_or(Value::Null));
499 }
500 Ok(ev)
501}
502pub(crate) fn submit_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
507 let ev = event_ctor(it, t, a)?;
508 let options = arg(a, 1);
509 if let Value::Object(o) = &ev {
510 o.borrow_mut()
511 .props
512 .insert("submitter".into(), obj_prop(&options, "submitter").unwrap_or(Value::Null));
513 }
514 Ok(ev)
515}
516pub(crate) fn message_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
523 let ev = event_ctor(it, t, a)?;
524 let options = arg(a, 1);
525 if let Value::Object(o) = &ev {
526 let mut b = o.borrow_mut();
527 b.props.insert("data".into(), obj_prop(&options, "data").unwrap_or(Value::Null));
528 b.props.insert("origin".into(), obj_prop(&options, "origin").unwrap_or_else(|| Value::str("")));
529 b.props.insert(
530 "lastEventId".into(),
531 obj_prop(&options, "lastEventId").unwrap_or_else(|| Value::str("")),
532 );
533 b.props.insert("source".into(), obj_prop(&options, "source").unwrap_or(Value::Null));
534 b.props.insert(
535 "ports".into(),
536 obj_prop(&options, "ports").unwrap_or_else(|| Value::Object(Obj::array(alloc::vec::Vec::new()))),
537 );
538 }
539 Ok(ev)
540}
541pub(crate) fn error_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
547 let ev = event_ctor(it, t, a)?;
548 let options = arg(a, 1);
549 if let Value::Object(o) = &ev {
550 let mut b = o.borrow_mut();
551 b.props
552 .insert("message".into(), obj_prop(&options, "message").unwrap_or_else(|| Value::str("")));
553 b.props
554 .insert("filename".into(), obj_prop(&options, "filename").unwrap_or_else(|| Value::str("")));
555 b.props.insert("lineno".into(), obj_prop(&options, "lineno").unwrap_or(Value::Number(0.0)));
556 b.props.insert("colno".into(), obj_prop(&options, "colno").unwrap_or(Value::Number(0.0)));
557 b.props.insert("error".into(), obj_prop(&options, "error").unwrap_or(Value::Null));
558 }
559 Ok(ev)
560}
561
562pub(crate) fn custom_event_ctor(_it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
567 let event_type = arg(a, 0).to_js_string();
568 let options = arg(a, 1);
569 let (detail, bubbles, cancelable, composed) = if let Value::Object(o) = &options {
570 let b = o.borrow();
571 (
572 b.props.get("detail").cloned().unwrap_or(Value::Undefined),
573 b.props.get("bubbles").map(|v| v.truthy()).unwrap_or(false),
574 b.props.get("cancelable").map(|v| v.truthy()).unwrap_or(false),
575 b.props.get("composed").map(|v| v.truthy()).unwrap_or(false),
576 )
577 } else {
578 (Value::Undefined, false, false, false)
579 };
580 let ev = Obj::plain();
581 {
582 let mut b = ev.borrow_mut();
583 b.props.insert("type".into(), Value::str(&event_type));
584 b.props.insert("detail".into(), detail);
585 b.props.insert("bubbles".into(), Value::Bool(bubbles));
586 b.props.insert("cancelable".into(), Value::Bool(cancelable));
587 b.props.insert("composed".into(), Value::Bool(composed));
589 b.props.insert("defaultPrevented".into(), Value::Bool(false));
590 b.props.insert("isTrusted".into(), Value::Bool(false));
593 b.props.insert("currentTarget".into(), Value::Null);
595 b.props.insert("eventPhase".into(), Value::Number(0.0));
596 b.props.insert("timeStamp".into(), Value::Number(next_perf_timestamp()));
598 b.props.insert("returnValue".into(), Value::Bool(true));
600 b.props.insert("cancelBubble".into(), Value::Bool(false));
601 b.props
602 .insert("preventDefault".into(), nv("preventDefault", event_prevent_default));
603 b.props.insert(
604 "stopPropagation".into(),
605 nv("stopPropagation", event_target_stop_propagation),
606 );
607 b.props.insert(
614 "stopImmediatePropagation".into(),
615 nv("stopImmediatePropagation", event_stop_immediate_propagation),
616 );
617 b.props.insert(
619 "composedPath".into(),
620 nv("composedPath", event_target_composed_path),
621 );
622 }
623 Ok(Value::Object(ev))
624}
625
626pub(crate) fn event_target_ctor(_it: &mut Interp, _t: Value, _a: &[Value]) -> Result<Value, Value> {
630 let o = Obj::plain();
631 {
632 let mut b = o.borrow_mut();
633 b.props.insert("_listeners".into(), Value::Object(Obj::plain()));
634 b.props.insert(
635 "addEventListener".into(),
636 nv("addEventListener", event_target_add_event_listener),
637 );
638 b.props.insert(
639 "removeEventListener".into(),
640 nv("removeEventListener", event_target_remove_event_listener),
641 );
642 b.props
643 .insert("dispatchEvent".into(), nv("dispatchEvent", event_target_dispatch_event));
644 }
645 Ok(Value::Object(o))
646}
647pub(crate) fn event_target_listeners(this: &Value) -> Option<super::super::value::ObjRef> {
648 if let Value::Object(o) = this {
649 if let Some(Value::Object(l)) = o.borrow().props.get("_listeners") {
650 return Some(l.clone());
651 }
652 }
653 None
654}
655pub(crate) fn event_target_listener_cb(entry: &Value) -> Value {
657 if let Value::Object(o) = entry {
658 if let ObjKind::Array(items) = &o.borrow().kind {
659 if let Some(cb) = items.first() {
660 return cb.clone();
661 }
662 }
663 }
664 entry.clone()
665}
666pub(crate) fn event_target_listener_once(entry: &Value) -> bool {
668 if let Value::Object(o) = entry {
669 if let ObjKind::Array(items) = &o.borrow().kind {
670 if let Some(v) = items.get(1) {
671 return v.truthy();
672 }
673 }
674 }
675 false
676}
677pub(crate) fn event_target_listener_aborted(entry: &Value) -> bool {
680 if let Value::Object(o) = entry {
681 if let ObjKind::Array(items) = &o.borrow().kind {
682 if let Some(sig) = items.get(2) {
683 return super::super::dom_bridge::is_signal_aborted(sig);
684 }
685 }
686 }
687 false
688}
689pub(crate) fn event_target_listener_capture(entry: &Value) -> bool {
694 if let Value::Object(o) = entry {
695 if let ObjKind::Array(items) = &o.borrow().kind {
696 if let Some(v) = items.get(3) {
697 return v.truthy();
698 }
699 }
700 }
701 false
702}
703pub(crate) fn event_target_add_event_listener(_it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
714 let Some(listeners) = event_target_listeners(&this) else { return Ok(Value::Undefined) };
715 let etype = arg(a, 0).to_js_string();
716 let cb = arg(a, 1);
717 let (capture, once) = parse_listener_opts(&arg(a, 2));
718 let signal = parse_listener_signal(&arg(a, 2));
719 if signal.as_ref().is_some_and(super::super::dom_bridge::is_signal_aborted) {
720 return Ok(Value::Undefined);
721 }
722 let entry = Value::Object(Obj::array(alloc::vec![
723 cb.clone(),
724 Value::Bool(once),
725 signal.unwrap_or(Value::Undefined),
726 Value::Bool(capture)
727 ]));
728 let existing = listeners.borrow().props.get(&etype).cloned();
729 match existing {
730 Some(Value::Object(arr)) => {
731 if let ObjKind::Array(items) = &mut arr.borrow_mut().kind {
732 let dup = items.iter().any(|v| {
740 match (&event_target_listener_cb(v), &cb) {
741 (Value::Object(x), Value::Object(y)) => {
742 Rc::ptr_eq(x, y) && event_target_listener_capture(v) == capture
743 }
744 _ => false,
745 }
746 });
747 if !dup {
748 items.push(entry);
749 }
750 }
751 }
752 _ => {
753 listeners
754 .borrow_mut()
755 .props
756 .insert(etype, Value::Object(Obj::array(alloc::vec![entry])));
757 }
758 }
759 Ok(Value::Undefined)
760}
761pub(crate) fn event_target_remove_event_listener(_it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
770 let Some(listeners) = event_target_listeners(&this) else { return Ok(Value::Undefined) };
771 let etype = arg(a, 0).to_js_string();
772 let cb = arg(a, 1);
773 let (capture, _once) = parse_listener_opts(&arg(a, 2));
774 if let Some(Value::Object(arr)) = listeners.borrow().props.get(&etype).cloned() {
775 if let ObjKind::Array(items) = &mut arr.borrow_mut().kind {
776 items.retain(|v| match (&event_target_listener_cb(v), &cb) {
777 (Value::Object(x), Value::Object(y)) => {
778 !(Rc::ptr_eq(x, y) && event_target_listener_capture(v) == capture)
779 }
780 _ => true,
781 });
782 }
783 }
784 Ok(Value::Undefined)
785}
786pub(crate) fn event_target_dispatch_event(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
788 let ev = arg(a, 0);
789 if let Some(listeners) = event_target_listeners(&this) {
790 let etype = if let Value::Object(eo) = &ev {
791 eo.borrow().props.get("type").map(|v| v.to_js_string()).unwrap_or_default()
792 } else {
793 String::new()
794 };
795 let cbs = match listeners.borrow().props.get(&etype) {
796 Some(Value::Object(arr)) => match &arr.borrow().kind {
797 ObjKind::Array(items) => items.clone(),
798 _ => alloc::vec::Vec::new(),
799 },
800 _ => alloc::vec::Vec::new(),
801 };
802 if let Value::Object(eo) = &ev {
803 let mut e = eo.borrow_mut();
804 e.props.insert("target".into(), this.clone());
805 e.props.insert("srcElement".into(), this.clone());
808 e.props.insert("currentTarget".into(), this.clone());
812 e.props.insert("eventPhase".into(), Value::Number(2.0));
813 }
814 for entry in cbs {
815 if event_target_listener_aborted(&entry) {
816 continue;
817 }
818 let cb = event_target_listener_cb(&entry);
819 let once = event_target_listener_once(&entry);
820 let ctx = alloc::format!("{} listener (EventTarget)", etype);
821 it.call_listener(&cb, this.clone(), core::slice::from_ref(&ev), &ctx);
822 if once {
826 if let Some(Value::Object(arr)) = listeners.borrow().props.get(&etype).cloned() {
827 if let ObjKind::Array(items) = &mut arr.borrow_mut().kind {
828 items.retain(|v| match (&event_target_listener_cb(v), &cb) {
829 (Value::Object(x), Value::Object(y)) => !Rc::ptr_eq(x, y),
830 _ => true,
831 });
832 }
833 }
834 }
835 let stopped = if let Value::Object(eo) = &ev {
839 matches!(eo.borrow().props.get("_stopImmediate"), Some(Value::Bool(true)))
840 } else {
841 false
842 };
843 if stopped {
844 break;
845 }
846 }
847 if let Value::Object(eo) = &ev {
850 let mut e = eo.borrow_mut();
851 e.props.insert("currentTarget".into(), Value::Null);
852 e.props.insert("eventPhase".into(), Value::Number(0.0));
853 }
854 }
855 let default_prevented = if let Value::Object(eo) = &ev {
856 matches!(eo.borrow().props.get("defaultPrevented"), Some(Value::Bool(true)))
857 } else {
858 false
859 };
860 Ok(Value::Bool(!default_prevented))
861}
862
863pub(crate) fn message_channel_ctor(it: &mut Interp, _t: Value, _a: &[Value]) -> Result<Value, Value> {
868 let port1 = message_port_new(it)?;
869 let port2 = message_port_new(it)?;
870 if let (Value::Object(p1), Value::Object(p2)) = (&port1, &port2) {
871 p1.borrow_mut().props.insert("_peer".into(), port2.clone());
872 p2.borrow_mut().props.insert("_peer".into(), port1.clone());
873 }
874 let ch = Obj::plain();
875 {
876 let mut b = ch.borrow_mut();
877 b.props.insert("port1".into(), port1);
878 b.props.insert("port2".into(), port2);
879 }
880 Ok(Value::Object(ch))
881}
882pub(crate) fn message_port_new(it: &mut Interp) -> Result<Value, Value> {
883 let port = event_target_ctor(it, Value::Undefined, &[])?;
884 if let Value::Object(o) = &port {
885 let mut b = o.borrow_mut();
886 b.props
887 .insert("postMessage".into(), nv("postMessage", message_port_post_message));
888 b.props.insert("start".into(), nv("start", dom_noop));
889 b.props.insert("close".into(), nv("close", message_port_close));
890 }
891 Ok(port)
892}
893pub(crate) fn message_port_is_closed(port: &Value) -> bool {
894 matches!(port, Value::Object(o) if o.borrow().props.get("_closed").map(|v| v.truthy()).unwrap_or(false))
895}
896pub(crate) fn message_port_post_message(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
900 if message_port_is_closed(&this) {
901 return Ok(Value::Undefined);
902 }
903 let data = structured_clone(it, Value::Undefined, a)?;
904 let peer = if let Value::Object(o) = &this {
905 o.borrow().props.get("_peer").cloned()
906 } else {
907 None
908 };
909 if let Some(peer) = peer {
910 message_port_deliver(it, &peer, data);
911 }
912 Ok(Value::Undefined)
913}
914pub(crate) fn message_port_deliver(it: &mut Interp, port: &Value, data: Value) {
918 if message_port_is_closed(port) {
919 return;
920 }
921 let ev = Obj::plain();
922 ev.borrow_mut().props.insert("type".into(), Value::str("message"));
923 ev.borrow_mut().props.insert("data".into(), data);
924 let onmessage = if let Value::Object(o) = port {
925 o.borrow().props.get("onmessage").cloned()
926 } else {
927 None
928 };
929 if let Some(f) = onmessage.and_then(callable_or_none) {
930 it.call_listener(
931 &f,
932 port.clone(),
933 &[Value::Object(ev.clone())],
934 "MessagePort onmessage",
935 );
936 }
937 let _ = event_target_dispatch_event(it, port.clone(), &[Value::Object(ev)]);
938}
939pub(crate) fn message_port_close(_it: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
940 if let Value::Object(o) = &this {
941 o.borrow_mut().props.insert("_closed".into(), Value::Bool(true));
942 }
943 Ok(Value::Undefined)
944}
945
946pub(crate) fn bc_registry(it: &mut Interp) -> super::super::value::ObjRef {
952 let existing = it.global.borrow().vars.get("__bc_registry").cloned();
953 if let Some(Value::Object(o)) = existing {
954 return o;
955 }
956 let reg = Obj::plain();
957 it.global
958 .borrow_mut()
959 .vars
960 .insert("__bc_registry".into(), Value::Object(reg.clone()));
961 reg
962}
963pub(crate) fn broadcast_channel_ctor(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
964 let name = arg(a, 0).to_js_string();
965 let base = event_target_ctor(it, Value::Undefined, &[])?;
966 if let Value::Object(o) = &base {
967 let mut b = o.borrow_mut();
968 b.props.insert("name".into(), Value::str(&name));
969 b.props
970 .insert("postMessage".into(), nv("postMessage", broadcast_channel_post_message));
971 b.props.insert("close".into(), nv("close", message_port_close));
972 }
973 let reg = bc_registry(it);
974 let existing = reg.borrow().props.get(&name).cloned();
975 match existing {
976 Some(Value::Object(arr)) => {
977 if let ObjKind::Array(items) = &mut arr.borrow_mut().kind {
978 items.push(base.clone());
979 }
980 }
981 _ => {
982 reg.borrow_mut()
983 .props
984 .insert(name, Value::Object(Obj::array(alloc::vec![base.clone()])));
985 }
986 }
987 Ok(base)
988}
989pub(crate) fn broadcast_channel_post_message(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
992 if message_port_is_closed(&this) {
993 return Ok(Value::Undefined);
994 }
995 let name = if let Value::Object(o) = &this {
996 o.borrow().props.get("name").map(|v| v.to_js_string()).unwrap_or_default()
997 } else {
998 String::new()
999 };
1000 let data = structured_clone(it, Value::Undefined, a)?;
1001 let reg = bc_registry(it);
1002 let peers: Vec<Value> = match reg.borrow().props.get(&name) {
1003 Some(Value::Object(arr)) => match &arr.borrow().kind {
1004 ObjKind::Array(items) => items.clone(),
1005 _ => alloc::vec::Vec::new(),
1006 },
1007 _ => alloc::vec::Vec::new(),
1008 };
1009 for peer in peers {
1010 let is_self = matches!((&peer, &this), (Value::Object(p), Value::Object(t)) if Rc::ptr_eq(p, t));
1011 if is_self {
1012 continue;
1013 }
1014 message_port_deliver(it, &peer, data.clone());
1015 }
1016 Ok(Value::Undefined)
1017}
1018
1019pub(crate) fn command_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
1023 let ev = event_ctor(it, t, a)?;
1024 let options = arg(a, 1);
1025 if let Value::Object(o) = &ev {
1026 let mut b = o.borrow_mut();
1027 b.props
1028 .insert("command".into(), obj_prop(&options, "command").unwrap_or_else(|| Value::str("")));
1029 b.props
1030 .insert("source".into(), obj_prop(&options, "source").unwrap_or(Value::Null));
1031 }
1032 Ok(ev)
1033}
1034
1035pub(crate) fn toggle_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
1038 let ev = event_ctor(it, t, a)?;
1039 let options = arg(a, 1);
1040 if let Value::Object(o) = &ev {
1041 let mut b = o.borrow_mut();
1042 b.props.insert(
1043 "oldState".into(),
1044 obj_prop(&options, "oldState").unwrap_or_else(|| Value::str("closed")),
1045 );
1046 b.props.insert(
1047 "newState".into(),
1048 obj_prop(&options, "newState").unwrap_or_else(|| Value::str("open")),
1049 );
1050 }
1051 Ok(ev)
1052}
1053
1054pub(crate) fn form_data_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
1057 let ev = event_ctor(it, t, a)?;
1058 let options = arg(a, 1);
1059 if let Value::Object(o) = &ev {
1060 let mut b = o.borrow_mut();
1061 b.props
1062 .insert("formData".into(), obj_prop(&options, "formData").unwrap_or(Value::Null));
1063 }
1064 Ok(ev)
1065}
1066