1use alloc::format;
7use alloc::rc::Rc;
8use alloc::string::String;
9use alloc::string::ToString;
10use alloc::vec;
11use alloc::vec::Vec;
12use core::cell::RefCell;
13use core::sync::atomic::{AtomicU64, Ordering};
14
15use super::interp::{Interp, Scope};
16use super::value::*;
17
18const WINDOW_MIRRORED_GLOBALS: &[&str] = &[
23 "navigator", "screen", "location", "document", "history",
24 "localStorage", "sessionStorage", "performance", "console",
25 "JSON", "Math", "Date", "Promise", "Array", "Object", "String",
26 "Number", "Boolean", "RegExp", "Error", "Map", "Set", "Symbol",
27 "XMLHttpRequest", "URL", "URLSearchParams", "Path2D", "ImageData", "Range", "NodeFilter",
28 "customElements", "ReadableStream", "WritableStream", "TransformStream", "MediaSource", "Worker",
29 "TextEncoderStream", "TextDecoderStream",
30];
31
32const ARRAY_PROTO_METHODS: &[&str] = &[
36 "push", "pop", "shift", "unshift", "slice", "splice", "concat",
37 "join", "reverse", "sort", "indexOf", "lastIndexOf", "includes",
38 "find", "findIndex", "findLast", "findLastIndex", "filter", "map",
39 "forEach", "reduce", "reduceRight", "some", "every", "flat",
40 "flatMap", "fill", "copyWithin", "at", "keys", "values", "entries",
41 "toString",
42];
43
44const STRING_PROTO_METHODS: &[&str] = &[
51 "charAt", "charCodeAt", "codePointAt", "localeCompare", "indexOf",
52 "lastIndexOf", "includes", "startsWith", "endsWith", "slice",
53 "substring", "substr", "toUpperCase", "toLowerCase", "trim",
54 "trimStart", "trimEnd", "split", "replace", "replaceAll", "match",
55 "matchAll", "search", "repeat", "concat", "padStart", "padEnd",
56 "at", "toString", "valueOf", "normalize",
57];
58
59pub fn install(global: &Rc<RefCell<Scope>>) {
60 let mut g = global.borrow_mut();
61
62 let console = Obj::plain();
64 {
65 let mut c = console.borrow_mut();
66 c.props.insert("log".into(), nv("console.log", console_log));
67 c.props
68 .insert("error".into(), nv("console.error", console_log));
69 c.props
70 .insert("warn".into(), nv("console.warn", console_log));
71 c.props
72 .insert("info".into(), nv("console.info", console_log));
73 c.props
74 .insert("debug".into(), nv("console.debug", console_log));
75 c.props
76 .insert("trace".into(), nv("console.trace", console_log));
77 c.props.insert("dir".into(), nv("console.dir", console_log));
78 c.props
79 .insert("table".into(), nv("console.table", console_log));
80 c.props
81 .insert("group".into(), nv("console.group", console_log));
82 c.props
83 .insert("groupEnd".into(), nv("console.groupEnd", dom_noop));
84 c.props.insert(
85 "groupCollapsed".into(),
86 nv("console.groupCollapsed", console_log),
87 );
88 c.props
89 .insert("count".into(), nv("console.count", dom_noop));
90 c.props
91 .insert("assert".into(), nv("console.assert", console_log));
92 c.props.insert("time".into(), nv("console.time", dom_noop));
93 c.props
94 .insert("timeEnd".into(), nv("console.timeEnd", dom_noop));
95 }
96 g.vars.insert("console".into(), Value::Object(console));
97
98 let math = Obj::plain();
100 {
101 let mut m = math.borrow_mut();
102 m.props
103 .insert("PI".into(), Value::Number(core::f64::consts::PI));
104 m.props
105 .insert("E".into(), Value::Number(core::f64::consts::E));
106 m.props.insert("floor".into(), nv("Math.floor", math_floor));
107 m.props.insert("ceil".into(), nv("Math.ceil", math_ceil));
108 m.props.insert("round".into(), nv("Math.round", math_round));
109 m.props.insert("trunc".into(), nv("Math.trunc", math_trunc));
110 m.props.insert("abs".into(), nv("Math.abs", math_abs));
111 m.props.insert("sign".into(), nv("Math.sign", math_sign));
112 m.props.insert("sqrt".into(), nv("Math.sqrt", math_sqrt));
113 m.props.insert("pow".into(), nv("Math.pow", math_pow));
114 m.props.insert("min".into(), nv("Math.min", math_min));
115 m.props.insert("max".into(), nv("Math.max", math_max));
116 m.props
117 .insert("random".into(), nv("Math.random", math_random));
118 m.props.insert("sin".into(), nv("Math.sin", math_sin));
119 m.props.insert("cos".into(), nv("Math.cos", math_cos));
120 m.props.insert("tan".into(), nv("Math.tan", math_tan));
121 m.props.insert("asin".into(), nv("Math.asin", math_asin));
122 m.props.insert("acos".into(), nv("Math.acos", math_acos));
123 m.props.insert("atan".into(), nv("Math.atan", math_atan));
124 m.props.insert("atan2".into(), nv("Math.atan2", math_atan2));
125 m.props.insert("log".into(), nv("Math.log", math_log));
126 m.props.insert("log2".into(), nv("Math.log2", math_log2));
127 m.props.insert("log10".into(), nv("Math.log10", math_log10));
128 m.props.insert("cbrt".into(), nv("Math.cbrt", math_cbrt));
129 m.props.insert("hypot".into(), nv("Math.hypot", math_hypot));
130 m.props.insert("exp".into(), nv("Math.exp", math_exp));
131 m.props.insert("fround".into(), nv("Math.fround", math_fround));
132 m.props.insert("f16round".into(), nv("Math.f16round", math_f16round));
133 m.props.insert("clamp".into(), nv("Math.clamp", math_clamp));
134 m.props.insert("sumPrecise".into(), nv("Math.sumPrecise", math_sum_precise));
135 m.props.insert("clz32".into(), nv("Math.clz32", math_clz32));
136 m.props.insert("imul".into(), nv("Math.imul", math_imul));
137 m.props.insert("sinh".into(), nv("Math.sinh", math_sinh));
138 m.props.insert("cosh".into(), nv("Math.cosh", math_cosh));
139 m.props.insert("tanh".into(), nv("Math.tanh", math_tanh));
140 m.props.insert("asinh".into(), nv("Math.asinh", math_asinh));
141 m.props.insert("acosh".into(), nv("Math.acosh", math_acosh));
142 m.props.insert("atanh".into(), nv("Math.atanh", math_atanh));
143 m.props.insert("expm1".into(), nv("Math.expm1", math_expm1));
144 m.props.insert("log1p".into(), nv("Math.log1p", math_log1p));
145 m.props.insert("LN2".into(), Value::Number(core::f64::consts::LN_2));
148 m.props.insert("LN10".into(), Value::Number(core::f64::consts::LN_10));
149 m.props.insert("LOG2E".into(), Value::Number(core::f64::consts::LOG2_E));
150 m.props.insert("LOG10E".into(), Value::Number(core::f64::consts::LOG10_E));
151 m.props.insert("SQRT2".into(), Value::Number(core::f64::consts::SQRT_2));
152 m.props.insert("SQRT1_2".into(), Value::Number(1.0 / core::f64::consts::SQRT_2));
153 m.props
154 .insert("PI".into(), Value::Number(core::f64::consts::PI));
155 m.props
156 .insert("E".into(), Value::Number(core::f64::consts::E));
157 }
158 g.vars.insert("Math".into(), Value::Object(math));
159
160 g.vars.insert("Intl".into(), create_intl_object());
168
169 {
176 let css_ns = Obj::plain();
177 css_ns
178 .borrow_mut()
179 .props
180 .insert("escape".into(), nv("CSS.escape", css_escape_static));
181 css_ns
182 .borrow_mut()
183 .props
184 .insert("supports".into(), nv("CSS.supports", css_supports_static));
185 {
190 let mut b = css_ns.borrow_mut();
191 b.props.insert("number".into(), nv("CSS.number", css_number_static));
192 b.props.insert("percent".into(), nv("CSS.percent", css_percent_static));
193 b.props.insert("px".into(), nv("CSS.px", css_px_static));
194 b.props.insert("em".into(), nv("CSS.em", css_em_static));
195 b.props.insert("rem".into(), nv("CSS.rem", css_rem_static));
196 b.props.insert("deg".into(), nv("CSS.deg", css_deg_static));
197 }
198 g.vars.insert("CSS".into(), Value::Object(css_ns));
199 }
200
201 let json = Obj::plain();
203 {
204 let mut j = json.borrow_mut();
205 j.props.insert("parse".into(), nv("JSON.parse", json_parse));
206 j.props
207 .insert("stringify".into(), nv("JSON.stringify", json_stringify));
208 j.props
211 .insert("rawJSON".into(), nv("JSON.rawJSON", json_raw_json));
212 j.props
213 .insert("isRawJSON".into(), nv("JSON.isRawJSON", json_is_raw_json));
214 }
215 g.vars.insert("JSON".into(), Value::Object(json));
216
217 let object_ctor = Obj::native("Object", object_ctor);
219 object_ctor
220 .borrow_mut()
221 .props
222 .insert("keys".into(), nv("Object.keys", object_keys));
223 object_ctor
224 .borrow_mut()
225 .props
226 .insert("values".into(), nv("Object.values", object_values));
227 object_ctor
228 .borrow_mut()
229 .props
230 .insert("entries".into(), nv("Object.entries", object_entries));
231 object_ctor
232 .borrow_mut()
233 .props
234 .insert("assign".into(), nv("Object.assign", object_assign));
235 object_ctor.borrow_mut().props.insert(
236 "fromEntries".into(),
237 nv("Object.fromEntries", object_from_entries),
238 );
239 object_ctor.borrow_mut().props.insert(
240 "getOwnPropertyNames".into(),
241 nv("Object.getOwnPropertyNames", object_keys),
242 );
243 object_ctor
244 .borrow_mut()
245 .props
246 .insert("freeze".into(), nv("Object.freeze", object_freeze));
247 object_ctor.borrow_mut().props.insert(
248 "isFrozen".into(),
249 nv("Object.isFrozen", object_is_frozen),
250 );
251 object_ctor
252 .borrow_mut()
253 .props
254 .insert("seal".into(), nv("Object.seal", object_seal));
255 object_ctor
256 .borrow_mut()
257 .props
258 .insert("isSealed".into(), nv("Object.isSealed", object_is_sealed));
259 object_ctor.borrow_mut().props.insert(
260 "preventExtensions".into(),
261 nv("Object.preventExtensions", object_prevent_extensions),
262 );
263 object_ctor.borrow_mut().props.insert(
264 "isExtensible".into(),
265 nv("Object.isExtensible", object_is_extensible),
266 );
267 object_ctor
271 .borrow_mut()
272 .props
273 .insert("is".into(), nv("Object.is", object_is));
274 object_ctor
275 .borrow_mut()
276 .props
277 .insert("create".into(), nv("Object.create", object_create));
278 object_ctor.borrow_mut().props.insert(
279 "defineProperty".into(),
280 nv("Object.defineProperty", object_define_property),
281 );
282 object_ctor.borrow_mut().props.insert(
283 "defineProperties".into(),
284 nv("Object.defineProperties", object_define_properties),
285 );
286 object_ctor.borrow_mut().props.insert(
287 "getOwnPropertyDescriptor".into(),
288 nv(
289 "Object.getOwnPropertyDescriptor",
290 object_get_own_property_descriptor,
291 ),
292 );
293 object_ctor.borrow_mut().props.insert(
294 "getOwnPropertyDescriptors".into(),
295 nv(
296 "Object.getOwnPropertyDescriptors",
297 object_get_own_property_descriptors,
298 ),
299 );
300 object_ctor
301 .borrow_mut()
302 .props
303 .insert("hasOwn".into(), nv("Object.hasOwn", object_has_own_static));
304 object_ctor
305 .borrow_mut()
306 .props
307 .insert("groupBy".into(), nv("Object.groupBy", object_group_by));
308 object_ctor.borrow_mut().props.insert(
309 "getPrototypeOf".into(),
310 nv("Object.getPrototypeOf", object_get_prototype_of),
311 );
312 object_ctor.borrow_mut().props.insert(
313 "setPrototypeOf".into(),
314 nv("Object.setPrototypeOf", object_set_prototype_of),
315 );
316 let object_proto = Obj::plain();
322 object_proto
323 .borrow_mut()
324 .props
325 .insert("toString".into(), nv("toString", obj_to_string));
326 object_ctor
327 .borrow_mut()
328 .props
329 .insert("prototype".into(), Value::Object(object_proto.clone()));
330 g.vars.insert("Object".into(), Value::Object(object_ctor));
331
332 let array_ctor = Obj::native("Array", array_ctor);
334 let array_proto = Obj::plain();
335 let unscopables_obj = Obj::plain();
336 {
337 let mut u = unscopables_obj.borrow_mut();
338 for key in [
339 "copyWithin", "entries", "fill", "find", "findIndex",
340 "findLast", "findLastIndex", "flat", "flatMap", "includes",
341 "keys", "values", "at",
342 ] {
343 u.props.insert(key.into(), Value::Bool(true));
344 }
345 }
346 array_proto
347 .borrow_mut()
348 .props
349 .insert("Symbol(Symbol.unscopables)".into(), Value::Object(unscopables_obj));
350 {
364 let probe = Obj::array(alloc::vec::Vec::new());
365 let mut ap = array_proto.borrow_mut();
366 for key in ARRAY_PROTO_METHODS {
367 let v = super::builtins::props_methods::object_get(&probe, key);
368 if !matches!(v, Value::Undefined) {
369 ap.props.insert(alloc::string::String::from(*key), v);
370 }
371 }
372 }
373 array_ctor
374 .borrow_mut()
375 .props
376 .insert("prototype".into(), Value::Object(array_proto));
377 array_ctor
378 .borrow_mut()
379 .props
380 .insert("isArray".into(), nv("Array.isArray", array_is_array));
381 array_ctor
382 .borrow_mut()
383 .props
384 .insert("from".into(), nv("Array.from", array_from));
385 array_ctor
386 .borrow_mut()
387 .props
388 .insert("of".into(), nv("Array.of", array_of));
389 array_ctor
390 .borrow_mut()
391 .props
392 .insert("fromAsync".into(), nv("Array.fromAsync", array_from_async));
393 g.vars.insert("Array".into(), Value::Object(array_ctor));
394
395 let string_ctor_v = nv("String", string_ctor);
397 if let Value::Object(sc) = &string_ctor_v {
398 let mut b = sc.borrow_mut();
399 b.props.insert(
400 "fromCharCode".into(),
401 nv("String.fromCharCode", string_from_char_code),
402 );
403 b.props.insert(
404 "fromCodePoint".into(),
405 nv("String.fromCodePoint", string_from_code_point),
406 );
407 b.props.insert("raw".into(), nv("String.raw", string_raw));
408 let string_proto = Obj::plain();
421 {
422 let mut sp = string_proto.borrow_mut();
423 for key in STRING_PROTO_METHODS {
424 let v = super::builtins::props_methods::string_get("", key);
425 if !matches!(v, Value::Undefined) {
426 sp.props.insert(alloc::string::String::from(*key), v);
427 }
428 }
429 }
430 b.props
431 .insert("prototype".into(), Value::Object(string_proto));
432 }
433 g.vars.insert("String".into(), string_ctor_v);
434 let parse_float_v = nv("parseFloat", global_parse_float);
441 let parse_int_v = nv("parseInt", global_parse_int);
442 let number_ctor_v = nv("Number", number_ctor);
443 if let Value::Object(nc) = &number_ctor_v {
444 let mut b = nc.borrow_mut();
445 b.props.insert(
446 "isInteger".into(),
447 nv("Number.isInteger", number_is_integer),
448 );
449 b.props.insert(
450 "isSafeInteger".into(),
451 nv("Number.isSafeInteger", number_is_safe_integer),
452 );
453 b.props.insert(
454 "isFinite".into(),
455 nv("Number.isFinite", number_is_finite_static),
456 );
457 b.props
458 .insert("isNaN".into(), nv("Number.isNaN", number_is_nan_static));
459 b.props.insert("parseFloat".into(), parse_float_v.clone());
460 b.props.insert("parseInt".into(), parse_int_v.clone());
461 b.props
462 .insert("MAX_SAFE_INTEGER".into(), Value::Number(9007199254740991.0));
463 b.props.insert(
464 "MIN_SAFE_INTEGER".into(),
465 Value::Number(-9007199254740991.0),
466 );
467 b.props
468 .insert("EPSILON".into(), Value::Number(f64::EPSILON));
469 b.props.insert("MAX_VALUE".into(), Value::Number(f64::MAX));
470 b.props
478 .insert("MIN_VALUE".into(), Value::Number(f64::from_bits(1)));
479 b.props.insert("NaN".into(), Value::Number(f64::NAN));
480 b.props
481 .insert("POSITIVE_INFINITY".into(), Value::Number(f64::INFINITY));
482 b.props
483 .insert("NEGATIVE_INFINITY".into(), Value::Number(f64::NEG_INFINITY));
484 }
485 g.vars.insert("Number".into(), number_ctor_v);
486 g.vars.insert("Boolean".into(), nv("Boolean", boolean_ctor));
487
488 let bigint_ctor_v = nv("BigInt", bigint_ctor);
490 if let Value::Object(bc) = &bigint_ctor_v {
491 let mut b = bc.borrow_mut();
492 b.props
493 .insert("asIntN".into(), nv("BigInt.asIntN", bigint_as_int_n));
494 b.props
495 .insert("asUintN".into(), nv("BigInt.asUintN", bigint_as_uint_n));
496 }
497 g.vars.insert("BigInt".into(), bigint_ctor_v);
498
499 g.vars.insert("parseInt".into(), parse_int_v);
501 g.vars.insert("parseFloat".into(), parse_float_v);
502 g.vars.insert("isNaN".into(), nv("isNaN", global_is_nan));
503 g.vars
504 .insert("isFinite".into(), nv("isFinite", global_is_finite));
505 g.vars.insert("eval".into(), nv("eval", global_eval));
511 let function_ctor_v = nv("Function", function_ctor);
518 if let Value::Object(fc) = &function_ctor_v {
519 let function_proto = Obj::plain();
520 {
521 let mut fp = function_proto.borrow_mut();
522 for key in ["call", "apply", "bind"] {
523 let v = super::builtins::props_methods::function_method(key);
524 if !matches!(v, Value::Undefined) {
525 fp.props.insert(alloc::string::String::from(key), v);
526 }
527 }
528 fp.props.insert(
529 "toString".into(),
530 nv("toString", super::builtins::props_methods::fn_to_string),
531 );
532 }
533 fc.borrow_mut()
534 .props
535 .insert("prototype".into(), Value::Object(function_proto));
536 }
537 g.vars.insert("Function".into(), function_ctor_v);
538
539 let location = Obj::plain();
542 {
543 let mut l = location.borrow_mut();
544 for k in [
545 "href", "protocol", "username", "password", "host", "hostname", "port", "origin",
546 "pathname", "search", "hash",
547 ] {
548 l.props.insert(String::from(k), Value::str(""));
549 }
550 l.props
551 .insert("assign".into(), nv("location.assign", location_assign));
552 l.props
553 .insert("replace".into(), nv("location.replace", location_replace));
554 l.props
555 .insert("reload".into(), nv("location.reload", location_reload));
556 l.props.insert(
557 "toString".into(),
558 nv("location.toString", location_to_string),
559 );
560 l.props.insert("_is_location".into(), Value::Bool(true));
563 }
564
565 let history = Obj::plain();
567 {
568 let mut h = history.borrow_mut();
569 h.props.insert("length".into(), Value::Number(1.0));
570 h.props.insert("state".into(), Value::Null);
571 h.props
572 .insert("scrollRestoration".into(), Value::str("auto"));
573 h.props.insert(
574 "pushState".into(),
575 nv("history.pushState", history_push_state),
576 );
577 h.props.insert(
578 "replaceState".into(),
579 nv("history.replaceState", history_replace_state),
580 );
581 h.props
582 .insert("back".into(), nv("history.back", history_back));
583 h.props
584 .insert("forward".into(), nv("history.forward", history_forward));
585 h.props.insert("go".into(), nv("history.go", history_go));
586 }
587
588 let document = Obj::host("document");
590 {
591 let mut d = document.borrow_mut();
592 d.props.insert("nodeType".into(), Value::Number(9.0));
595 d.props.insert("nodeName".into(), Value::str("#document"));
596 d.props.insert("ownerDocument".into(), Value::Null);
597 d.props.insert(
598 "getElementById".into(),
599 nv("getElementById", document_get_element_by_id),
600 );
601 d.props.insert(
602 "querySelector".into(),
603 nv("querySelector", document_query_selector),
604 );
605 d.props.insert(
606 "querySelectorAll".into(),
607 nv("querySelectorAll", document_query_selector_all),
608 );
609 d.props.insert(
615 "elementFromPoint".into(),
616 nv("elementFromPoint", document_element_from_point),
617 );
618 d.props.insert(
619 "elementsFromPoint".into(),
620 nv("elementsFromPoint", document_elements_from_point),
621 );
622 d.props.insert(
623 "createElement".into(),
624 nv("document.createElement", document_create_element),
625 );
626 d.props.insert(
627 "createElementNS".into(),
628 nv("document.createElementNS", document_create_element_ns),
629 );
630 d.props.insert(
631 "createTextNode".into(),
632 nv("document.createTextNode", document_create_text_node),
633 );
634 d.props.insert(
635 "createComment".into(),
636 nv("document.createComment", document_create_comment),
637 );
638 d.props.insert(
640 "createEvent".into(),
641 nv("document.createEvent", document_create_event),
642 );
643 d.props.insert(
645 "createDocumentFragment".into(),
646 nv("document.createDocumentFragment", document_create_document_fragment),
647 );
648 d.props
649 .insert("location".into(), Value::Object(location.clone()));
650 d.props.insert(
651 "getElementsByClassName".into(),
652 nv(
653 "getElementsByClassName",
654 document_get_elements_by_class_name,
655 ),
656 );
657 d.props.insert(
658 "getElementsByTagName".into(),
659 nv("getElementsByTagName", document_get_elements_by_tag_name),
660 );
661 d.props.insert(
662 "getElementsByTagNameNS".into(),
663 nv("getElementsByTagNameNS", document_get_elements_by_tag_name_ns),
664 );
665 d.props.insert(
666 "getElementsByName".into(),
667 nv("getElementsByName", document_get_elements_by_name),
668 );
669 d.props.insert("title".into(), Value::str(""));
670 d.props.insert("activeElement".into(), Value::Null);
671 d.props.insert("_listeners".into(), Value::Object(Obj::plain()));
676 d.props.insert("readyState".into(), Value::str("complete"));
677 d.props.insert("designMode".into(), Value::str("off"));
682 d.props.insert("fullscreenElement".into(), Value::Null);
684 d.props.insert("webkitFullscreenElement".into(), Value::Null);
685 d.props.insert("mozFullScreenElement".into(), Value::Null);
686 d.props.insert("msFullscreenElement".into(), Value::Null);
687 d.props.insert("fullscreenEnabled".into(), Value::Bool(true));
688 d.props.insert("webkitFullscreenEnabled".into(), Value::Bool(true));
689 d.props.insert("mozFullScreenEnabled".into(), Value::Bool(true));
690 d.props.insert("msFullscreenEnabled".into(), Value::Bool(true));
691 d.props.insert("onfullscreenchange".into(), Value::Null);
692 d.props.insert("onwebkitfullscreenchange".into(), Value::Null);
693 d.props.insert("onfullscreenerror".into(), Value::Null);
694 d.props.insert(
695 "exitFullscreen".into(),
696 nv("document.exitFullscreen", document_exit_fullscreen),
697 );
698 d.props.insert(
699 "webkitExitFullscreen".into(),
700 nv("document.webkitExitFullscreen", document_exit_fullscreen),
701 );
702 d.props.insert(
703 "webkitCancelFullScreen".into(),
704 nv("document.webkitCancelFullScreen", document_exit_fullscreen),
705 );
706 d.props.insert(
707 "mozCancelFullScreen".into(),
708 nv("document.mozCancelFullScreen", document_exit_fullscreen),
709 );
710 d.props.insert(
711 "msExitFullscreen".into(),
712 nv("document.msExitFullscreen", document_exit_fullscreen),
713 );
714 d.props.insert("pointerLockElement".into(), Value::Null);
717 d.props.insert(
718 "exitPointerLock".into(),
719 nv("document.exitPointerLock", document_exit_pointer_lock),
720 );
721 d.props.insert("pictureInPictureElement".into(), Value::Null);
725 d.props.insert("pictureInPictureEnabled".into(), Value::Bool(true));
726 d.props.insert(
727 "exitPictureInPicture".into(),
728 nv("document.exitPictureInPicture", document_exit_picture_in_picture),
729 );
730 d.props.insert(
737 "hasStorageAccess".into(),
738 nv("document.hasStorageAccess", document_has_storage_access),
739 );
740 d.props.insert(
741 "requestStorageAccess".into(),
742 nv("document.requestStorageAccess", document_request_storage_access),
743 );
744 d.props.insert(
754 "addEventListener".into(),
755 nv("document.addEventListener", document_add_event_listener),
756 );
757 d.props.insert(
762 "removeEventListener".into(),
763 nv("document.removeEventListener", document_remove_event_listener),
764 );
765 d.props.insert(
768 "dispatchEvent".into(),
769 nv("document.dispatchEvent", document_dispatch_event),
770 );
771 d.props
772 .insert("write".into(), nv("document.write", dom_noop));
773 d.props.insert(
774 "createRange".into(),
775 nv("document.createRange", document_create_range),
776 );
777 d.props.insert(
780 "createTreeWalker".into(),
781 nv("document.createTreeWalker", document_create_tree_walker),
782 );
783 d.props.insert(
788 "createNodeIterator".into(),
789 nv("document.createNodeIterator", document_create_node_iterator),
790 );
791 d.props.insert(
795 "importNode".into(),
796 nv("document.importNode", doc_import_node),
797 );
798 d.props.insert(
799 "adoptNode".into(),
800 nv("document.adoptNode", doc_adopt_node),
801 );
802 d.props.insert(
805 "createAttribute".into(),
806 nv("document.createAttribute", document_create_attribute),
807 );
808 d.props.insert(
809 "getSelection".into(),
810 nv("document.getSelection", document_get_selection),
811 );
812 d.props.insert(
813 "execCommand".into(),
814 nv("document.execCommand", document_exec_command),
815 );
816 d.props.insert(
820 "getAnimations".into(),
821 nv("document.getAnimations", |_, _, _| Ok(Value::Object(Obj::array(alloc::vec![])))),
822 );
823 d.props.insert(
824 "hasFocus".into(),
825 nv("document.hasFocus", |_, _, _| Ok(Value::Bool(true))),
826 );
827 d.props.insert("visibilityState".into(), Value::str("visible"));
834 d.props.insert("hidden".into(), Value::Bool(false));
835 d.props.insert("characterSet".into(), Value::str("UTF-8"));
844 d.props.insert("compatMode".into(), Value::str("CSS1Compat"));
845 d.props.insert("contentType".into(), Value::str("text/html"));
846 d.props.insert("doctype".into(), Value::Null);
847 d.props.insert("currentScript".into(), Value::Null);
856 let implementation = Obj::plain();
867 {
868 let mut im = implementation.borrow_mut();
869 im.props.insert(
870 "hasFeature".into(),
871 nv("DOMImplementation.hasFeature", |_, _, _| Ok(Value::Bool(true))),
872 );
873 im.props.insert(
874 "createDocumentType".into(),
875 nv("DOMImplementation.createDocumentType", dom_implementation_create_document_type),
876 );
877 im.props.insert(
878 "createHTMLDocument".into(),
879 nv("DOMImplementation.createHTMLDocument", dom_implementation_create_html_document),
880 );
881 im.props.insert(
882 "createDocument".into(),
883 nv("DOMImplementation.createDocument", dom_implementation_create_document),
884 );
885 }
886 d.props
887 .insert("implementation".into(), Value::Object(implementation));
888 }
889 fn dom_implementation_create_document_type(
896 _it: &mut Interp,
897 _t: Value,
898 a: &[Value],
899 ) -> Result<Value, Value> {
900 let obj = Obj::plain();
901 {
902 let mut b = obj.borrow_mut();
903 b.props.insert("nodeType".into(), Value::Number(10.0));
904 b.props.insert("name".into(), Value::str(arg(a, 0).to_js_string()));
905 b.props.insert("publicId".into(), Value::str(arg(a, 1).to_js_string()));
906 b.props.insert("systemId".into(), Value::str(arg(a, 2).to_js_string()));
907 }
908 Ok(Value::Object(obj))
909 }
910 fn dom_implementation_create_html_document(
911 _it: &mut Interp,
912 _t: Value,
913 a: &[Value],
914 ) -> Result<Value, Value> {
915 let title = if !a.is_empty() && !matches!(a[0], Value::Undefined) {
916 a[0].to_js_string()
917 } else {
918 String::new()
919 };
920 let doc = Obj::plain();
921 {
922 let mut b = doc.borrow_mut();
923 b.props.insert("nodeType".into(), Value::Number(9.0));
924 b.props.insert("nodeName".into(), Value::str("#document"));
925 b.props.insert("title".into(), Value::str(&title));
926 b.props.insert("body".into(), Value::Null);
927 b.props.insert("head".into(), Value::Null);
928 b.props.insert("documentElement".into(), Value::Null);
929 b.props.insert("createElement".into(), nv("createElement", document_create_element));
930 }
931 Ok(Value::Object(doc))
932 }
933 fn dom_implementation_create_document(
934 _it: &mut Interp,
935 _t: Value,
936 a: &[Value],
937 ) -> Result<Value, Value> {
938 let ns = arg(a, 0);
939 let qname = arg(a, 1);
940 let doc = Obj::plain();
941 {
942 let mut b = doc.borrow_mut();
943 b.props.insert("nodeType".into(), Value::Number(9.0));
944 b.props.insert("nodeName".into(), Value::str("#document"));
945 b.props.insert("namespaceURI".into(), ns);
946 b.props.insert("qualifiedName".into(), qname);
947 b.props.insert("createElement".into(), nv("createElement", document_create_element));
948 }
949 Ok(Value::Object(doc))
950 }
951 g.vars
952 .insert("document".into(), Value::Object(document.clone()));
953
954 let window = Obj::plain();
956 let screen_obj = Obj::plain();
957 {
958 let mut w = window.borrow_mut();
959 w.props.insert("document".into(), Value::Object(document));
960 w.props
961 .insert("location".into(), Value::Object(location.clone()));
962 w.props
963 .insert("history".into(), Value::Object(history.clone()));
964 w.props.insert(
965 "addEventListener".into(),
966 nv("window.addEventListener", window_add_event_listener),
967 );
968 w.props.insert(
969 "removeEventListener".into(),
970 nv("window.removeEventListener", window_remove_event_listener),
971 );
972 w.props.insert(
973 "dispatchEvent".into(),
974 nv("window.dispatchEvent", window_dispatch_event),
975 );
976 w.props.insert("print".into(), nv("window.print", dom_noop));
979 w.props.insert("scrollY".into(), Value::Number(0.0));
980 w.props.insert("pageYOffset".into(), Value::Number(0.0));
981 w.props.insert("scrollX".into(), Value::Number(0.0));
982 w.props.insert("pageXOffset".into(), Value::Number(0.0));
983 w.props
984 .insert("scrollTo".into(), nv("scrollTo", window_scroll_to));
985 w.props
986 .insert("scroll".into(), nv("scroll", window_scroll_to));
987 w.props
994 .insert("scrollBy".into(), nv("window.scrollBy", window_scroll_by));
995 w.props
996 .insert("matchMedia".into(), nv("matchMedia", window_match_media));
997 w.props
1003 .insert("postMessage".into(), nv("postMessage", window_post_message));
1004 w.props.insert("alert".into(), nv("alert", console_log));
1005 w.props
1010 .insert("confirm".into(), nv("window.confirm", window_confirm));
1011 w.props
1012 .insert("prompt".into(), nv("window.prompt", window_prompt));
1013 w.props
1017 .insert("open".into(), nv("window.open", window_open));
1018 w.props
1019 .insert("close".into(), nv("window.close", window_close));
1020 w.props
1023 .insert("stop".into(), nv("window.stop", window_stop));
1024 w.props
1025 .insert("focus".into(), nv("window.focus", window_focus));
1026 w.props
1027 .insert("blur".into(), nv("window.blur", window_focus));
1028 w.props.insert(
1035 "getSelection".into(),
1036 nv("window.getSelection", document_get_selection),
1037 );
1038 w.props.insert("self".into(), Value::Object(window.clone()));
1044 w.props.insert("top".into(), Value::Object(window.clone()));
1045 w.props.insert("parent".into(), Value::Object(window.clone()));
1046 w.props.insert("frames".into(), Value::Object(window.clone()));
1047 w.props.insert("name".into(), Value::str(""));
1048 w.props.insert(
1049 "getComputedStyle".into(),
1050 nv("getComputedStyle", get_computed_style),
1051 );
1052 w.props.insert(
1053 "localStorage".into(),
1054 Value::Object(Obj::host("storage:local")),
1055 );
1056 w.props.insert(
1057 "sessionStorage".into(),
1058 Value::Object(Obj::host("storage:session")),
1059 );
1060 let vw = super::super::layout::VIEWPORT_HINT_W.load(core::sync::atomic::Ordering::Relaxed);
1062 let vh = super::super::layout::VIEWPORT_HINT_H.load(core::sync::atomic::Ordering::Relaxed);
1063 let vw_f = if vw > 0 { vw as f64 } else { 1024.0 };
1064 let vh_f = if vh > 0 { vh as f64 } else { 600.0 };
1065 w.props.insert("innerWidth".into(), Value::Number(vw_f));
1066 w.props.insert("innerHeight".into(), Value::Number(vh_f));
1067 w.props.insert("outerWidth".into(), Value::Number(vw_f));
1068 w.props.insert("outerHeight".into(), Value::Number(vh_f));
1069 w.props
1070 .insert("devicePixelRatio".into(), Value::Number(1.0));
1071 {
1082 let mut s = screen_obj.borrow_mut();
1083 s.props.insert("width".into(), Value::Number(vw_f));
1084 s.props.insert("height".into(), Value::Number(vh_f));
1085 s.props.insert("availWidth".into(), Value::Number(vw_f));
1086 s.props.insert("availHeight".into(), Value::Number(vh_f));
1087 s.props.insert("colorDepth".into(), Value::Number(24.0));
1088 s.props.insert("pixelDepth".into(), Value::Number(24.0));
1089 let orientation = Obj::plain();
1090 let otype = if vw_f >= vh_f { "landscape-primary" } else { "portrait-primary" };
1091 orientation.borrow_mut().props.insert("type".into(), Value::str(otype));
1092 orientation.borrow_mut().props.insert("angle".into(), Value::Number(0.0));
1093 orientation
1099 .borrow_mut()
1100 .props
1101 .insert("lock".into(), nv("screen.orientation.lock", screen_orientation_lock));
1102 orientation.borrow_mut().props.insert(
1103 "unlock".into(),
1104 nv("screen.orientation.unlock", screen_orientation_unlock),
1105 );
1106 s.props.insert("orientation".into(), Value::Object(orientation));
1107 }
1108 w.props.insert("screen".into(), Value::Object(screen_obj.clone()));
1109 }
1110 let cookie_store = Obj::plain();
1115 {
1116 let mut cs = cookie_store.borrow_mut();
1117 cs.props.insert("get".into(), nv("cookieStore.get", cookie_store_get));
1118 cs.props.insert("getAll".into(), nv("cookieStore.getAll", cookie_store_get_all));
1119 cs.props.insert("set".into(), nv("cookieStore.set", cookie_store_set));
1120 cs.props.insert("delete".into(), nv("cookieStore.delete", cookie_store_delete));
1121 }
1122 window
1123 .borrow_mut()
1124 .props
1125 .insert("cookieStore".into(), Value::Object(cookie_store.clone()));
1126
1127 let custom_elements = Obj::plain();
1129 {
1130 let mut ce = custom_elements.borrow_mut();
1131 ce.props.insert("define".into(), nv("customElements.define", custom_elements_define));
1132 ce.props.insert("get".into(), nv("customElements.get", custom_elements_get));
1133 ce.props.insert("whenDefined".into(), nv("customElements.whenDefined", custom_elements_when_defined));
1134 ce.props.insert("upgrade".into(), nv("customElements.upgrade", custom_elements_upgrade));
1135 ce.props.insert("_registry".into(), Value::Object(Obj::plain()));
1136 }
1137 window
1138 .borrow_mut()
1139 .props
1140 .insert("customElements".into(), Value::Object(custom_elements.clone()));
1141
1142 window
1144 .borrow_mut()
1145 .props
1146 .insert("ReadableStream".into(), nv("ReadableStream", readable_stream_ctor));
1147 window
1148 .borrow_mut()
1149 .props
1150 .insert("WritableStream".into(), nv("WritableStream", writable_stream_ctor));
1151 window
1152 .borrow_mut()
1153 .props
1154 .insert("TransformStream".into(), nv("TransformStream", transform_stream_ctor));
1155
1156 let media_source_ctor_obj = Obj::native("MediaSource", media_source_ctor);
1158 media_source_ctor_obj.borrow_mut().props.insert(
1159 "isTypeSupported".into(),
1160 nv("MediaSource.isTypeSupported", media_source_is_type_supported),
1161 );
1162 let media_source_ctor_val = Value::Object(media_source_ctor_obj);
1163 window
1164 .borrow_mut()
1165 .props
1166 .insert("MediaSource".into(), media_source_ctor_val.clone());
1167 let worker_ctor_val = nv("Worker", worker_ctor);
1168 window
1169 .borrow_mut()
1170 .props
1171 .insert("Worker".into(), worker_ctor_val.clone());
1172 let text_encoder_stream_ctor_val = nv("TextEncoderStream", text_encoder_stream_ctor);
1173 let text_decoder_stream_ctor_val = nv("TextDecoderStream", text_decoder_stream_ctor);
1174 window
1175 .borrow_mut()
1176 .props
1177 .insert("TextEncoderStream".into(), text_encoder_stream_ctor_val.clone());
1178 window
1179 .borrow_mut()
1180 .props
1181 .insert("TextDecoderStream".into(), text_decoder_stream_ctor_val.clone());
1182
1183 g.vars.insert("window".into(), Value::Object(window));
1184 g.vars.insert("screen".into(), Value::Object(screen_obj));
1185 g.vars.insert("cookieStore".into(), Value::Object(cookie_store));
1186 g.vars.insert("customElements".into(), Value::Object(custom_elements));
1187 g.vars.insert("ReadableStream".into(), nv("ReadableStream", readable_stream_ctor));
1188 g.vars.insert("WritableStream".into(), nv("WritableStream", writable_stream_ctor));
1189 g.vars.insert("TransformStream".into(), nv("TransformStream", transform_stream_ctor));
1190 g.vars.insert("MediaSource".into(), media_source_ctor_val);
1191 g.vars.insert("Worker".into(), worker_ctor_val);
1192 g.vars.insert("TextEncoderStream".into(), text_encoder_stream_ctor_val);
1193 g.vars.insert("TextDecoderStream".into(), text_decoder_stream_ctor_val);
1194 g.vars.insert(
1195 "innerWidth".into(),
1196 Value::Number({
1197 let v =
1198 super::super::layout::VIEWPORT_HINT_W.load(core::sync::atomic::Ordering::Relaxed);
1199 if v > 0 {
1200 v as f64
1201 } else {
1202 1024.0
1203 }
1204 }),
1205 );
1206 g.vars.insert(
1207 "innerHeight".into(),
1208 Value::Number({
1209 let v =
1210 super::super::layout::VIEWPORT_HINT_H.load(core::sync::atomic::Ordering::Relaxed);
1211 if v > 0 {
1212 v as f64
1213 } else {
1214 600.0
1215 }
1216 }),
1217 );
1218 g.vars.insert(
1219 "getComputedStyle".into(),
1220 nv("getComputedStyle", get_computed_style),
1221 );
1222 g.vars.insert(
1223 "localStorage".into(),
1224 Value::Object(Obj::host("storage:local")),
1225 );
1226 g.vars.insert(
1227 "sessionStorage".into(),
1228 Value::Object(Obj::host("storage:session")),
1229 );
1230
1231 g.vars.insert(
1233 "URLSearchParams".into(),
1234 nv("URLSearchParams", url_search_params_ctor),
1235 );
1236 g.vars.insert(
1237 "URLPattern".into(),
1238 nv("URLPattern", url_pattern_ctor),
1239 );
1240 g.vars
1241 .insert("FormData".into(), nv("FormData", form_data_ctor));
1242 {
1248 let url_ctor_val = nv("URL", url_ctor);
1249 if let Value::Object(o) = &url_ctor_val {
1250 let mut b = o.borrow_mut();
1251 b.props.insert("canParse".into(), nv("URL.canParse", url_can_parse));
1252 b.props.insert("parse".into(), nv("URL.parse", url_parse));
1255 b.props.insert(
1256 "createObjectURL".into(),
1257 nv("URL.createObjectURL", url_create_object_url),
1258 );
1259 b.props.insert(
1260 "revokeObjectURL".into(),
1261 nv("URL.revokeObjectURL", url_revoke_object_url),
1262 );
1263 }
1264 g.vars.insert("URL".into(), url_ctor_val);
1265 }
1266
1267 g.vars
1271 .insert("XMLSerializer".into(), nv("XMLSerializer", xml_serializer_ctor));
1272
1273 g.vars.insert(
1275 "encodeURIComponent".into(),
1276 nv("encodeURIComponent", js_encode_uri_component),
1277 );
1278 g.vars.insert(
1279 "decodeURIComponent".into(),
1280 nv("decodeURIComponent", js_decode_uri_component),
1281 );
1282 g.vars
1283 .insert("encodeURI".into(), nv("encodeURI", js_encode_uri));
1284 g.vars
1285 .insert("decodeURI".into(), nv("decodeURI", js_decode_uri));
1286 g.vars.insert("escape".into(), nv("escape", js_escape));
1289 g.vars.insert("unescape".into(), nv("unescape", js_unescape));
1290 g.vars.insert("ClipboardItem".into(), nv("ClipboardItem", clipboard_item_ctor));
1293 g.vars.insert("EyeDropper".into(), nv("EyeDropper", eye_dropper_ctor));
1300
1301 g.vars.insert("btoa".into(), nv("btoa", btoa));
1303 g.vars.insert("atob".into(), nv("atob", atob));
1304
1305 let navigator = Obj::plain();
1307 {
1308 let mut n = navigator.borrow_mut();
1309 n.props.insert(
1310 "userAgent".into(),
1311 Value::str("AtmOS/1.0 (Raspberry Pi; aarch64) AtmOSBrowser/1.0"),
1312 );
1313 n.props.insert("platform".into(), Value::str("AtmOS"));
1314 n.props.insert("language".into(), Value::str("ja-JP"));
1315 n.props.insert("onLine".into(), Value::Bool(true));
1316 n.props.insert("vendor".into(), Value::str("Sugimura Lab"));
1317 n.props.insert("cookieEnabled".into(), Value::Bool(true));
1325 n.props
1326 .insert("hardwareConcurrency".into(), Value::Number(4.0));
1327 n.props.insert("maxTouchPoints".into(), Value::Number(0.0));
1328 n.props.insert(
1329 "languages".into(),
1330 Value::Object(Obj::array(alloc::vec![Value::str("ja-JP")])),
1331 );
1332 n.props.insert("webdriver".into(), Value::Bool(false));
1333 let ua_data = Obj::plain();
1339 {
1340 let mut u = ua_data.borrow_mut();
1341 let brand_entry = Obj::plain();
1342 brand_entry.borrow_mut().props.insert("brand".into(), Value::str("AtmOSBrowser"));
1343 brand_entry.borrow_mut().props.insert("version".into(), Value::str("1"));
1344 u.props.insert(
1345 "brands".into(),
1346 Value::Object(Obj::array(alloc::vec![Value::Object(brand_entry)])),
1347 );
1348 u.props.insert("mobile".into(), Value::Bool(false));
1349 u.props.insert("platform".into(), Value::str("AtmOS"));
1350 u.props.insert(
1351 "getHighEntropyValues".into(),
1352 nv("getHighEntropyValues", navigator_get_high_entropy_values),
1353 );
1354 }
1355 n.props.insert("userAgentData".into(), Value::Object(ua_data));
1356 }
1357 let clipboard = Obj::plain();
1362 {
1363 let mut c = clipboard.borrow_mut();
1364 c.props.insert("_clipboard".into(), Value::str(""));
1365 c.props.insert("writeText".into(), nv("writeText", clipboard_write_text));
1366 c.props.insert("readText".into(), nv("readText", clipboard_read_text));
1367 c.props.insert("write".into(), nv("write", navigator_clipboard_write));
1371 c.props.insert("read".into(), nv("read", navigator_clipboard_read));
1372 }
1373 navigator
1374 .borrow_mut()
1375 .props
1376 .insert("clipboard".into(), Value::Object(clipboard));
1377 let storage_mgr = Obj::plain();
1384 {
1385 let mut s = storage_mgr.borrow_mut();
1386 s.props.insert("estimate".into(), nv("estimate", navigator_storage_estimate));
1387 s.props.insert("persist".into(), nv("persist", navigator_storage_persist));
1388 s.props.insert("persisted".into(), nv("persisted", navigator_storage_persist));
1389 }
1390 navigator
1391 .borrow_mut()
1392 .props
1393 .insert("storage".into(), Value::Object(storage_mgr));
1394 navigator
1397 .borrow_mut()
1398 .props
1399 .insert("sendBeacon".into(), nv("sendBeacon", navigator_send_beacon));
1400 let geolocation = Obj::plain();
1407 {
1408 let mut geo = geolocation.borrow_mut();
1409 geo.props.insert(
1410 "getCurrentPosition".into(),
1411 nv("getCurrentPosition", geolocation_get_current_position),
1412 );
1413 geo.props
1414 .insert("watchPosition".into(), nv("watchPosition", geolocation_watch_position));
1415 geo.props
1416 .insert("clearWatch".into(), nv("clearWatch", geolocation_clear_watch));
1417 }
1418 navigator
1419 .borrow_mut()
1420 .props
1421 .insert("geolocation".into(), Value::Object(geolocation));
1422 let permissions = Obj::plain();
1430 permissions
1431 .borrow_mut()
1432 .props
1433 .insert("query".into(), nv("permissions.query", permissions_query));
1434 navigator
1435 .borrow_mut()
1436 .props
1437 .insert("permissions".into(), Value::Object(permissions));
1438 let wake_lock = Obj::plain();
1444 wake_lock
1445 .borrow_mut()
1446 .props
1447 .insert("request".into(), nv("wakeLock.request", wake_lock_request));
1448 navigator
1449 .borrow_mut()
1450 .props
1451 .insert("wakeLock".into(), Value::Object(wake_lock));
1452 navigator
1460 .borrow_mut()
1461 .props
1462 .insert("canShare".into(), nv("navigator.canShare", navigator_can_share));
1463 navigator
1464 .borrow_mut()
1465 .props
1466 .insert("share".into(), nv("navigator.share", navigator_share));
1467 navigator
1473 .borrow_mut()
1474 .props
1475 .insert("vibrate".into(), nv("navigator.vibrate", navigator_vibrate));
1476 navigator
1482 .borrow_mut()
1483 .props
1484 .insert("getBattery".into(), nv("navigator.getBattery", navigator_get_battery));
1485 let connection = Obj::plain();
1492 {
1493 let mut c = connection.borrow_mut();
1494 c.props.insert("type".into(), Value::str("ethernet"));
1495 c.props.insert("effectiveType".into(), Value::str("4g"));
1496 c.props.insert("downlink".into(), Value::Number(10.0));
1497 c.props.insert("rtt".into(), Value::Number(50.0));
1498 c.props.insert("saveData".into(), Value::Bool(false));
1499 c.props
1500 .insert("addEventListener".into(), nv("addEventListener", dom_noop));
1501 c.props
1502 .insert("removeEventListener".into(), nv("removeEventListener", dom_noop));
1503 }
1504 navigator
1505 .borrow_mut()
1506 .props
1507 .insert("connection".into(), Value::Object(connection));
1508 let locks = Obj::plain();
1515 {
1516 let mut l = locks.borrow_mut();
1517 l.props.insert("request".into(), nv("navigator.locks.request", navigator_locks_request));
1518 l.props.insert("query".into(), nv("navigator.locks.query", navigator_locks_query));
1519 }
1520 navigator.borrow_mut().props.insert("locks".into(), Value::Object(locks));
1521 g.vars.insert("navigator".into(), Value::Object(navigator));
1522
1523 let performance = Obj::plain();
1525 performance
1526 .borrow_mut()
1527 .props
1528 .insert("now".into(), nv("performance.now", performance_now));
1529 performance
1534 .borrow_mut()
1535 .props
1536 .insert("timeOrigin".into(), Value::Number(epoch_ms_now()));
1537 {
1543 let origin = libm::floor(epoch_ms_now());
1544 let timing = Obj::plain();
1545 {
1546 let mut t = timing.borrow_mut();
1547 for key in [
1548 "navigationStart", "fetchStart", "domainLookupStart", "domainLookupEnd",
1549 "connectStart", "connectEnd", "secureConnectionStart", "requestStart",
1550 "responseStart", "responseEnd", "domLoading", "domInteractive",
1551 "domContentLoadedEventStart", "domContentLoadedEventEnd", "domComplete",
1552 "loadEventStart", "loadEventEnd",
1553 ] {
1554 t.props.insert(key.into(), Value::Number(origin));
1555 }
1556 for key in ["unloadEventStart", "unloadEventEnd", "redirectStart", "redirectEnd"] {
1557 t.props.insert(key.into(), Value::Number(0.0));
1558 }
1559 }
1560 let navigation = Obj::plain();
1561 {
1562 let mut n = navigation.borrow_mut();
1563 n.props.insert("type".into(), Value::Number(0.0)); n.props.insert("redirectCount".into(), Value::Number(0.0));
1565 }
1566 let mut p = performance.borrow_mut();
1567 p.props.insert("timing".into(), Value::Object(timing));
1568 p.props.insert("navigation".into(), Value::Object(navigation));
1569 }
1570 {
1576 let mut p = performance.borrow_mut();
1577 p.props.insert("_entries".into(), Value::Object(Obj::array(alloc::vec::Vec::new())));
1578 p.props.insert("mark".into(), nv("mark", perf_mark));
1579 p.props.insert("measure".into(), nv("measure", perf_measure));
1580 p.props.insert("getEntries".into(), nv("getEntries", perf_get_entries));
1584 p.props.insert(
1585 "getEntriesByType".into(),
1586 nv("getEntriesByType", perf_get_entries_by_type),
1587 );
1588 p.props.insert(
1589 "getEntriesByName".into(),
1590 nv("getEntriesByName", perf_get_entries_by_name),
1591 );
1592 p.props.insert("clearMarks".into(), nv("clearMarks", perf_clear_marks));
1593 p.props
1594 .insert("clearMeasures".into(), nv("clearMeasures", perf_clear_measures));
1595 p.props
1598 .insert("_observers".into(), Value::Object(Obj::array(alloc::vec::Vec::new())));
1599 }
1600 g.vars
1601 .insert("performance".into(), Value::Object(performance));
1602 let performance_observer_ctor_val = nv("PerformanceObserver", performance_observer_ctor);
1603 if let Value::Object(po) = &performance_observer_ctor_val {
1608 po.borrow_mut().props.insert(
1609 "supportedEntryTypes".into(),
1610 Value::Object(Obj::array(alloc::vec![Value::str("mark"), Value::str("measure")])),
1611 );
1612 }
1613 g.vars
1614 .insert("PerformanceObserver".into(), performance_observer_ctor_val);
1615
1616 let ab_ctor = nv("ArrayBuffer", arraybuffer_ctor);
1620 if let Value::Object(o) = &ab_ctor {
1621 o.borrow_mut()
1622 .props
1623 .insert("isView".into(), nv("isView", arraybuffer_is_view));
1624 }
1625 g.vars.insert("ArrayBuffer".into(), ab_ctor);
1626 let mut register_typed_array = |name: &str, ctor: NativeFn, from_fn: NativeFn| {
1627 let f = nv(name, ctor);
1628 if let Value::Object(o) = &f {
1629 o.borrow_mut()
1630 .props
1631 .insert("from".into(), nv("from", from_fn));
1632 let proto = Obj::plain();
1633 proto.borrow_mut().proto = Some(object_proto.clone());
1634 o.borrow_mut()
1635 .props
1636 .insert("prototype".into(), Value::Object(proto.clone()));
1637 proto
1638 .borrow_mut()
1639 .props
1640 .insert("constructor".into(), f.clone());
1641 }
1642 g.vars.insert(String::from(name), f);
1643 };
1644 register_typed_array("Uint8Array", uint8array_ctor, uint8array_from);
1645 register_typed_array("Int8Array", int8array_ctor, int8array_from);
1646 register_typed_array(
1647 "Uint8ClampedArray",
1648 uint8clampedarray_ctor,
1649 uint8clampedarray_from,
1650 );
1651 register_typed_array("Int16Array", int16array_ctor, int16array_from);
1652 register_typed_array("Uint16Array", uint16array_ctor, uint16array_from);
1653 register_typed_array("Int32Array", int32array_ctor, int32array_from);
1654 register_typed_array("Uint32Array", uint32array_ctor, uint32array_from);
1655 register_typed_array("Float16Array", float16array_ctor, float16array_from);
1656 register_typed_array("Float32Array", float32array_ctor, float32array_from);
1657 register_typed_array("Float64Array", float64array_ctor, float64array_from);
1658 if let Some(Value::Object(u8a)) = g.vars.get("Uint8Array").cloned() {
1660 u8a.borrow_mut()
1661 .props
1662 .insert("fromBase64".into(), nv("fromBase64", ta_from_base64));
1663 u8a.borrow_mut()
1664 .props
1665 .insert("fromHex".into(), nv("fromHex", ta_from_hex));
1666 }
1667 g.vars.insert("DataView".into(), nv("DataView", dataview_ctor));
1672 g.vars.insert("Blob".into(), nv("Blob", blob_ctor));
1676 g.vars.insert("File".into(), nv("File", file_ctor));
1681 g.vars.insert("Option".into(), nv("Option", option_ctor));
1689 g.vars
1696 .insert("FileReader".into(), nv("FileReader", file_reader_ctor));
1697
1698 {
1704 let notification_ctor_val = nv("Notification", notification_ctor);
1705 if let Value::Object(o) = ¬ification_ctor_val {
1706 let mut b = o.borrow_mut();
1707 b.props.insert("permission".into(), Value::str("granted"));
1708 b.props.insert(
1709 "requestPermission".into(),
1710 nv("requestPermission", notification_request_permission),
1711 );
1712 }
1713 g.vars.insert("Notification".into(), notification_ctor_val);
1714 }
1715
1716 g.vars
1718 .insert("TextEncoder".into(), nv("TextEncoder", text_encoder_ctor));
1719 g.vars
1720 .insert("TextDecoder".into(), nv("TextDecoder", text_decoder_ctor));
1721
1722 g.vars
1724 .insert("DOMParser".into(), nv("DOMParser", dom_parser_ctor));
1725
1726 let crypto = Obj::plain();
1728 {
1729 let mut c = crypto.borrow_mut();
1730 c.props
1731 .insert("randomUUID".into(), nv("randomUUID", crypto_random_uuid));
1732 c.props.insert(
1733 "getRandomValues".into(),
1734 nv("getRandomValues", crypto_get_random_values),
1735 );
1736 let subtle = Obj::plain();
1740 subtle
1741 .borrow_mut()
1742 .props
1743 .insert("digest".into(), nv("digest", subtle_digest));
1744 c.props.insert("subtle".into(), Value::Object(subtle));
1745 }
1746 g.vars.insert("crypto".into(), Value::Object(crypto));
1747
1748 g.vars.insert(
1750 "structuredClone".into(),
1751 nv("structuredClone", structured_clone),
1752 );
1753
1754 g.vars.insert(
1756 "AbortController".into(),
1757 nv("AbortController", abort_controller_ctor),
1758 );
1759 {
1768 let abort_signal_ns = Obj::native("AbortSignal", abort_signal_illegal_ctor);
1769 abort_signal_ns
1770 .borrow_mut()
1771 .props
1772 .insert("timeout".into(), nv("AbortSignal.timeout", abort_signal_timeout));
1773 abort_signal_ns
1774 .borrow_mut()
1775 .props
1776 .insert("abort".into(), nv("AbortSignal.abort", abort_signal_abort_static));
1777 abort_signal_ns
1778 .borrow_mut()
1779 .props
1780 .insert("any".into(), nv("AbortSignal.any", abort_signal_any));
1781 g.vars
1782 .insert("AbortSignal".into(), Value::Object(abort_signal_ns));
1783 }
1784 let event_target_proto = Obj::plain();
1789 {
1790 let mut b = event_target_proto.borrow_mut();
1791 b.props.insert("addEventListener".into(), nv("addEventListener", event_target_proto_add));
1792 b.props.insert("removeEventListener".into(), nv("removeEventListener", event_target_proto_remove));
1793 b.props.insert("dispatchEvent".into(), nv("dispatchEvent", event_target_proto_dispatch));
1794 }
1795 {
1796 let et_ctor = nv("EventTarget", event_target_ctor);
1797 if let Value::Object(c) = &et_ctor {
1798 c.borrow_mut().props.insert("prototype".into(), Value::Object(event_target_proto.clone()));
1799 event_target_proto.borrow_mut().props.insert("constructor".into(), et_ctor.clone());
1800 }
1801 g.vars.insert("EventTarget".into(), et_ctor);
1802 }
1803 g.vars
1807 .insert("MessageChannel".into(), nv("MessageChannel", message_channel_ctor));
1808 g.vars
1812 .insert("BroadcastChannel".into(), nv("BroadcastChannel", broadcast_channel_ctor));
1813 g.vars.insert("CSSStyleSheet".into(), Value::Object(Obj::plain()));
1814 g.vars.insert("CSSStyleRule".into(), Value::Object(Obj::plain()));
1815 {
1819 let make_dom_cls = |name: &str, parent_proto: Option<&ObjRef>| -> (Value, ObjRef) {
1820 let ctor = Obj::native(name, |it, this, _| match &this {
1829 Value::Object(o) if matches!(o.borrow().kind, ObjKind::DomElement(_)) => Ok(this.clone()),
1830 _ => Err(it.type_error("Illegal constructor")),
1831 });
1832 let proto = Obj::plain();
1833 if let Some(parent) = parent_proto {
1834 proto.borrow_mut().proto = Some(parent.clone());
1835 }
1836 proto
1837 .borrow_mut()
1838 .props
1839 .insert("constructor".into(), Value::Object(ctor.clone()));
1840 ctor.borrow_mut()
1841 .props
1842 .insert("prototype".into(), Value::Object(proto.clone()));
1843 (Value::Object(ctor), proto)
1844 };
1845
1846 let (node_ctor, node_proto) = make_dom_cls("Node", Some(&event_target_proto));
1847 let (element_ctor, element_proto) = make_dom_cls("Element", Some(&node_proto));
1848 dom_forward::install(&node_proto, &element_proto);
1849 let (html_element_ctor, html_element_proto) = make_dom_cls("HTMLElement", Some(&element_proto));
1850
1851 let consts: &[(&str, f64)] = &[
1852 ("ELEMENT_NODE", 1.0),
1853 ("ATTRIBUTE_NODE", 2.0),
1854 ("TEXT_NODE", 3.0),
1855 ("CDATA_SECTION_NODE", 4.0),
1856 ("PROCESSING_INSTRUCTION_NODE", 7.0),
1857 ("COMMENT_NODE", 8.0),
1858 ("DOCUMENT_NODE", 9.0),
1859 ("DOCUMENT_TYPE_NODE", 10.0),
1860 ("DOCUMENT_FRAGMENT_NODE", 11.0),
1861 ("DOCUMENT_POSITION_DISCONNECTED", 1.0),
1862 ("DOCUMENT_POSITION_PRECEDING", 2.0),
1863 ("DOCUMENT_POSITION_FOLLOWING", 4.0),
1864 ("DOCUMENT_POSITION_CONTAINS", 8.0),
1865 ("DOCUMENT_POSITION_CONTAINED_BY", 16.0),
1866 ("DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC", 32.0),
1867 ];
1868 if let Value::Object(c) = &node_ctor {
1869 for (name, val) in consts {
1870 c.borrow_mut()
1871 .props
1872 .insert(String::from(*name), Value::Number(*val));
1873 }
1874 }
1875
1876 g.vars.insert("Node".into(), node_ctor);
1877 g.vars.insert("Element".into(), element_ctor);
1878 g.vars.insert("HTMLElement".into(), html_element_ctor);
1879 {
1882 let (_, chardata_proto) = {
1883 let (c, p) = make_dom_cls("CharacterData", Some(&node_proto));
1884 g.vars.insert("CharacterData".into(), c);
1885 ((), p)
1886 };
1887 for name in ["Text", "Comment", "CDATASection", "ProcessingInstruction"] {
1888 let (c, _) = make_dom_cls(name, Some(&chardata_proto));
1889 g.vars.insert(name.into(), c);
1890 }
1891 let (win_ctor, win_proto) = make_dom_cls("Window", Some(&event_target_proto));
1895 g.vars.insert("Window".into(), win_ctor);
1896 if let Some(Value::Object(w)) = g.vars.get("window").cloned() {
1897 let mut wb = w.borrow_mut();
1898 if wb.proto.is_none() {
1899 wb.proto = Some(win_proto.clone());
1900 }
1901 }
1902 let (doc_ctor, doc_proto) = make_dom_cls("Document", Some(&node_proto));
1903 dom_forward::install_document(&doc_proto);
1904 g.vars.insert("Document".into(), doc_ctor);
1905 let (hdoc, hdoc_proto) = make_dom_cls("HTMLDocument", Some(&doc_proto));
1906 g.vars.insert("HTMLDocument".into(), hdoc);
1907 if let Some(Value::Object(d)) = g.vars.get("document").cloned() {
1909 let mut db = d.borrow_mut();
1910 if db.proto.is_none() {
1911 db.proto = Some(hdoc_proto.clone());
1912 }
1913 }
1914 for name in ["DocumentType", "Attr"] {
1915 let (c, _) = make_dom_cls(name, Some(&node_proto));
1916 g.vars.insert(name.into(), c);
1917 }
1918 let (df, df_proto) = make_dom_cls("DocumentFragment", Some(&node_proto));
1919 dom_forward::install_fragment(&df_proto);
1920 g.vars.insert("DocumentFragment".into(), df);
1921 let (sr, _) = make_dom_cls("ShadowRoot", Some(&df_proto));
1923 g.vars.insert("ShadowRoot".into(), sr);
1924 let (svg, _) = make_dom_cls("SVGElement", Some(&element_proto));
1925 g.vars.insert("SVGElement".into(), svg);
1926 let (media, media_proto) = make_dom_cls("HTMLMediaElement", Some(&html_element_proto));
1927 g.vars.insert("HTMLMediaElement".into(), media);
1928 for name in ["HTMLVideoElement", "HTMLAudioElement"] {
1929 let (c, _) = make_dom_cls(name, Some(&media_proto));
1930 g.vars.insert(name.into(), c);
1931 }
1932 for name in [
1933 "HTMLDivElement", "HTMLSpanElement", "HTMLAnchorElement", "HTMLImageElement",
1934 "HTMLButtonElement", "HTMLFormElement", "HTMLSelectElement", "HTMLOptionElement",
1935 "HTMLTextAreaElement", "HTMLLabelElement", "HTMLScriptElement", "HTMLStyleElement",
1936 "HTMLLinkElement", "HTMLMetaElement", "HTMLHeadElement", "HTMLBodyElement",
1937 "HTMLHtmlElement", "HTMLTemplateElement", "HTMLIFrameElement", "HTMLCanvasElement",
1938 "HTMLParagraphElement", "HTMLHeadingElement", "HTMLUListElement", "HTMLOListElement",
1939 "HTMLLIElement", "HTMLTableElement", "HTMLTableRowElement", "HTMLTableCellElement",
1940 "HTMLSlotElement", "HTMLUnknownElement", "HTMLDialogElement", "HTMLPreElement",
1941 "HTMLBRElement", "HTMLHRElement", "HTMLSourceElement", "HTMLTrackElement",
1942 ] {
1943 if !g.vars.contains_key(name) {
1944 let (c, _) = make_dom_cls(name, Some(&html_element_proto));
1945 g.vars.insert(name.into(), c);
1946 }
1947 }
1948 }
1949 g.vars.insert("Image".into(), nv("Image", image_ctor));
1952 g.vars.insert("Audio".into(), nv("Audio", audio_ctor));
1953
1954 let (nodelist_ctor, nodelist_proto) = make_dom_cls("NodeList", None);
1955 let (htmlcollection_ctor, _) = make_dom_cls("HTMLCollection", None);
1956 let (radionodelist_ctor, _) = make_dom_cls("RadioNodeList", Some(&nodelist_proto));
1957 g.vars.insert("NodeList".into(), nodelist_ctor);
1958 g.vars.insert("HTMLCollection".into(), htmlcollection_ctor);
1959 g.vars.insert("RadioNodeList".into(), radionodelist_ctor);
1960
1961 let html_classes = &[
1962 "HTMLInputElement",
1963 "HTMLFormElement",
1964 "HTMLAnchorElement",
1965 "HTMLImageElement",
1966 "HTMLButtonElement",
1967 "HTMLSelectElement",
1968 "HTMLOptionElement",
1969 "HTMLTextAreaElement",
1970 "HTMLDivElement",
1971 "HTMLSpanElement",
1972 "HTMLScriptElement",
1973 "HTMLStyleElement",
1974 "HTMLIFrameElement",
1975 "HTMLCanvasElement",
1976 "HTMLParagraphElement",
1977 "HTMLHeadingElement",
1978 "HTMLTableElement",
1979 "HTMLTableRowElement",
1980 "HTMLTableCellElement",
1981 "HTMLUListElement",
1982 "HTMLLIElement",
1983 "HTMLTemplateElement",
1984 "HTMLUnknownElement",
1985 ];
1986
1987 for cls_name in html_classes {
1988 let (ctor, _) = make_dom_cls(cls_name, Some(&html_element_proto));
1989 if *cls_name == "HTMLScriptElement" {
1990 if let Value::Object(c) = &ctor {
1991 c.borrow_mut().props.insert(
1992 String::from("supports"),
1993 nv("HTMLScriptElement.supports", |_: &mut Interp, _: Value, a: &[Value]| {
1994 let ty = a.first().map(|v| v.to_js_string()).unwrap_or_default();
1995 Ok(Value::Bool(matches!(ty.as_str(), "classic" | "module")))
1996 }),
1997 );
1998 }
1999 }
2000 g.vars.insert((*cls_name).into(), ctor);
2001 }
2002 }
2003
2004 g.vars.insert(
2006 "IntersectionObserver".into(),
2007 nv("IntersectionObserver", intersection_observer_ctor),
2008 );
2009
2010 g.vars.insert(
2012 "ResizeObserver".into(),
2013 nv("ResizeObserver", resize_observer_ctor),
2014 );
2015
2016 g.vars.insert(
2018 "MutationObserver".into(),
2019 nv("MutationObserver", mutation_observer_ctor),
2020 );
2021
2022 g.vars
2024 .insert("CustomEvent".into(), nv("CustomEvent", custom_event_ctor));
2025
2026 {
2031 let event_ctor_val = nv("Event", event_ctor);
2032 if let Value::Object(o) = &event_ctor_val {
2033 let phase_consts: &[(&str, f64)] = &[
2034 ("NONE", 0.0),
2035 ("CAPTURING_PHASE", 1.0),
2036 ("AT_TARGET", 2.0),
2037 ("BUBBLING_PHASE", 3.0),
2038 ];
2039 for (name, val) in phase_consts {
2040 o.borrow_mut()
2041 .props
2042 .insert(String::from(*name), Value::Number(*val));
2043 }
2044 }
2045 g.vars.insert("Event".into(), event_ctor_val);
2046 }
2047
2048 g.vars
2053 .insert("KeyboardEvent".into(), nv("KeyboardEvent", keyboard_event_ctor));
2054 g.vars
2055 .insert("MouseEvent".into(), nv("MouseEvent", mouse_event_ctor));
2056 g.vars
2059 .insert("WheelEvent".into(), nv("WheelEvent", wheel_event_ctor));
2060 g.vars
2061 .insert("FocusEvent".into(), nv("FocusEvent", focus_event_ctor));
2062 g.vars.insert("Touch".into(), nv("Touch", touch_ctor));
2064 g.vars
2065 .insert("TouchEvent".into(), nv("TouchEvent", touch_event_ctor));
2066 let dom_rect_fn = nv("DOMRect", dom_rect_ctor);
2069 if let Value::Object(ref o) = dom_rect_fn {
2070 o.borrow_mut().props.insert("fromRect".into(), nv("fromRect", dom_rect_from_rect));
2071 }
2072 g.vars.insert("DOMRect".into(), dom_rect_fn.clone());
2073 g.vars.insert("DOMRectReadOnly".into(), dom_rect_fn);
2074
2075 let dom_point_fn = nv("DOMPoint", dom_point_ctor);
2078 if let Value::Object(ref o) = dom_point_fn {
2079 o.borrow_mut().props.insert("fromPoint".into(), nv("fromPoint", dom_point_from_point));
2080 }
2081 g.vars.insert("DOMPoint".into(), dom_point_fn.clone());
2082 g.vars.insert("DOMPointReadOnly".into(), dom_point_fn);
2083 let dom_matrix_fn = nv("DOMMatrix", dom_matrix_ctor);
2086 if let Value::Object(ref o) = dom_matrix_fn {
2087 o.borrow_mut().props.insert("fromMatrix".into(), nv("fromMatrix", |it, _, a| dom_matrix_ctor(it, Value::Undefined, a)));
2088 o.borrow_mut().props.insert("fromFloat32Array".into(), nv("fromFloat32Array", |it, _, a| dom_matrix_ctor(it, Value::Undefined, a)));
2089 o.borrow_mut().props.insert("fromFloat64Array".into(), nv("fromFloat64Array", |it, _, a| dom_matrix_ctor(it, Value::Undefined, a)));
2090 }
2091 g.vars.insert("DOMMatrix".into(), dom_matrix_fn.clone());
2092 g.vars.insert("DOMMatrixReadOnly".into(), dom_matrix_fn);
2093
2094 let dom_quad_fn = nv("DOMQuad", dom_quad_ctor);
2095 if let Value::Object(ref o) = dom_quad_fn {
2096 o.borrow_mut().props.insert("fromRect".into(), nv("fromRect", |it, _, a| {
2097 let r = arg(a, 0);
2098 let rx = it.get_property(&r, "x").unwrap_or(Value::Number(0.0)).to_number();
2099 let ry = it.get_property(&r, "y").unwrap_or(Value::Number(0.0)).to_number();
2100 let rw = it.get_property(&r, "width").unwrap_or(Value::Number(0.0)).to_number();
2101 let rh = it.get_property(&r, "height").unwrap_or(Value::Number(0.0)).to_number();
2102 let p1 = dom_point_ctor(it, Value::Undefined, &[Value::Number(rx), Value::Number(ry)])?;
2103 let p2 = dom_point_ctor(it, Value::Undefined, &[Value::Number(rx + rw), Value::Number(ry)])?;
2104 let p3 = dom_point_ctor(it, Value::Undefined, &[Value::Number(rx + rw), Value::Number(ry + rh)])?;
2105 let p4 = dom_point_ctor(it, Value::Undefined, &[Value::Number(rx), Value::Number(ry + rh)])?;
2106 dom_quad_ctor(it, Value::Undefined, &[p1, p2, p3, p4])
2107 }));
2108 }
2109 g.vars.insert("DOMQuad".into(), dom_quad_fn);
2110 g.vars.insert("Path2D".into(), nv("Path2D", dom_path2d_ctor));
2111 g.vars.insert("ImageData".into(), nv("ImageData", dom_image_data_ctor));
2112
2113 let range_ctor_fn = nv("Range", |it, t, a| dom_document::document_create_range(it, t, a));
2114 if let Value::Object(ref ro) = range_ctor_fn {
2115 let mut rb = ro.borrow_mut();
2116 rb.props.insert(
2117 "START_TO_START".into(),
2118 Value::Number(crate::os_lib::dom_range::START_TO_START as f64),
2119 );
2120 rb.props.insert(
2121 "START_TO_END".into(),
2122 Value::Number(crate::os_lib::dom_range::START_TO_END as f64),
2123 );
2124 rb.props.insert(
2125 "END_TO_END".into(),
2126 Value::Number(crate::os_lib::dom_range::END_TO_END as f64),
2127 );
2128 rb.props.insert(
2129 "END_TO_START".into(),
2130 Value::Number(crate::os_lib::dom_range::END_TO_START as f64),
2131 );
2132 }
2133 g.vars.insert("Range".into(), range_ctor_fn);
2134
2135 g.vars.insert(
2138 "HashChangeEvent".into(),
2139 nv("HashChangeEvent", hash_change_event_ctor),
2140 );
2141 g.vars.insert(
2142 "PageTransitionEvent".into(),
2143 nv("PageTransitionEvent", page_transition_event_ctor),
2144 );
2145 g.vars.insert(
2148 "PopStateEvent".into(),
2149 nv("PopStateEvent", pop_state_event_ctor),
2150 );
2151 g.vars
2154 .insert("PointerEvent".into(), nv("PointerEvent", pointer_event_ctor));
2155 g.vars
2156 .insert("InputEvent".into(), nv("InputEvent", input_event_ctor));
2157 g.vars
2160 .insert("ProgressEvent".into(), nv("ProgressEvent", progress_event_ctor));
2161 g.vars
2162 .insert("StorageEvent".into(), nv("StorageEvent", storage_event_ctor));
2163 g.vars
2165 .insert("CommandEvent".into(), nv("CommandEvent", command_event_ctor));
2166 g.vars
2167 .insert("ToggleEvent".into(), nv("ToggleEvent", toggle_event_ctor));
2168 g.vars
2169 .insert("FormDataEvent".into(), nv("FormDataEvent", form_data_event_ctor));
2170
2171 g.vars.insert(
2174 "CompositionEvent".into(),
2175 nv("CompositionEvent", composition_event_ctor),
2176 );
2177 g.vars
2178 .insert("ClipboardEvent".into(), nv("ClipboardEvent", clipboard_event_ctor));
2179 g.vars
2182 .insert("AnimationEvent".into(), nv("AnimationEvent", animation_event_ctor));
2183 g.vars
2184 .insert("TransitionEvent".into(), nv("TransitionEvent", transition_event_ctor));
2185 g.vars.insert("DragEvent".into(), nv("DragEvent", drag_event_ctor));
2186 g.vars
2187 .insert("SubmitEvent".into(), nv("SubmitEvent", submit_event_ctor));
2188 g.vars
2191 .insert("MessageEvent".into(), nv("MessageEvent", message_event_ctor));
2192 g.vars.insert("ErrorEvent".into(), nv("ErrorEvent", error_event_ctor));
2193
2194 g.vars.insert("scrollY".into(), Value::Number(0.0));
2196 g.vars.insert("pageYOffset".into(), Value::Number(0.0));
2197 g.vars.insert("scrollX".into(), Value::Number(0.0));
2198 g.vars.insert("pageXOffset".into(), Value::Number(0.0));
2199 g.vars
2200 .insert("scrollTo".into(), nv("scrollTo", window_scroll_to));
2201 g.vars
2202 .insert("scroll".into(), nv("scroll", window_scroll_to));
2203 g.vars
2206 .insert("scrollBy".into(), nv("scrollBy", window_scroll_by));
2207 g.vars
2208 .insert("matchMedia".into(), nv("matchMedia", window_match_media));
2209
2210 g.vars.insert("location".into(), Value::Object(location));
2213 g.vars.insert("history".into(), Value::Object(history));
2214 g.vars.insert("alert".into(), nv("alert", console_log));
2215 g.vars
2218 .insert("confirm".into(), nv("confirm", window_confirm));
2219 g.vars.insert("prompt".into(), nv("prompt", window_prompt));
2220 g.vars.insert("open".into(), nv("open", window_open));
2223 g.vars.insert("close".into(), nv("close", window_close));
2224 g.vars.insert("stop".into(), nv("stop", window_stop));
2226 g.vars.insert("focus".into(), nv("focus", window_focus));
2227 g.vars.insert("blur".into(), nv("blur", window_focus));
2228 g.vars
2231 .insert("getSelection".into(), nv("getSelection", document_get_selection));
2232
2233 let map_ctor_v = nv("Map", map_ctor);
2235 if let Value::Object(mc) = &map_ctor_v {
2236 mc.borrow_mut()
2237 .props
2238 .insert("groupBy".into(), nv("Map.groupBy", map_group_by));
2239 }
2240 g.vars.insert("Map".into(), map_ctor_v);
2241 g.vars.insert("Set".into(), nv("Set", set_ctor));
2242
2243 let promise_ctor_v = nv("Promise", promise_ctor);
2245 if let Value::Object(pc) = &promise_ctor_v {
2246 pc.borrow_mut().props.insert(
2247 "resolve".into(),
2248 nv("Promise.resolve", promise_resolve_static),
2249 );
2250 pc.borrow_mut()
2251 .props
2252 .insert("reject".into(), nv("Promise.reject", promise_reject_static));
2253 pc.borrow_mut()
2254 .props
2255 .insert("all".into(), nv("Promise.all", promise_all_static));
2256 pc.borrow_mut().props.insert(
2257 "allSettled".into(),
2258 nv("Promise.allSettled", promise_all_settled_static),
2259 );
2260 pc.borrow_mut()
2261 .props
2262 .insert("race".into(), nv("Promise.race", promise_race_static));
2263 pc.borrow_mut()
2264 .props
2265 .insert("any".into(), nv("Promise.any", promise_any_static));
2266 pc.borrow_mut().props.insert(
2267 "withResolvers".into(),
2268 nv("Promise.withResolvers", promise_with_resolvers_static),
2269 );
2270 pc.borrow_mut()
2271 .props
2272 .insert("try".into(), nv("Promise.try", promise_try_static));
2273 }
2274 g.vars.insert("Promise".into(), promise_ctor_v);
2275
2276 g.vars.insert("Proxy".into(), nv("Proxy", proxy_ctor));
2278
2279 let reflect = Obj::plain();
2281 {
2282 let mut r = reflect.borrow_mut();
2283 r.props.insert("get".into(), nv("Reflect.get", reflect_get));
2284 r.props.insert("set".into(), nv("Reflect.set", reflect_set));
2285 r.props.insert("has".into(), nv("Reflect.has", reflect_has));
2286 r.props.insert(
2287 "deleteProperty".into(),
2288 nv("Reflect.deleteProperty", reflect_delete_property),
2289 );
2290 r.props
2291 .insert("ownKeys".into(), nv("Reflect.ownKeys", reflect_own_keys));
2292 r.props.insert(
2293 "getPrototypeOf".into(),
2294 nv("Reflect.getPrototypeOf", reflect_get_prototype_of),
2295 );
2296 r.props.insert(
2297 "defineProperty".into(),
2298 nv("Reflect.defineProperty", reflect_define_property),
2299 );
2300 r.props
2301 .insert("apply".into(), nv("Reflect.apply", reflect_apply));
2302 r.props.insert(
2303 "construct".into(),
2304 nv("Reflect.construct", reflect_construct),
2305 );
2306 r.props.insert(
2310 "setPrototypeOf".into(),
2311 nv("Reflect.setPrototypeOf", object_set_prototype_of),
2312 );
2313 r.props.insert(
2314 "isExtensible".into(),
2315 nv("Reflect.isExtensible", object_is_extensible),
2316 );
2317 r.props.insert(
2318 "preventExtensions".into(),
2319 nv("Reflect.preventExtensions", object_prevent_extensions),
2320 );
2321 r.props.insert(
2322 "getOwnPropertyDescriptor".into(),
2323 nv(
2324 "Reflect.getOwnPropertyDescriptor",
2325 object_get_own_property_descriptor,
2326 ),
2327 );
2328 }
2329 g.vars.insert("Reflect".into(), Value::Object(reflect));
2330
2331 let iterator_ctor = nv("Iterator", |_: &mut Interp, _: Value, _: &[Value]| {
2334 Ok(Value::Undefined)
2335 });
2336 if let Value::Object(ic) = &iterator_ctor {
2337 ic.borrow_mut()
2338 .props
2339 .insert("from".into(), nv("Iterator.from", iterator_from));
2340 ic.borrow_mut()
2341 .props
2342 .insert("range".into(), nv("Iterator.range", iterator_range));
2343 ic.borrow_mut()
2344 .props
2345 .insert("concat".into(), nv("Iterator.concat", iterator_concat_static));
2346 }
2347 g.vars.insert("Iterator".into(), iterator_ctor);
2348
2349 g.vars
2351 .insert("setTimeout".into(), nv("setTimeout", set_timeout));
2352 g.vars
2353 .insert("setInterval".into(), nv("setInterval", set_interval));
2354 g.vars
2355 .insert("clearTimeout".into(), nv("clearTimeout", clear_timeout));
2356 g.vars
2357 .insert("clearInterval".into(), nv("clearInterval", clear_interval));
2358 g.vars.insert(
2359 "queueMicrotask".into(),
2360 nv("queueMicrotask", queue_microtask),
2361 );
2362 g.vars
2366 .insert("reportError".into(), nv("reportError", report_error));
2367 g.vars.insert(
2368 "requestAnimationFrame".into(),
2369 nv("requestAnimationFrame", request_animation_frame),
2370 );
2371 g.vars.insert(
2372 "cancelAnimationFrame".into(),
2373 nv("cancelAnimationFrame", clear_timeout),
2374 );
2375 g.vars.insert(
2376 "requestIdleCallback".into(),
2377 nv("requestIdleCallback", request_idle_callback),
2378 );
2379 g.vars.insert(
2380 "cancelIdleCallback".into(),
2381 nv("cancelIdleCallback", dom_noop),
2382 );
2383
2384 let date_ctor_obj = Obj::native("Date", date_ctor);
2390 date_ctor_obj
2391 .borrow_mut()
2392 .props
2393 .insert("now".into(), nv("Date.now", date_now_static));
2394 date_ctor_obj
2395 .borrow_mut()
2396 .props
2397 .insert("parse".into(), nv("Date.parse", date_parse_static));
2398 date_ctor_obj
2403 .borrow_mut()
2404 .props
2405 .insert("UTC".into(), nv("Date.UTC", date_utc_static));
2406 g.vars.insert("Date".into(), Value::Object(date_ctor_obj));
2407
2408 let error_proto = Obj::plain();
2412 error_proto
2413 .borrow_mut()
2414 .props
2415 .insert("name".into(), Value::str("Error"));
2416 error_proto
2417 .borrow_mut()
2418 .props
2419 .insert("message".into(), Value::str(""));
2420 let error_ctor_obj = Obj::native("Error", error_ctor);
2421 error_ctor_obj
2422 .borrow_mut()
2423 .props
2424 .insert("prototype".into(), Value::Object(error_proto.clone()));
2425 error_proto
2426 .borrow_mut()
2427 .props
2428 .insert("constructor".into(), Value::Object(error_ctor_obj.clone()));
2429 error_ctor_obj
2430 .borrow_mut()
2431 .props
2432 .insert("isError".into(), nv("Error.isError", error_is_error));
2433 g.vars.insert("Error".into(), Value::Object(error_ctor_obj));
2434
2435 fn make_error_subtype(
2436 name: &str,
2437 error_proto: &ObjRef,
2438 ctor_fn: NativeFn,
2439 ) -> Value {
2440 let proto = Obj::plain();
2441 proto.borrow_mut().proto = Some(error_proto.clone());
2442 proto
2443 .borrow_mut()
2444 .props
2445 .insert("name".into(), Value::str(name));
2446 let ctor_obj = Obj::native(name, ctor_fn);
2447 ctor_obj
2448 .borrow_mut()
2449 .props
2450 .insert("prototype".into(), Value::Object(proto.clone()));
2451 proto
2452 .borrow_mut()
2453 .props
2454 .insert("constructor".into(), Value::Object(ctor_obj.clone()));
2455 Value::Object(ctor_obj)
2456 }
2457 g.vars.insert(
2458 "TypeError".into(),
2459 make_error_subtype("TypeError", &error_proto, type_error_ctor),
2460 );
2461 g.vars.insert(
2462 "RangeError".into(),
2463 make_error_subtype("RangeError", &error_proto, range_error_ctor),
2464 );
2465 g.vars.insert(
2466 "SyntaxError".into(),
2467 make_error_subtype("SyntaxError", &error_proto, syntax_error_ctor),
2468 );
2469 g.vars.insert(
2470 "SuppressedError".into(),
2471 make_error_subtype("SuppressedError", &error_proto, suppressed_error_ctor),
2472 );
2473 g.vars.insert(
2474 "AggregateError".into(),
2475 make_error_subtype("AggregateError", &error_proto, aggregate_error_ctor),
2476 );
2477
2478 {
2486 let dom_exception_ctor_val = nv("DOMException", dom_exception_ctor);
2487 if let Value::Object(o) = &dom_exception_ctor_val {
2488 let mut b = o.borrow_mut();
2489 let legacy_codes: &[(&str, f64)] = &[
2490 ("INDEX_SIZE_ERR", 1.0),
2491 ("HIERARCHY_REQUEST_ERR", 3.0),
2492 ("WRONG_DOCUMENT_ERR", 4.0),
2493 ("INVALID_CHARACTER_ERR", 5.0),
2494 ("NO_MODIFICATION_ALLOWED_ERR", 7.0),
2495 ("NOT_FOUND_ERR", 8.0),
2496 ("NOT_SUPPORTED_ERR", 9.0),
2497 ("INUSE_ATTRIBUTE_ERR", 10.0),
2498 ("INVALID_STATE_ERR", 11.0),
2499 ("SYNTAX_ERR", 12.0),
2500 ("INVALID_MODIFICATION_ERR", 13.0),
2501 ("NAMESPACE_ERR", 14.0),
2502 ("INVALID_ACCESS_ERR", 15.0),
2503 ("SECURITY_ERR", 18.0),
2504 ("NETWORK_ERR", 19.0),
2505 ("ABORT_ERR", 20.0),
2506 ("TIMEOUT_ERR", 23.0),
2507 ("DATA_CLONE_ERR", 25.0),
2508 ];
2509 for (name, code) in legacy_codes {
2510 b.props.insert(String::from(*name), Value::Number(*code));
2511 }
2512 }
2513 g.vars.insert("DOMException".into(), dom_exception_ctor_val);
2514 }
2515
2516 {
2518 let node_filter = Obj::plain();
2519 {
2520 let mut b = node_filter.borrow_mut();
2521 b.props.insert("FILTER_ACCEPT".into(), Value::Number(1.0));
2522 b.props.insert("FILTER_REJECT".into(), Value::Number(2.0));
2523 b.props.insert("FILTER_SKIP".into(), Value::Number(3.0));
2524 b.props.insert("SHOW_ALL".into(), Value::Number(0xFFFF_FFFFu32 as f64));
2525 b.props.insert("SHOW_ELEMENT".into(), Value::Number(0x1 as f64));
2526 b.props.insert("SHOW_ATTRIBUTE".into(), Value::Number(0x2 as f64));
2527 b.props.insert("SHOW_TEXT".into(), Value::Number(0x4 as f64));
2528 b.props.insert("SHOW_CDATA_SECTION".into(), Value::Number(0x8 as f64));
2529 b.props.insert("SHOW_ENTITY_REFERENCE".into(), Value::Number(0x10 as f64));
2530 b.props.insert("SHOW_ENTITY".into(), Value::Number(0x20 as f64));
2531 b.props.insert("SHOW_PROCESSING_INSTRUCTION".into(), Value::Number(0x40 as f64));
2532 b.props.insert("SHOW_COMMENT".into(), Value::Number(0x80 as f64));
2533 b.props.insert("SHOW_DOCUMENT".into(), Value::Number(0x100 as f64));
2534 b.props.insert("SHOW_DOCUMENT_TYPE".into(), Value::Number(0x200 as f64));
2535 b.props.insert("SHOW_DOCUMENT_FRAGMENT".into(), Value::Number(0x400 as f64));
2536 b.props.insert("SHOW_NOTATION".into(), Value::Number(0x800 as f64));
2537 }
2538 g.vars.insert("NodeFilter".into(), Value::Object(node_filter));
2539 }
2540
2541 g.vars.insert(
2543 "FinalizationRegistry".into(),
2544 nv("FinalizationRegistry", finalization_registry_ctor),
2545 );
2546
2547 g.vars.insert("fetch".into(), nv("fetch", fetch));
2549 g.vars.insert("Request".into(), nv("Request", request_ctor));
2550 g.vars.insert("Headers".into(), nv("Headers", headers_ctor));
2551 {
2556 let response_ctor_val = nv("Response", response_ctor);
2557 if let Value::Object(o) = &response_ctor_val {
2558 let mut b = o.borrow_mut();
2559 b.props.insert("json".into(), nv("Response.json", response_json_static));
2560 b.props.insert("error".into(), nv("Response.error", response_error_static));
2561 b.props
2562 .insert("redirect".into(), nv("Response.redirect", response_redirect_static));
2563 }
2564 g.vars.insert("Response".into(), response_ctor_val);
2565 }
2566 g.vars
2568 .insert("XMLHttpRequest".into(), nv("XMLHttpRequest", xhr_ctor));
2569
2570 let regexp_ctor_v = nv("RegExp", regexp_ctor);
2572 if let Value::Object(rc) = ®exp_ctor_v {
2573 rc.borrow_mut()
2574 .props
2575 .insert("escape".into(), nv("RegExp.escape", regexp_escape_static));
2576 let proto = Obj::plain();
2580 {
2581 let mut pb = proto.borrow_mut();
2582 let methods: [(&str, NativeFn); 9] = [
2583 ("test", re_test),
2584 ("exec", re_exec),
2585 ("toString", re_to_string),
2586 ("compile", re_compile),
2587 ("Symbol(Symbol.match)", re_symbol_match),
2588 ("Symbol(Symbol.replace)", re_symbol_replace),
2589 ("Symbol(Symbol.search)", re_symbol_search),
2590 ("Symbol(Symbol.split)", re_symbol_split),
2591 ("Symbol(Symbol.matchAll)", re_symbol_match_all),
2592 ];
2593 for (name, f) in methods {
2594 pb.props.insert(name.into(), nv(name, f));
2595 }
2596 pb.props.insert("constructor".into(), regexp_ctor_v.clone());
2597 }
2598 rc.borrow_mut().props.insert("prototype".into(), Value::Object(proto));
2599 }
2600 g.vars.insert("RegExp".into(), regexp_ctor_v);
2601
2602 g.vars.insert("WeakMap".into(), nv("WeakMap", weakmap_ctor));
2604 g.vars.insert("WeakSet".into(), nv("WeakSet", weakset_ctor));
2605 g.vars.insert("WeakRef".into(), nv("WeakRef", weakref_ctor));
2606
2607 {
2609 let sym_fn = nv("Symbol", symbol_fn);
2610 if let Value::Object(sf) = &sym_fn {
2611 sf.borrow_mut().props.insert("for".into(), nv("Symbol.for", symbol_for));
2612 sf.borrow_mut().props.insert("keyFor".into(), nv("Symbol.keyFor", symbol_key_for));
2613 sf.borrow_mut().props.insert("iterator".into(), Value::str("Symbol(Symbol.iterator)"));
2614 sf.borrow_mut().props.insert("toPrimitive".into(), Value::str("Symbol(Symbol.toPrimitive)"));
2615 sf.borrow_mut().props.insert("hasInstance".into(), Value::str("Symbol(Symbol.hasInstance)"));
2616 sf.borrow_mut().props.insert("toStringTag".into(), Value::str("Symbol(Symbol.toStringTag)"));
2617 sf.borrow_mut().props.insert("asyncIterator".into(), Value::str("Symbol(Symbol.asyncIterator)"));
2618 sf.borrow_mut()
2623 .props
2624 .insert("isConcatSpreadable".into(), Value::str("Symbol(Symbol.isConcatSpreadable)"));
2625 for name in [
2633 "species",
2634 "unscopables",
2635 "match",
2636 "matchAll",
2637 "replace",
2638 "search",
2639 "split",
2640 ] {
2641 sf.borrow_mut()
2642 .props
2643 .insert(String::from(name), Value::str(format!("Symbol(Symbol.{})", name)));
2644 }
2645 sf.borrow_mut().props.insert("dispose".into(), Value::str("Symbol(Symbol.dispose)"));
2647 sf.borrow_mut().props.insert("asyncDispose".into(), Value::str("Symbol(Symbol.asyncDispose)"));
2648 }
2649 g.vars.insert("Symbol".into(), sym_fn);
2650
2651 use super::value::Accessor;
2660 let species_fn = nv("get [Symbol.species]", symbol_species_getter);
2661 for ctor_name in [
2662 "Array", "RegExp", "Promise", "Map", "Set", "ArrayBuffer",
2663 "Uint8Array", "Int8Array", "Uint8ClampedArray", "Int16Array",
2664 "Uint16Array", "Int32Array", "Uint32Array", "Float16Array", "Float32Array",
2665 "Float64Array", "BigInt64Array", "BigUint64Array",
2666 ] {
2667 if let Some(Value::Object(ctor_obj)) = g.vars.get(ctor_name).cloned() {
2668 ctor_obj.borrow_mut().accessors.insert(
2669 "Symbol(Symbol.species)".into(),
2670 Accessor { get: Some(species_fn.clone()), set: None },
2671 );
2672 }
2673 }
2674 }
2675
2676 g.vars.insert("NaN".into(), Value::Number(f64::NAN));
2678 g.vars
2679 .insert("Infinity".into(), Value::Number(f64::INFINITY));
2680 g.vars.insert("undefined".into(), Value::Undefined);
2681 let global_this = g.vars.get("window").cloned().unwrap_or(Value::Undefined);
2683 g.vars.insert("globalThis".into(), global_this);
2684 if let Some(Value::Object(w)) = g.vars.get("window").cloned() {
2706 for name in WINDOW_MIRRORED_GLOBALS {
2707 if w.borrow().props.contains_key(*name) {
2708 continue;
2709 }
2710 if let Some(v) = g.vars.get(*name).cloned() {
2711 w.borrow_mut()
2712 .props
2713 .insert(alloc::string::String::from(*name), v);
2714 }
2715 }
2716 }
2717 {
2722 let ctors: alloc::vec::Vec<(alloc::string::String, Rc<RefCell<Obj>>)> = g
2723 .vars
2724 .iter()
2725 .filter(|(k, _)| k.chars().next().is_some_and(|c| c.is_ascii_uppercase()))
2726 .filter_map(|(k, v)| match v {
2727 Value::Object(o) if o.borrow().is_callable() && !o.borrow().props.contains_key("prototype") => {
2728 Some((k.clone(), o.clone()))
2729 }
2730 _ => None,
2731 })
2732 .collect();
2733 for (_name, ctor) in ctors {
2734 let proto = Obj::plain();
2735 proto.borrow_mut().props.insert("constructor".into(), Value::Object(ctor.clone()));
2736 ctor.borrow_mut().props.insert("prototype".into(), Value::Object(proto));
2737 }
2738 }
2739 let window_ref = g.vars.get("window").cloned().unwrap_or(Value::Undefined);
2740 g.vars.insert("self".into(), window_ref.clone());
2741 g.vars.insert("top".into(), window_ref.clone());
2742 g.vars.insert("parent".into(), window_ref.clone());
2743 g.vars.insert("frames".into(), window_ref);
2744}
2745
2746
2747mod dom;
2752mod console_math_json;
2753mod object_array;
2754mod props_methods;
2755mod collections;
2756mod promise;
2757mod web_forms;
2758mod encoding;
2759mod extra_methods;
2760mod typed_array;
2761mod text_clone;
2762mod extra_static;
2763mod dom_document;
2764mod observers;
2765mod events;
2766mod window_api;
2767mod static_classlist;
2768mod timers_gen;
2769mod weak_symbol;
2770mod regexp;
2771mod dom_forward;
2772pub(crate) use dom_forward::{named_node_map_get, named_node_map_item};
2773mod date;
2774mod errors_misc;
2775mod intl;
2776mod crypto_subtle;
2777mod streams;
2778mod mse;
2779mod worker;
2780
2781pub(crate) use dom::*;
2782pub(crate) use console_math_json::*;
2783pub(crate) use object_array::*;
2784pub(crate) use props_methods::*;
2785pub(crate) use collections::*;
2786pub(crate) use promise::*;
2787pub(crate) use web_forms::*;
2788pub(crate) use encoding::*;
2789pub(crate) use extra_methods::*;
2790pub(crate) use typed_array::*;
2791pub(crate) use text_clone::*;
2792pub(crate) use extra_static::*;
2793pub(crate) use dom_document::*;
2794pub(crate) use observers::*;
2795pub(crate) use events::*;
2796pub(crate) use window_api::*;
2797pub(crate) use static_classlist::*;
2798pub(crate) use timers_gen::*;
2799pub(crate) use weak_symbol::*;
2800pub(crate) use regexp::*;
2801pub(crate) use date::*;
2802pub(crate) use errors_misc::*;
2803pub(crate) use intl::*;
2804pub(crate) use crypto_subtle::*;
2805pub(crate) use streams::*;
2806pub(crate) use mse::*;
2807pub(crate) use worker::*;
2808
2809