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 t = arg(a, 0).to_js_string(); if t == "readystatechange" || t == "load" { let k = match &this { Value::Object(o) => alloc::format!("{:?}", core::mem::discriminant(&o.borrow().kind)), _ => String::from("?") }; crate::warn!("[TMPRS] generic add {} this={} stack={:?}", t, k, _it.call_names.iter().rev().take(5).collect::<Vec<_>>()); } } let Some(listeners) = event_target_listeners(&this) else { return Ok(Value::Undefined) };
716 let etype = arg(a, 0).to_js_string();
717 let cb = arg(a, 1);
718 let (capture, once) = parse_listener_opts(&arg(a, 2));
719 let signal = parse_listener_signal(&arg(a, 2));
720 if signal.as_ref().is_some_and(super::super::dom_bridge::is_signal_aborted) {
721 return Ok(Value::Undefined);
722 }
723 let entry = Value::Object(Obj::array(alloc::vec![
724 cb.clone(),
725 Value::Bool(once),
726 signal.unwrap_or(Value::Undefined),
727 Value::Bool(capture)
728 ]));
729 let existing = listeners.borrow().props.get(&etype).cloned();
730 match existing {
731 Some(Value::Object(arr)) => {
732 if let ObjKind::Array(items) = &mut arr.borrow_mut().kind {
733 let dup = items.iter().any(|v| {
741 match (&event_target_listener_cb(v), &cb) {
742 (Value::Object(x), Value::Object(y)) => {
743 Rc::ptr_eq(x, y) && event_target_listener_capture(v) == capture
744 }
745 _ => false,
746 }
747 });
748 if !dup {
749 items.push(entry);
750 }
751 }
752 }
753 _ => {
754 listeners
755 .borrow_mut()
756 .props
757 .insert(etype, Value::Object(Obj::array(alloc::vec![entry])));
758 }
759 }
760 Ok(Value::Undefined)
761}
762pub(crate) fn event_target_remove_event_listener(_it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
771 let Some(listeners) = event_target_listeners(&this) else { return Ok(Value::Undefined) };
772 let etype = arg(a, 0).to_js_string();
773 let cb = arg(a, 1);
774 let (capture, _once) = parse_listener_opts(&arg(a, 2));
775 if let Some(Value::Object(arr)) = listeners.borrow().props.get(&etype).cloned() {
776 if let ObjKind::Array(items) = &mut arr.borrow_mut().kind {
777 items.retain(|v| match (&event_target_listener_cb(v), &cb) {
778 (Value::Object(x), Value::Object(y)) => {
779 !(Rc::ptr_eq(x, y) && event_target_listener_capture(v) == capture)
780 }
781 _ => true,
782 });
783 }
784 }
785 Ok(Value::Undefined)
786}
787pub(crate) fn event_target_dispatch_event(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
789 let ev = arg(a, 0);
790 if let Some(listeners) = event_target_listeners(&this) {
791 let etype = if let Value::Object(eo) = &ev {
792 eo.borrow().props.get("type").map(|v| v.to_js_string()).unwrap_or_default()
793 } else {
794 String::new()
795 };
796 let cbs = match listeners.borrow().props.get(&etype) {
797 Some(Value::Object(arr)) => match &arr.borrow().kind {
798 ObjKind::Array(items) => items.clone(),
799 _ => alloc::vec::Vec::new(),
800 },
801 _ => alloc::vec::Vec::new(),
802 };
803 if let Value::Object(eo) = &ev {
804 let mut e = eo.borrow_mut();
805 e.props.insert("target".into(), this.clone());
806 e.props.insert("srcElement".into(), this.clone());
809 e.props.insert("currentTarget".into(), this.clone());
813 e.props.insert("eventPhase".into(), Value::Number(2.0));
814 }
815 for entry in cbs {
816 if event_target_listener_aborted(&entry) {
817 continue;
818 }
819 let cb = event_target_listener_cb(&entry);
820 let once = event_target_listener_once(&entry);
821 let ctx = alloc::format!("{} listener (EventTarget)", etype);
822 it.call_listener(&cb, this.clone(), core::slice::from_ref(&ev), &ctx);
823 if once {
827 if let Some(Value::Object(arr)) = listeners.borrow().props.get(&etype).cloned() {
828 if let ObjKind::Array(items) = &mut arr.borrow_mut().kind {
829 items.retain(|v| match (&event_target_listener_cb(v), &cb) {
830 (Value::Object(x), Value::Object(y)) => !Rc::ptr_eq(x, y),
831 _ => true,
832 });
833 }
834 }
835 }
836 let stopped = if let Value::Object(eo) = &ev {
840 matches!(eo.borrow().props.get("_stopImmediate"), Some(Value::Bool(true)))
841 } else {
842 false
843 };
844 if stopped {
845 break;
846 }
847 }
848 if let Value::Object(eo) = &ev {
851 let mut e = eo.borrow_mut();
852 e.props.insert("currentTarget".into(), Value::Null);
853 e.props.insert("eventPhase".into(), Value::Number(0.0));
854 }
855 }
856 let default_prevented = if let Value::Object(eo) = &ev {
857 matches!(eo.borrow().props.get("defaultPrevented"), Some(Value::Bool(true)))
858 } else {
859 false
860 };
861 Ok(Value::Bool(!default_prevented))
862}
863
864pub(crate) fn message_channel_ctor(it: &mut Interp, _t: Value, _a: &[Value]) -> Result<Value, Value> {
869 let port1 = message_port_new(it)?;
870 let port2 = message_port_new(it)?;
871 if let (Value::Object(p1), Value::Object(p2)) = (&port1, &port2) {
872 p1.borrow_mut().props.insert("_peer".into(), port2.clone());
873 p2.borrow_mut().props.insert("_peer".into(), port1.clone());
874 }
875 let ch = Obj::plain();
876 {
877 let mut b = ch.borrow_mut();
878 b.props.insert("port1".into(), port1);
879 b.props.insert("port2".into(), port2);
880 }
881 Ok(Value::Object(ch))
882}
883pub(crate) fn message_port_new(it: &mut Interp) -> Result<Value, Value> {
884 let port = event_target_ctor(it, Value::Undefined, &[])?;
885 if let Value::Object(o) = &port {
886 let mut b = o.borrow_mut();
887 b.props
888 .insert("postMessage".into(), nv("postMessage", message_port_post_message));
889 b.props.insert("start".into(), nv("start", dom_noop));
890 b.props.insert("close".into(), nv("close", message_port_close));
891 }
892 Ok(port)
893}
894pub(crate) fn message_port_is_closed(port: &Value) -> bool {
895 matches!(port, Value::Object(o) if o.borrow().props.get("_closed").map(|v| v.truthy()).unwrap_or(false))
896}
897pub(crate) fn message_port_post_message(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
901 if message_port_is_closed(&this) {
902 return Ok(Value::Undefined);
903 }
904 let data = structured_clone(it, Value::Undefined, a)?;
905 let peer = if let Value::Object(o) = &this {
906 o.borrow().props.get("_peer").cloned()
907 } else {
908 None
909 };
910 if let Some(peer) = peer {
911 message_port_deliver(it, &peer, data);
912 }
913 Ok(Value::Undefined)
914}
915pub(crate) fn message_port_deliver(it: &mut Interp, port: &Value, data: Value) {
919 if message_port_is_closed(port) {
920 return;
921 }
922 let ev = Obj::plain();
923 ev.borrow_mut().props.insert("type".into(), Value::str("message"));
924 ev.borrow_mut().props.insert("data".into(), data);
925 let onmessage = if let Value::Object(o) = port {
926 o.borrow().props.get("onmessage").cloned()
927 } else {
928 None
929 };
930 if let Some(f) = onmessage.and_then(callable_or_none) {
931 it.call_listener(
932 &f,
933 port.clone(),
934 &[Value::Object(ev.clone())],
935 "MessagePort onmessage",
936 );
937 }
938 let _ = event_target_dispatch_event(it, port.clone(), &[Value::Object(ev)]);
939}
940pub(crate) fn message_port_close(_it: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
941 if let Value::Object(o) = &this {
942 o.borrow_mut().props.insert("_closed".into(), Value::Bool(true));
943 }
944 Ok(Value::Undefined)
945}
946
947pub(crate) fn bc_registry(it: &mut Interp) -> super::super::value::ObjRef {
953 let existing = it.global.borrow().vars.get("__bc_registry").cloned();
954 if let Some(Value::Object(o)) = existing {
955 return o;
956 }
957 let reg = Obj::plain();
958 it.global
959 .borrow_mut()
960 .vars
961 .insert("__bc_registry".into(), Value::Object(reg.clone()));
962 reg
963}
964pub(crate) fn broadcast_channel_ctor(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
965 let name = arg(a, 0).to_js_string();
966 let base = event_target_ctor(it, Value::Undefined, &[])?;
967 if let Value::Object(o) = &base {
968 let mut b = o.borrow_mut();
969 b.props.insert("name".into(), Value::str(&name));
970 b.props
971 .insert("postMessage".into(), nv("postMessage", broadcast_channel_post_message));
972 b.props.insert("close".into(), nv("close", message_port_close));
973 }
974 let reg = bc_registry(it);
975 let existing = reg.borrow().props.get(&name).cloned();
976 match existing {
977 Some(Value::Object(arr)) => {
978 if let ObjKind::Array(items) = &mut arr.borrow_mut().kind {
979 items.push(base.clone());
980 }
981 }
982 _ => {
983 reg.borrow_mut()
984 .props
985 .insert(name, Value::Object(Obj::array(alloc::vec![base.clone()])));
986 }
987 }
988 Ok(base)
989}
990pub(crate) fn broadcast_channel_post_message(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
993 if message_port_is_closed(&this) {
994 return Ok(Value::Undefined);
995 }
996 let name = if let Value::Object(o) = &this {
997 o.borrow().props.get("name").map(|v| v.to_js_string()).unwrap_or_default()
998 } else {
999 String::new()
1000 };
1001 let data = structured_clone(it, Value::Undefined, a)?;
1002 let reg = bc_registry(it);
1003 let peers: Vec<Value> = match reg.borrow().props.get(&name) {
1004 Some(Value::Object(arr)) => match &arr.borrow().kind {
1005 ObjKind::Array(items) => items.clone(),
1006 _ => alloc::vec::Vec::new(),
1007 },
1008 _ => alloc::vec::Vec::new(),
1009 };
1010 for peer in peers {
1011 let is_self = matches!((&peer, &this), (Value::Object(p), Value::Object(t)) if Rc::ptr_eq(p, t));
1012 if is_self {
1013 continue;
1014 }
1015 message_port_deliver(it, &peer, data.clone());
1016 }
1017 Ok(Value::Undefined)
1018}
1019
1020pub(crate) fn command_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
1024 let ev = event_ctor(it, t, a)?;
1025 let options = arg(a, 1);
1026 if let Value::Object(o) = &ev {
1027 let mut b = o.borrow_mut();
1028 b.props
1029 .insert("command".into(), obj_prop(&options, "command").unwrap_or_else(|| Value::str("")));
1030 b.props
1031 .insert("source".into(), obj_prop(&options, "source").unwrap_or(Value::Null));
1032 }
1033 Ok(ev)
1034}
1035
1036pub(crate) fn toggle_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
1039 let ev = event_ctor(it, t, a)?;
1040 let options = arg(a, 1);
1041 if let Value::Object(o) = &ev {
1042 let mut b = o.borrow_mut();
1043 b.props.insert(
1044 "oldState".into(),
1045 obj_prop(&options, "oldState").unwrap_or_else(|| Value::str("closed")),
1046 );
1047 b.props.insert(
1048 "newState".into(),
1049 obj_prop(&options, "newState").unwrap_or_else(|| Value::str("open")),
1050 );
1051 }
1052 Ok(ev)
1053}
1054
1055pub(crate) fn form_data_event_ctor(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
1058 let ev = event_ctor(it, t, a)?;
1059 let options = arg(a, 1);
1060 if let Value::Object(o) = &ev {
1061 let mut b = o.borrow_mut();
1062 b.props
1063 .insert("formData".into(), obj_prop(&options, "formData").unwrap_or(Value::Null));
1064 }
1065 Ok(ev)
1066}
1067
1068
1069pub(crate) fn document_create_event(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
1074 let iface = arg(a, 0).to_js_string();
1075 let ev = event_ctor(it, Value::Undefined, &[Value::str("")])?;
1076 if let Value::Object(o) = &ev {
1077 let mut b = o.borrow_mut();
1078 b.props.insert("initEvent".into(), nv("initEvent", event_init_event));
1079 b.props.insert("initCustomEvent".into(), nv("initCustomEvent", event_init_event));
1080 b.props.insert("initUIEvent".into(), nv("initUIEvent", event_init_event));
1081 b.props.insert("initMouseEvent".into(), nv("initMouseEvent", event_init_event));
1082 b.props.insert("initKeyboardEvent".into(), nv("initKeyboardEvent", event_init_event));
1083 if iface.eq_ignore_ascii_case("CustomEvent") {
1084 b.props.insert("detail".into(), Value::Null);
1085 }
1086 }
1087 Ok(ev)
1088}
1089
1090pub(crate) fn event_init_event(_it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
1092 if let Value::Object(o) = &this {
1093 let mut b = o.borrow_mut();
1094 b.props.insert("type".into(), Value::str(arg(a, 0).to_js_string()));
1095 b.props.insert("bubbles".into(), Value::Bool(arg(a, 1).truthy()));
1096 b.props.insert("cancelable".into(), Value::Bool(arg(a, 2).truthy()));
1097 if a.len() > 3 && b.props.contains_key("detail") {
1098 b.props.insert("detail".into(), arg(a, 3));
1099 }
1100 }
1101 Ok(Value::Undefined)
1102}
1103
1104fn event_target_proto_call(it: &mut Interp, this: Value, a: &[Value], name: &str) -> Result<Value, Value> {
1112 { let t = arg(a, 0).to_js_string(); if t == "readystatechange" { let k = match &this { Value::Object(o) => alloc::format!("{:?} own={}", core::mem::discriminant(&o.borrow().kind), o.borrow().props.contains_key(name)), _ => String::from("?") }; crate::warn!("[TMPRS] proto_call {} {} this={}", name, t, k); } } if let Some(idx) = this_dom_idx(&this) {
1114 let f = it.dom_builtin_get(idx, name);
1116 return it.call_value(&f, this, a);
1117 }
1118 if let Value::Object(o) = &this {
1119 let own = o.borrow().props.get(name).cloned();
1120 if let Some(f @ Value::Object(_)) = own {
1121 return it.call_value(&f, this, a);
1122 }
1123 }
1124 match name {
1125 "addEventListener" => event_target_add_event_listener(it, this, a),
1126 "removeEventListener" => event_target_remove_event_listener(it, this, a),
1127 _ => event_target_dispatch_event(it, this, a),
1128 }
1129}
1130pub(crate) fn event_target_proto_add(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
1131 event_target_proto_call(it, this, a, "addEventListener")
1132}
1133pub(crate) fn event_target_proto_remove(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
1134 event_target_proto_call(it, this, a, "removeEventListener")
1135}
1136pub(crate) fn event_target_proto_dispatch(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
1137 event_target_proto_call(it, this, a, "dispatchEvent")
1138}