Skip to main content

pipa/runtime/
context.rs

1use super::atom::{Atom, AtomTable};
2use super::event_loop::EventLoop;
3use super::extension::MacroTaskExtension;
4use super::runtime::JSRuntime;
5use crate::builtins;
6use crate::builtins::promise::{Microtask, MicrotaskQueue};
7use crate::compiler::codegen::OptLevel;
8use crate::host::HostFunction;
9use crate::object::JSObject;
10use crate::object::ShapeCache;
11use crate::util::FxHashMap;
12use crate::value::JSValue;
13
14#[allow(non_snake_case)]
15pub struct CommonAtoms {
16    pub length: Atom,
17    pub prototype: Atom,
18    pub constructor: Atom,
19    pub call: Atom,
20    pub apply: Atom,
21    pub bind: Atom,
22    pub to_string: Atom,
23    pub value_of: Atom,
24    pub push: Atom,
25    pub pop: Atom,
26    pub shift: Atom,
27    pub unshift: Atom,
28    pub slice: Atom,
29    pub splice: Atom,
30    pub join: Atom,
31    pub map: Atom,
32    pub for_each: Atom,
33    pub filter: Atom,
34    pub reduce: Atom,
35    pub index_of: Atom,
36    pub last_index_of: Atom,
37    pub includes: Atom,
38    pub concat: Atom,
39    pub reverse: Atom,
40    pub sort: Atom,
41    pub flat: Atom,
42    pub flat_map: Atom,
43    pub find: Atom,
44    pub find_index: Atom,
45    pub every: Atom,
46    pub some: Atom,
47    pub fill: Atom,
48    pub keys: Atom,
49    pub values: Atom,
50    pub entries: Atom,
51    pub has_own_property: Atom,
52    pub is_prototype_of: Atom,
53    pub property_is_enumerable: Atom,
54    pub to_locale_string: Atom,
55    pub split: Atom,
56    pub replace: Atom,
57    pub match_atom: Atom,
58    pub search: Atom,
59    pub test: Atom,
60    pub exec: Atom,
61    pub then: Atom,
62    pub catch: Atom,
63    pub finally: Atom,
64    pub message: Atom,
65    pub name: Atom,
66    pub stack: Atom,
67    pub __proto__: Atom,
68    pub __super__: Atom,
69    pub __boundFn: Atom,
70    pub __boundArgs: Atom,
71    pub __boundThis: Atom,
72    pub __value__: Atom,
73    pub __dateValue__: Atom,
74    pub __pattern__: Atom,
75    pub __flags__: Atom,
76    pub source: Atom,
77    pub global: Atom,
78    pub ignore_case: Atom,
79    pub multiline: Atom,
80    pub sticky: Atom,
81    pub unicode: Atom,
82    pub undefined: Atom,
83    pub null: Atom,
84    pub object: Atom,
85    pub function: Atom,
86    pub number: Atom,
87    pub string: Atom,
88    pub boolean: Atom,
89    pub symbol: Atom,
90    pub bigint: Atom,
91    pub math: Atom,
92    pub json: Atom,
93    pub array: Atom,
94    pub regexp: Atom,
95    pub error: Atom,
96    pub date: Atom,
97    pub promise: Atom,
98    pub map_ctor: Atom,
99    pub set_ctor: Atom,
100    pub weak_map_ctor: Atom,
101    pub weak_set_ctor: Atom,
102    pub proxy: Atom,
103    pub reflect: Atom,
104    pub console: Atom,
105    pub index: Atom,
106    pub input: Atom,
107    pub empty: Atom,
108    pub n0: Atom,
109    pub n1: Atom,
110
111    pub typeof_undefined: Atom,
112    pub typeof_object: Atom,
113    pub typeof_boolean: Atom,
114    pub typeof_number: Atom,
115    pub typeof_bigint: Atom,
116    pub typeof_symbol: Atom,
117    pub typeof_string: Atom,
118    pub typeof_function: Atom,
119
120    pub dot_all: Atom,
121    pub last_index: Atom,
122    pub callee: Atom,
123    pub default_: Atom,
124    pub url: Atom,
125    pub __promise_state__: Atom,
126    pub __promise_result__: Atom,
127    pub __done__: Atom,
128    pub __iter_arr__: Atom,
129    pub __iter_idx__: Atom,
130    pub to_string_tag: Atom,
131}
132
133impl CommonAtoms {
134    pub fn new(tbl: &mut AtomTable) -> Self {
135        CommonAtoms {
136            length: tbl.intern("length"),
137            prototype: tbl.intern("prototype"),
138            constructor: tbl.intern("constructor"),
139            call: tbl.intern("call"),
140            apply: tbl.intern("apply"),
141            bind: tbl.intern("bind"),
142            to_string: tbl.intern("toString"),
143            value_of: tbl.intern("valueOf"),
144            push: tbl.intern("push"),
145            pop: tbl.intern("pop"),
146            shift: tbl.intern("shift"),
147            unshift: tbl.intern("unshift"),
148            slice: tbl.intern("slice"),
149            splice: tbl.intern("splice"),
150            join: tbl.intern("join"),
151            map: tbl.intern("map"),
152            for_each: tbl.intern("forEach"),
153            filter: tbl.intern("filter"),
154            reduce: tbl.intern("reduce"),
155            index_of: tbl.intern("indexOf"),
156            last_index_of: tbl.intern("lastIndexOf"),
157            includes: tbl.intern("includes"),
158            concat: tbl.intern("concat"),
159            reverse: tbl.intern("reverse"),
160            sort: tbl.intern("sort"),
161            flat: tbl.intern("flat"),
162            flat_map: tbl.intern("flatMap"),
163            find: tbl.intern("find"),
164            find_index: tbl.intern("findIndex"),
165            every: tbl.intern("every"),
166            some: tbl.intern("some"),
167            fill: tbl.intern("fill"),
168            keys: tbl.intern("keys"),
169            values: tbl.intern("values"),
170            entries: tbl.intern("entries"),
171            has_own_property: tbl.intern("hasOwnProperty"),
172            is_prototype_of: tbl.intern("isPrototypeOf"),
173            property_is_enumerable: tbl.intern("propertyIsEnumerable"),
174            to_locale_string: tbl.intern("toLocaleString"),
175            split: tbl.intern("split"),
176            replace: tbl.intern("replace"),
177            match_atom: tbl.intern("match"),
178            search: tbl.intern("search"),
179            test: tbl.intern("test"),
180            exec: tbl.intern("exec"),
181            then: tbl.intern("then"),
182            catch: tbl.intern("catch"),
183            finally: tbl.intern("finally"),
184            message: tbl.intern("message"),
185            name: tbl.intern("name"),
186            stack: tbl.intern("stack"),
187            __proto__: tbl.intern("__proto__"),
188            __super__: tbl.intern("__super__"),
189            __boundFn: tbl.intern("__boundFn"),
190            __boundArgs: tbl.intern("__boundArgs"),
191            __boundThis: tbl.intern("__boundThis"),
192            __value__: tbl.intern("__value__"),
193            __dateValue__: tbl.intern("__dateValue__"),
194            __pattern__: tbl.intern("__pattern__"),
195            __flags__: tbl.intern("__flags__"),
196            source: tbl.intern("source"),
197            global: tbl.intern("global"),
198            ignore_case: tbl.intern("ignoreCase"),
199            multiline: tbl.intern("multiline"),
200            sticky: tbl.intern("sticky"),
201            unicode: tbl.intern("unicode"),
202            undefined: tbl.intern("undefined"),
203            null: tbl.intern("null"),
204            object: tbl.intern("Object"),
205            function: tbl.intern("Function"),
206            number: tbl.intern("Number"),
207            string: tbl.intern("String"),
208            boolean: tbl.intern("Boolean"),
209            symbol: tbl.intern("Symbol"),
210            bigint: tbl.intern("BigInt"),
211            math: tbl.intern("Math"),
212            json: tbl.intern("JSON"),
213            array: tbl.intern("Array"),
214            regexp: tbl.intern("RegExp"),
215            error: tbl.intern("Error"),
216            date: tbl.intern("Date"),
217            promise: tbl.intern("Promise"),
218            map_ctor: tbl.intern("Map"),
219            set_ctor: tbl.intern("Set"),
220            weak_map_ctor: tbl.intern("WeakMap"),
221            weak_set_ctor: tbl.intern("WeakSet"),
222            proxy: tbl.intern("Proxy"),
223            reflect: tbl.intern("Reflect"),
224            console: tbl.intern("console"),
225            index: tbl.intern("index"),
226            input: tbl.intern("input"),
227            empty: tbl.intern(""),
228            n0: tbl.intern("0"),
229            n1: tbl.intern("1"),
230            typeof_undefined: tbl.intern("undefined"),
231            typeof_object: tbl.intern("object"),
232            typeof_boolean: tbl.intern("boolean"),
233            typeof_number: tbl.intern("number"),
234            typeof_bigint: tbl.intern("bigint"),
235            typeof_symbol: tbl.intern("symbol"),
236            typeof_string: tbl.intern("string"),
237            typeof_function: tbl.intern("function"),
238            dot_all: tbl.intern("dotAll"),
239            last_index: tbl.intern("lastIndex"),
240            callee: tbl.intern("callee"),
241            default_: tbl.intern("default"),
242            url: tbl.intern("url"),
243            __promise_state__: tbl.intern("__promise_state__"),
244            __promise_result__: tbl.intern("__promise_result__"),
245            __done__: tbl.intern("__done__"),
246            __iter_arr__: tbl.intern("__iter_arr__"),
247            __iter_idx__: tbl.intern("__iter_idx__"),
248            to_string_tag: tbl.intern("Symbol.toStringTag"),
249        }
250    }
251}
252
253pub struct JSContext {
254    runtime: *mut JSRuntime,
255    global_object: JSValue,
256    interrupt_counter: i32,
257    builtin_functions: FxHashMap<String, HostFunction>,
258
259    string_prototype: Option<usize>,
260    number_prototype: Option<usize>,
261    array_prototype: Option<usize>,
262    array_iterator_prototype: Option<usize>,
263    map_iterator_prototype: Option<usize>,
264    set_iterator_prototype: Option<usize>,
265    regexp_prototype: Option<usize>,
266    date_prototype: Option<usize>,
267    object_prototype: Option<usize>,
268    function_prototype: Option<usize>,
269    map_prototype: Option<usize>,
270    set_prototype: Option<usize>,
271    weakmap_prototype: Option<usize>,
272    weakset_prototype: Option<usize>,
273    dataview_prototype: Option<usize>,
274    typed_array_prototype: Option<usize>,
275    error_prototype: Option<usize>,
276    type_error_prototype: Option<usize>,
277    reference_error_prototype: Option<usize>,
278    syntax_error_prototype: Option<usize>,
279    range_error_prototype: Option<usize>,
280    uri_error_prototype: Option<usize>,
281    eval_error_prototype: Option<usize>,
282    symbol_prototype: Option<usize>,
283    bool_prototype: Option<usize>,
284    bigint_prototype: Option<usize>,
285    weakref_prototype: Option<usize>,
286    finalization_registry_prototype: Option<usize>,
287    pub finalization_registries: std::cell::RefCell<Vec<usize>>,
288    generator_prototype: Option<usize>,
289    async_generator_prototype: Option<usize>,
290    promise_prototype: Option<usize>,
291
292    register_vm_ptr: Option<usize>,
293    compiler_opt_level: OptLevel,
294
295    pub pending_exception: Option<JSValue>,
296
297    pending_callback: Option<PendingCallback>,
298
299    microtask_queue: MicrotaskQueue,
300
301    current_module_specifier: Option<String>,
302    import_meta_object: Option<usize>,
303
304    event_loop: EventLoop,
305
306    running_event_loop: Option<*mut EventLoop>,
307
308    shape_cache: ShapeCache,
309
310    pub common_atoms: CommonAtoms,
311
312    cached_int_atoms: [Atom; 100],
313
314    args_length_shape: Option<std::ptr::NonNull<crate::object::shape::Shape>>,
315}
316
317#[derive(Clone)]
318pub struct PendingCallback {
319    pub func: JSValue,
320
321    pub args: Vec<JSValue>,
322
323    pub is_method_call: bool,
324}
325
326impl JSContext {
327    const INTERRUPT_THRESHOLD: i32 = 1000;
328
329    pub fn new(runtime: &mut JSRuntime) -> Self {
330        let global = JSObject::new_global();
331        let global_ptr = Box::into_raw(Box::new(global)) as usize;
332        runtime.gc_heap_mut().track(global_ptr);
333        let global_value = JSValue::new_object(global_ptr);
334
335        let mut ctx = JSContext {
336            runtime: runtime as *mut JSRuntime,
337            global_object: global_value,
338            interrupt_counter: Self::INTERRUPT_THRESHOLD,
339            builtin_functions: FxHashMap::default(),
340            string_prototype: None,
341            number_prototype: None,
342            array_prototype: None,
343            array_iterator_prototype: None,
344            map_iterator_prototype: None,
345            set_iterator_prototype: None,
346            regexp_prototype: None,
347            date_prototype: None,
348            object_prototype: None,
349            function_prototype: None,
350            map_prototype: None,
351            set_prototype: None,
352            weakmap_prototype: None,
353            weakset_prototype: None,
354            dataview_prototype: None,
355            typed_array_prototype: None,
356            error_prototype: None,
357            type_error_prototype: None,
358            reference_error_prototype: None,
359            syntax_error_prototype: None,
360            range_error_prototype: None,
361            uri_error_prototype: None,
362            eval_error_prototype: None,
363            symbol_prototype: None,
364            bool_prototype: None,
365            bigint_prototype: None,
366            weakref_prototype: None,
367            finalization_registry_prototype: None,
368            finalization_registries: std::cell::RefCell::new(Vec::new()),
369            generator_prototype: None,
370            async_generator_prototype: None,
371            promise_prototype: None,
372            register_vm_ptr: None,
373            compiler_opt_level: OptLevel::default(),
374            pending_exception: None,
375            pending_callback: None,
376            microtask_queue: MicrotaskQueue::new(),
377            current_module_specifier: None,
378            import_meta_object: None,
379            event_loop: EventLoop::new(),
380            running_event_loop: None,
381            shape_cache: ShapeCache::new(),
382            common_atoms: CommonAtoms::new(runtime.atom_table_mut()),
383            cached_int_atoms: {
384                let mut arr = [Atom::empty(); 100];
385                for i in 0..100 {
386                    arr[i] = runtime.atom_table_mut().intern(&i.to_string());
387                }
388                arr
389            },
390            args_length_shape: None,
391        };
392
393        builtins::init_globals(&mut ctx);
394
395        ctx
396    }
397
398    #[inline(always)]
399    pub fn check_interrupt(&mut self) -> Result<(), String> {
400        self.interrupt_counter -= 1;
401        if self.interrupt_counter <= 0 {
402            self.interrupt_counter = Self::INTERRUPT_THRESHOLD;
403            if self.runtime_mut().is_interrupted() {
404                return Err("interrupted".to_string());
405            }
406        }
407        Ok(())
408    }
409
410    #[inline(always)]
411    pub fn reset_interrupt_counter(&mut self) {
412        self.interrupt_counter = 0;
413    }
414
415    pub fn runtime(&self) -> &JSRuntime {
416        unsafe { &*self.runtime }
417    }
418
419    pub fn runtime_mut(&mut self) -> &mut JSRuntime {
420        unsafe { &mut *self.runtime }
421    }
422
423    pub fn atom_table(&self) -> &AtomTable {
424        self.runtime().atom_table()
425    }
426
427    pub fn atom_table_mut(&mut self) -> &mut AtomTable {
428        self.runtime_mut().atom_table_mut()
429    }
430
431    pub fn shape_cache(&self) -> &ShapeCache {
432        &self.shape_cache
433    }
434
435    pub fn shape_cache_mut(&mut self) -> &mut ShapeCache {
436        &mut self.shape_cache
437    }
438
439    #[inline]
440    pub fn get_or_create_args_length_shape(
441        &mut self,
442    ) -> std::ptr::NonNull<crate::object::shape::Shape> {
443        if let Some(s) = self.args_length_shape {
444            return s;
445        }
446        let root = self.shape_cache.root_shape();
447        let s = self.shape_cache.transition(root, self.common_atoms.length);
448        self.args_length_shape = Some(s);
449        s
450    }
451
452    pub fn global(&self) -> JSValue {
453        self.global_object
454    }
455
456    pub fn set_global(&mut self, value: JSValue) {
457        self.global_object = value;
458    }
459
460    pub fn intern(&mut self, s: &str) -> Atom {
461        self.atom_table_mut().intern(s)
462    }
463
464    #[inline]
465    pub fn intern_concat(&mut self, a: &str, b: &str) -> Atom {
466        self.atom_table_mut().intern_concat(a, b)
467    }
468
469    #[inline]
470    pub fn intern_concat_atoms(&mut self, a: Atom, b: Atom) -> Atom {
471        self.atom_table_mut().intern_concat_atoms(a, b)
472    }
473
474    #[inline]
475    pub fn int_atom(&self, n: usize) -> Atom {
476        if n < 100 {
477            unsafe { *self.cached_int_atoms.get_unchecked(n) }
478        } else {
479            self.common_atoms.empty
480        }
481    }
482
483    #[inline]
484    pub fn int_atom_mut(&mut self, n: usize) -> Atom {
485        if n < 100 {
486            unsafe { *self.cached_int_atoms.get_unchecked(n) }
487        } else {
488            self.atom_table_mut().intern(&n.to_string())
489        }
490    }
491
492    pub fn intern_fast(&mut self, s: &str) -> Atom {
493        self.atom_table_mut().intern_fast(s)
494    }
495
496    pub fn lookup_atom(&self, s: &str) -> Option<Atom> {
497        self.atom_table().lookup(s)
498    }
499
500    pub fn get_atom_str(&self, atom: Atom) -> &str {
501        self.atom_table().get(atom)
502    }
503
504    #[inline]
505    pub fn string_char_count(&self, atom: Atom) -> usize {
506        self.atom_table().char_count(atom)
507    }
508
509    #[inline]
510    pub fn string_char_code_at(&self, atom: Atom, index: usize) -> Option<u32> {
511        self.atom_table().char_code_at(atom, index)
512    }
513
514    pub fn mark_symbol_atom(&mut self, atom: Atom) {
515        self.atom_table_mut().mark_symbol_atom(atom.index());
516    }
517
518    pub fn is_symbol_atom(&self, atom: Atom) -> bool {
519        self.atom_table().is_symbol_atom(atom.index())
520    }
521
522    pub fn register_builtin(&mut self, name: &str, func: HostFunction) {
523        self.builtin_functions.insert(name.to_string(), func);
524    }
525
526    pub fn register_global_builtin(
527        &mut self,
528        name: &'static str,
529        arity: u32,
530        func: crate::host::HostFunc,
531    ) {
532        self.register_builtin(name, HostFunction::new(name, arity, func));
533        let mut f = crate::object::function::JSFunction::new_builtin(self.intern(name), arity);
534        f.set_builtin_marker(self, name);
535        let ptr = Box::into_raw(Box::new(f)) as usize;
536        self.runtime_mut().gc_heap_mut().track_function(ptr);
537        self.global()
538            .as_object_mut()
539            .set(self.intern(name), crate::value::JSValue::new_function(ptr));
540    }
541
542    pub fn call_builtin(&mut self, name: &str, args: &[JSValue]) -> JSValue {
543        let func = self.builtin_functions.get(name).cloned();
544        if let Some(f) = func {
545            f.call(self, args)
546        } else {
547            JSValue::undefined()
548        }
549    }
550
551    pub fn get_builtin_func(&self, name: &str) -> Option<crate::host::func::HostFunc> {
552        self.builtin_functions.get(name).map(|f| f.func)
553    }
554
555    pub fn get_builtin_name(&self, name: &str) -> Option<&'static str> {
556        self.builtin_functions.get(name).map(|f| f.name)
557    }
558
559    pub fn builtin_needs_this(&self, name: &str) -> bool {
560        self.builtin_functions
561            .get(name)
562            .map(|f| f.needs_this)
563            .unwrap_or(false)
564    }
565
566    pub fn builtin_is_constructor(&self, name: &str) -> bool {
567        self.builtin_functions
568            .get(name)
569            .map(|f| f.is_constructor)
570            .unwrap_or(false)
571    }
572
573    pub fn get_builtin_arity(&self, name: &str) -> Option<u32> {
574        self.builtin_functions.get(name).map(|f| f.arity)
575    }
576
577    pub fn call_builtin_direct(
578        &mut self,
579        func: crate::host::func::HostFunc,
580        args: &[JSValue],
581    ) -> JSValue {
582        func(self, args)
583    }
584
585    pub fn set_string_prototype(&mut self, ptr: usize) {
586        self.string_prototype = Some(ptr);
587    }
588
589    pub fn set_number_prototype(&mut self, ptr: usize) {
590        self.number_prototype = Some(ptr);
591    }
592
593    pub fn set_array_prototype(&mut self, ptr: usize) {
594        self.array_prototype = Some(ptr);
595    }
596
597    pub fn set_array_iterator_prototype(&mut self, ptr: usize) {
598        self.array_iterator_prototype = Some(ptr);
599    }
600
601    pub fn get_array_iterator_prototype(&self) -> Option<usize> {
602        self.array_iterator_prototype
603    }
604
605    pub fn set_map_iterator_prototype(&mut self, ptr: usize) {
606        self.map_iterator_prototype = Some(ptr);
607    }
608
609    pub fn get_map_iterator_prototype(&self) -> Option<usize> {
610        self.map_iterator_prototype
611    }
612
613    pub fn set_set_iterator_prototype(&mut self, ptr: usize) {
614        self.set_iterator_prototype = Some(ptr);
615    }
616
617    pub fn get_set_iterator_prototype(&self) -> Option<usize> {
618        self.set_iterator_prototype
619    }
620
621    pub fn set_regexp_prototype(&mut self, ptr: usize) {
622        self.regexp_prototype = Some(ptr);
623    }
624
625    pub fn set_object_prototype(&mut self, ptr: usize) {
626        self.object_prototype = Some(ptr);
627    }
628
629    pub fn set_function_prototype(&mut self, ptr: usize) {
630        self.function_prototype = Some(ptr);
631    }
632
633    pub fn set_map_prototype(&mut self, ptr: usize) {
634        self.map_prototype = Some(ptr);
635    }
636
637    pub fn set_set_prototype(&mut self, ptr: usize) {
638        self.set_prototype = Some(ptr);
639    }
640
641    pub fn get_string_prototype(&self) -> Option<*mut JSObject> {
642        self.string_prototype.map(|p| p as *mut JSObject)
643    }
644
645    pub fn get_number_prototype(&self) -> Option<*mut JSObject> {
646        self.number_prototype.map(|p| p as *mut JSObject)
647    }
648
649    pub fn get_bool_prototype(&self) -> Option<*mut JSObject> {
650        self.bool_prototype.map(|p| p as *mut JSObject)
651    }
652
653    pub fn set_bool_prototype(&mut self, ptr: usize) {
654        self.bool_prototype = Some(ptr);
655    }
656
657    pub fn get_bigint_prototype(&self) -> Option<*mut JSObject> {
658        self.bigint_prototype.map(|p| p as *mut JSObject)
659    }
660
661    pub fn set_bigint_prototype(&mut self, ptr: usize) {
662        self.bigint_prototype = Some(ptr);
663    }
664
665    pub fn get_array_prototype(&self) -> Option<*mut JSObject> {
666        self.array_prototype.map(|p| p as *mut JSObject)
667    }
668
669    pub fn get_regexp_prototype(&self) -> Option<*mut JSObject> {
670        self.regexp_prototype.map(|p| p as *mut JSObject)
671    }
672
673    pub fn get_object_prototype(&self) -> Option<*mut JSObject> {
674        self.object_prototype.map(|p| p as *mut JSObject)
675    }
676
677    pub fn set_date_prototype(&mut self, ptr: usize) {
678        self.date_prototype = Some(ptr);
679    }
680
681    pub fn get_date_prototype(&self) -> Option<*mut JSObject> {
682        self.date_prototype.map(|p| p as *mut JSObject)
683    }
684
685    pub fn get_function_prototype(&self) -> Option<*mut JSObject> {
686        self.function_prototype.map(|p| p as *mut JSObject)
687    }
688
689    pub fn get_map_prototype(&self) -> Option<*mut JSObject> {
690        self.map_prototype.map(|p| p as *mut JSObject)
691    }
692
693    pub fn get_set_prototype(&self) -> Option<*mut JSObject> {
694        self.set_prototype.map(|p| p as *mut JSObject)
695    }
696
697    pub fn set_weakmap_prototype(&mut self, ptr: usize) {
698        self.weakmap_prototype = Some(ptr);
699    }
700
701    pub fn get_weakmap_prototype(&self) -> Option<*mut JSObject> {
702        self.weakmap_prototype.map(|p| p as *mut JSObject)
703    }
704
705    pub fn set_weakset_prototype(&mut self, ptr: usize) {
706        self.weakset_prototype = Some(ptr);
707    }
708
709    pub fn set_dataview_prototype(&mut self, ptr: usize) {
710        self.dataview_prototype = Some(ptr);
711    }
712
713    pub fn set_typed_array_prototype(&mut self, ptr: usize) {
714        self.typed_array_prototype = Some(ptr);
715    }
716
717    pub fn get_weakset_prototype(&self) -> Option<*mut JSObject> {
718        self.weakset_prototype.map(|p| p as *mut JSObject)
719    }
720
721    pub fn get_dataview_prototype(&self) -> Option<*mut JSObject> {
722        self.dataview_prototype.map(|p| p as *mut JSObject)
723    }
724
725    pub fn get_typed_array_prototype(&self) -> Option<*mut JSObject> {
726        self.typed_array_prototype.map(|p| p as *mut JSObject)
727    }
728
729    pub fn set_error_prototype(&mut self, ptr: usize) {
730        self.error_prototype = Some(ptr);
731    }
732
733    pub fn get_error_prototype(&self) -> Option<*mut JSObject> {
734        self.error_prototype.map(|p| p as *mut JSObject)
735    }
736
737    pub fn set_type_error_prototype(&mut self, ptr: usize) {
738        self.type_error_prototype = Some(ptr);
739    }
740
741    pub fn get_type_error_prototype(&self) -> Option<*mut JSObject> {
742        self.type_error_prototype.map(|p| p as *mut JSObject)
743    }
744
745    pub fn set_reference_error_prototype(&mut self, ptr: usize) {
746        self.reference_error_prototype = Some(ptr);
747    }
748
749    pub fn get_reference_error_prototype(&self) -> Option<*mut JSObject> {
750        self.reference_error_prototype.map(|p| p as *mut JSObject)
751    }
752
753    pub fn set_range_error_prototype(&mut self, ptr: usize) {
754        self.range_error_prototype = Some(ptr);
755    }
756
757    pub fn get_range_error_prototype(&self) -> Option<*mut JSObject> {
758        self.range_error_prototype.map(|p| p as *mut JSObject)
759    }
760
761    pub fn set_uri_error_prototype(&mut self, ptr: usize) {
762        self.uri_error_prototype = Some(ptr);
763    }
764
765    pub fn get_uri_error_prototype(&self) -> Option<*mut JSObject> {
766        self.uri_error_prototype.map(|p| p as *mut JSObject)
767    }
768
769    pub fn set_syntax_error_prototype(&mut self, ptr: usize) {
770        self.syntax_error_prototype = Some(ptr);
771    }
772
773    pub fn get_syntax_error_prototype(&self) -> Option<*mut JSObject> {
774        self.syntax_error_prototype.map(|p| p as *mut JSObject)
775    }
776
777    pub fn set_eval_error_prototype(&mut self, ptr: usize) {
778        self.eval_error_prototype = Some(ptr);
779    }
780
781    pub fn get_eval_error_prototype(&self) -> Option<*mut JSObject> {
782        self.eval_error_prototype.map(|p| p as *mut JSObject)
783    }
784
785    pub fn set_symbol_prototype(&mut self, ptr: usize) {
786        self.symbol_prototype = Some(ptr);
787    }
788
789    pub fn get_symbol_prototype(&self) -> Option<*mut JSObject> {
790        self.symbol_prototype.map(|p| p as *mut JSObject)
791    }
792
793    pub fn set_weakref_prototype(&mut self, ptr: usize) {
794        self.weakref_prototype = Some(ptr);
795    }
796
797    pub fn get_weakref_prototype(&self) -> Option<*mut JSObject> {
798        self.weakref_prototype.map(|p| p as *mut JSObject)
799    }
800
801    pub fn set_finalization_registry_prototype(&mut self, ptr: usize) {
802        self.finalization_registry_prototype = Some(ptr);
803    }
804
805    pub fn get_finalization_registry_prototype(&self) -> Option<*mut JSObject> {
806        self.finalization_registry_prototype
807            .map(|p| p as *mut JSObject)
808    }
809
810    pub fn set_generator_prototype(&mut self, ptr: usize) {
811        self.generator_prototype = Some(ptr);
812    }
813
814    pub fn get_generator_prototype(&self) -> Option<*mut JSObject> {
815        self.generator_prototype.map(|p| p as *mut JSObject)
816    }
817
818    pub fn set_async_generator_prototype(&mut self, ptr: usize) {
819        self.async_generator_prototype = Some(ptr);
820    }
821
822    pub fn get_async_generator_prototype(&self) -> Option<*mut JSObject> {
823        self.async_generator_prototype.map(|p| p as *mut JSObject)
824    }
825
826    pub fn set_promise_prototype(&mut self, ptr: usize) {
827        self.promise_prototype = Some(ptr);
828    }
829
830    pub fn get_promise_prototype(&self) -> Option<*mut JSObject> {
831        self.promise_prototype.map(|p| p as *mut JSObject)
832    }
833
834    pub fn set_register_vm_ptr(&mut self, ptr: Option<usize>) {
835        self.register_vm_ptr = ptr;
836    }
837
838    pub fn get_register_vm_ptr(&self) -> Option<usize> {
839        self.register_vm_ptr
840    }
841
842    pub fn add_extension(&mut self, ext: Box<dyn MacroTaskExtension>) {
843        self.event_loop_mut().extensions.push(ext);
844    }
845
846    pub fn set_compiler_opt_level(&mut self, opt_level: OptLevel) {
847        self.compiler_opt_level = opt_level;
848    }
849
850    pub fn get_compiler_opt_level(&self) -> OptLevel {
851        self.compiler_opt_level
852    }
853
854    pub fn set_pending_callback(&mut self, callback: PendingCallback) {
855        self.pending_callback = Some(callback);
856    }
857
858    pub fn take_pending_callback(&mut self) -> Option<PendingCallback> {
859        self.pending_callback.take()
860    }
861
862    pub fn has_pending_callback(&self) -> bool {
863        self.pending_callback.is_some()
864    }
865
866    pub fn microtask_enqueue(&mut self, task: Microtask) {
867        self.microtask_queue.enqueue(task);
868    }
869
870    pub fn microtask_is_empty(&self) -> bool {
871        self.microtask_queue.is_empty()
872    }
873
874    pub fn microtask_dequeue(&mut self) -> Option<Microtask> {
875        self.microtask_queue.dequeue()
876    }
877
878    pub fn set_current_module(&mut self, specifier: Option<String>) {
879        self.current_module_specifier = specifier;
880    }
881
882    pub fn get_current_module(&self) -> Option<&str> {
883        self.current_module_specifier.as_deref()
884    }
885
886    pub fn get_symbol_registry_ptr(&self) -> Option<usize> {
887        self.runtime().symbol_registry()
888    }
889
890    pub fn set_symbol_registry_ptr(&mut self, ptr: Option<usize>) {
891        self.runtime_mut().set_symbol_registry(ptr);
892    }
893
894    pub fn set_import_meta(&mut self, ptr: Option<usize>) {
895        self.import_meta_object = ptr;
896    }
897
898    pub fn get_import_meta(&self) -> Option<usize> {
899        self.import_meta_object
900    }
901
902    pub fn event_loop(&self) -> &EventLoop {
903        &self.event_loop
904    }
905
906    pub fn event_loop_mut(&mut self) -> &mut EventLoop {
907        if let Some(ptr) = self.running_event_loop {
908            unsafe { &mut *ptr }
909        } else {
910            &mut self.event_loop
911        }
912    }
913
914    pub fn run_event_loop(&mut self) -> Result<super::event_loop::EventLoopResult, String> {
915        let mut event_loop = std::mem::take(&mut self.event_loop);
916
917        self.running_event_loop = Some(&mut event_loop as *mut EventLoop);
918        let result = event_loop.run_until_complete(self, None);
919        self.running_event_loop = None;
920        self.event_loop = event_loop;
921        result
922    }
923
924    pub fn run_event_loop_with_timeout(
925        &mut self,
926        timeout_ms: u64,
927    ) -> Result<super::event_loop::EventLoopResult, String> {
928        let mut event_loop = std::mem::take(&mut self.event_loop);
929
930        self.running_event_loop = Some(&mut event_loop as *mut EventLoop);
931        let result = event_loop.run_until_complete(self, Some(timeout_ms));
932        self.running_event_loop = None;
933        self.event_loop = event_loop;
934        result
935    }
936}