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}
131
132impl CommonAtoms {
133 pub fn new(tbl: &mut AtomTable) -> Self {
134 CommonAtoms {
135 length: tbl.intern("length"),
136 prototype: tbl.intern("prototype"),
137 constructor: tbl.intern("constructor"),
138 call: tbl.intern("call"),
139 apply: tbl.intern("apply"),
140 bind: tbl.intern("bind"),
141 to_string: tbl.intern("toString"),
142 value_of: tbl.intern("valueOf"),
143 push: tbl.intern("push"),
144 pop: tbl.intern("pop"),
145 shift: tbl.intern("shift"),
146 unshift: tbl.intern("unshift"),
147 slice: tbl.intern("slice"),
148 splice: tbl.intern("splice"),
149 join: tbl.intern("join"),
150 map: tbl.intern("map"),
151 for_each: tbl.intern("forEach"),
152 filter: tbl.intern("filter"),
153 reduce: tbl.intern("reduce"),
154 index_of: tbl.intern("indexOf"),
155 last_index_of: tbl.intern("lastIndexOf"),
156 includes: tbl.intern("includes"),
157 concat: tbl.intern("concat"),
158 reverse: tbl.intern("reverse"),
159 sort: tbl.intern("sort"),
160 flat: tbl.intern("flat"),
161 flat_map: tbl.intern("flatMap"),
162 find: tbl.intern("find"),
163 find_index: tbl.intern("findIndex"),
164 every: tbl.intern("every"),
165 some: tbl.intern("some"),
166 fill: tbl.intern("fill"),
167 keys: tbl.intern("keys"),
168 values: tbl.intern("values"),
169 entries: tbl.intern("entries"),
170 has_own_property: tbl.intern("hasOwnProperty"),
171 is_prototype_of: tbl.intern("isPrototypeOf"),
172 property_is_enumerable: tbl.intern("propertyIsEnumerable"),
173 to_locale_string: tbl.intern("toLocaleString"),
174 split: tbl.intern("split"),
175 replace: tbl.intern("replace"),
176 match_atom: tbl.intern("match"),
177 search: tbl.intern("search"),
178 test: tbl.intern("test"),
179 exec: tbl.intern("exec"),
180 then: tbl.intern("then"),
181 catch: tbl.intern("catch"),
182 finally: tbl.intern("finally"),
183 message: tbl.intern("message"),
184 name: tbl.intern("name"),
185 stack: tbl.intern("stack"),
186 __proto__: tbl.intern("__proto__"),
187 __super__: tbl.intern("__super__"),
188 __boundFn: tbl.intern("__boundFn"),
189 __boundArgs: tbl.intern("__boundArgs"),
190 __boundThis: tbl.intern("__boundThis"),
191 __value__: tbl.intern("__value__"),
192 __dateValue__: tbl.intern("__dateValue__"),
193 __pattern__: tbl.intern("__pattern__"),
194 __flags__: tbl.intern("__flags__"),
195 source: tbl.intern("source"),
196 global: tbl.intern("global"),
197 ignore_case: tbl.intern("ignoreCase"),
198 multiline: tbl.intern("multiline"),
199 sticky: tbl.intern("sticky"),
200 unicode: tbl.intern("unicode"),
201 undefined: tbl.intern("undefined"),
202 null: tbl.intern("null"),
203 object: tbl.intern("Object"),
204 function: tbl.intern("Function"),
205 number: tbl.intern("Number"),
206 string: tbl.intern("String"),
207 boolean: tbl.intern("Boolean"),
208 symbol: tbl.intern("Symbol"),
209 bigint: tbl.intern("BigInt"),
210 math: tbl.intern("Math"),
211 json: tbl.intern("JSON"),
212 array: tbl.intern("Array"),
213 regexp: tbl.intern("RegExp"),
214 error: tbl.intern("Error"),
215 date: tbl.intern("Date"),
216 promise: tbl.intern("Promise"),
217 map_ctor: tbl.intern("Map"),
218 set_ctor: tbl.intern("Set"),
219 weak_map_ctor: tbl.intern("WeakMap"),
220 weak_set_ctor: tbl.intern("WeakSet"),
221 proxy: tbl.intern("Proxy"),
222 reflect: tbl.intern("Reflect"),
223 console: tbl.intern("console"),
224 index: tbl.intern("index"),
225 input: tbl.intern("input"),
226 empty: tbl.intern(""),
227 n0: tbl.intern("0"),
228 n1: tbl.intern("1"),
229 typeof_undefined: tbl.intern("undefined"),
230 typeof_object: tbl.intern("object"),
231 typeof_boolean: tbl.intern("boolean"),
232 typeof_number: tbl.intern("number"),
233 typeof_bigint: tbl.intern("bigint"),
234 typeof_symbol: tbl.intern("symbol"),
235 typeof_string: tbl.intern("string"),
236 typeof_function: tbl.intern("function"),
237 dot_all: tbl.intern("dotAll"),
238 last_index: tbl.intern("lastIndex"),
239 callee: tbl.intern("callee"),
240 default_: tbl.intern("default"),
241 url: tbl.intern("url"),
242 __promise_state__: tbl.intern("__promise_state__"),
243 __promise_result__: tbl.intern("__promise_result__"),
244 __done__: tbl.intern("__done__"),
245 __iter_arr__: tbl.intern("__iter_arr__"),
246 __iter_idx__: tbl.intern("__iter_idx__"),
247 }
248 }
249}
250
251pub struct JSContext {
252 runtime: *mut JSRuntime,
253 global_object: JSValue,
254 interrupt_counter: i32,
255 builtin_functions: FxHashMap<String, HostFunction>,
256
257 string_prototype: Option<usize>,
258 number_prototype: Option<usize>,
259 array_prototype: Option<usize>,
260 regexp_prototype: Option<usize>,
261 object_prototype: Option<usize>,
262 function_prototype: Option<usize>,
263 map_prototype: Option<usize>,
264 set_prototype: Option<usize>,
265 weakmap_prototype: Option<usize>,
266 weakset_prototype: Option<usize>,
267 error_prototype: Option<usize>,
268 type_error_prototype: Option<usize>,
269 reference_error_prototype: Option<usize>,
270 syntax_error_prototype: Option<usize>,
271 range_error_prototype: Option<usize>,
272 symbol_prototype: Option<usize>,
273 weakref_prototype: Option<usize>,
274 finalization_registry_prototype: Option<usize>,
275 pub finalization_registries: std::cell::RefCell<Vec<usize>>,
276 generator_prototype: Option<usize>,
277 async_generator_prototype: Option<usize>,
278 promise_prototype: Option<usize>,
279
280 register_vm_ptr: Option<usize>,
281 compiler_opt_level: OptLevel,
282
283 pub pending_exception: Option<JSValue>,
284
285 pending_callback: Option<PendingCallback>,
286
287 microtask_queue: MicrotaskQueue,
288
289 current_module_specifier: Option<String>,
290 import_meta_object: Option<usize>,
291
292 event_loop: EventLoop,
293
294 running_event_loop: Option<*mut EventLoop>,
295
296 shape_cache: ShapeCache,
297
298 pub common_atoms: CommonAtoms,
299
300 cached_int_atoms: [Atom; 100],
301
302 args_length_shape: Option<std::ptr::NonNull<crate::object::shape::Shape>>,
303}
304
305#[derive(Clone)]
306pub struct PendingCallback {
307 pub func: JSValue,
308
309 pub args: Vec<JSValue>,
310
311 pub is_method_call: bool,
312}
313
314impl JSContext {
315 const INTERRUPT_THRESHOLD: i32 = 1000;
316
317 pub fn new(runtime: &mut JSRuntime) -> Self {
318 let global = JSObject::new_global();
319 let global_ptr = Box::into_raw(Box::new(global)) as usize;
320 runtime.gc_heap_mut().track(global_ptr);
321 let global_value = JSValue::new_object(global_ptr);
322
323 let mut ctx = JSContext {
324 runtime: runtime as *mut JSRuntime,
325 global_object: global_value,
326 interrupt_counter: Self::INTERRUPT_THRESHOLD,
327 builtin_functions: FxHashMap::default(),
328 string_prototype: None,
329 number_prototype: None,
330 array_prototype: None,
331 regexp_prototype: None,
332 object_prototype: None,
333 function_prototype: None,
334 map_prototype: None,
335 set_prototype: None,
336 weakmap_prototype: None,
337 weakset_prototype: None,
338 error_prototype: None,
339 type_error_prototype: None,
340 reference_error_prototype: None,
341 syntax_error_prototype: None,
342 range_error_prototype: None,
343 symbol_prototype: None,
344 weakref_prototype: None,
345 finalization_registry_prototype: None,
346 finalization_registries: std::cell::RefCell::new(Vec::new()),
347 generator_prototype: None,
348 async_generator_prototype: None,
349 promise_prototype: None,
350 register_vm_ptr: None,
351 compiler_opt_level: OptLevel::default(),
352 pending_exception: None,
353 pending_callback: None,
354 microtask_queue: MicrotaskQueue::new(),
355 current_module_specifier: None,
356 import_meta_object: None,
357 event_loop: EventLoop::new(),
358 running_event_loop: None,
359 shape_cache: ShapeCache::new(),
360 common_atoms: CommonAtoms::new(runtime.atom_table_mut()),
361 cached_int_atoms: {
362 let mut arr = [Atom::empty(); 100];
363 for i in 0..100 {
364 arr[i] = runtime.atom_table_mut().intern(&i.to_string());
365 }
366 arr
367 },
368 args_length_shape: None,
369 };
370
371 builtins::init_globals(&mut ctx);
372
373 ctx
374 }
375
376 #[inline(always)]
377 pub fn check_interrupt(&mut self) -> Result<(), String> {
378 self.interrupt_counter -= 1;
379 if self.interrupt_counter <= 0 {
380 self.interrupt_counter = Self::INTERRUPT_THRESHOLD;
381 if self.runtime_mut().is_interrupted() {
382 return Err("interrupted".to_string());
383 }
384 }
385 Ok(())
386 }
387
388 #[inline(always)]
389 pub fn reset_interrupt_counter(&mut self) {
390 self.interrupt_counter = 0;
391 }
392
393 pub fn runtime(&self) -> &JSRuntime {
394 unsafe { &*self.runtime }
395 }
396
397 pub fn runtime_mut(&mut self) -> &mut JSRuntime {
398 unsafe { &mut *self.runtime }
399 }
400
401 pub fn atom_table(&self) -> &AtomTable {
402 self.runtime().atom_table()
403 }
404
405 pub fn atom_table_mut(&mut self) -> &mut AtomTable {
406 self.runtime_mut().atom_table_mut()
407 }
408
409 pub fn shape_cache(&self) -> &ShapeCache {
410 &self.shape_cache
411 }
412
413 pub fn shape_cache_mut(&mut self) -> &mut ShapeCache {
414 &mut self.shape_cache
415 }
416
417 #[inline]
418 pub fn get_or_create_args_length_shape(
419 &mut self,
420 ) -> std::ptr::NonNull<crate::object::shape::Shape> {
421 if let Some(s) = self.args_length_shape {
422 return s;
423 }
424 let root = self.shape_cache.root_shape();
425 let s = self.shape_cache.transition(root, self.common_atoms.length);
426 self.args_length_shape = Some(s);
427 s
428 }
429
430 pub fn global(&self) -> JSValue {
431 self.global_object
432 }
433
434 pub fn set_global(&mut self, value: JSValue) {
435 self.global_object = value;
436 }
437
438 pub fn intern(&mut self, s: &str) -> Atom {
439 self.atom_table_mut().intern(s)
440 }
441
442 #[inline]
443 pub fn intern_concat(&mut self, a: &str, b: &str) -> Atom {
444 self.atom_table_mut().intern_concat(a, b)
445 }
446
447 #[inline]
448 pub fn intern_concat_atoms(&mut self, a: Atom, b: Atom) -> Atom {
449 self.atom_table_mut().intern_concat_atoms(a, b)
450 }
451
452 #[inline]
453 pub fn int_atom(&self, n: usize) -> Atom {
454 if n < 100 {
455 unsafe { *self.cached_int_atoms.get_unchecked(n) }
456 } else {
457 self.common_atoms.empty
458 }
459 }
460
461 #[inline]
462 pub fn int_atom_mut(&mut self, n: usize) -> Atom {
463 if n < 100 {
464 unsafe { *self.cached_int_atoms.get_unchecked(n) }
465 } else {
466 self.atom_table_mut().intern(&n.to_string())
467 }
468 }
469
470 pub fn intern_fast(&mut self, s: &str) -> Atom {
471 self.atom_table_mut().intern_fast(s)
472 }
473
474 pub fn lookup_atom(&self, s: &str) -> Option<Atom> {
475 self.atom_table().lookup(s)
476 }
477
478 pub fn get_atom_str(&self, atom: Atom) -> &str {
479 self.atom_table().get(atom)
480 }
481
482 #[inline]
483 pub fn string_char_count(&self, atom: Atom) -> usize {
484 self.atom_table().char_count(atom)
485 }
486
487 #[inline]
488 pub fn string_char_code_at(&self, atom: Atom, index: usize) -> Option<u32> {
489 self.atom_table().char_code_at(atom, index)
490 }
491
492 pub fn mark_symbol_atom(&mut self, atom: Atom) {
493 self.atom_table_mut().mark_symbol_atom(atom.index());
494 }
495
496 pub fn is_symbol_atom(&self, atom: Atom) -> bool {
497 self.atom_table().is_symbol_atom(atom.index())
498 }
499
500 pub fn register_builtin(&mut self, name: &str, func: HostFunction) {
501 self.builtin_functions.insert(name.to_string(), func);
502 }
503
504 pub fn register_global_builtin(&mut self, name: &'static str, arity: u32, func: crate::host::HostFunc) {
505 self.register_builtin(name, HostFunction::new(name, arity, func));
506 let mut f = crate::object::function::JSFunction::new_builtin(self.intern(name), arity);
507 f.set_builtin_marker(self, name);
508 let ptr = Box::into_raw(Box::new(f)) as usize;
509 self.runtime_mut().gc_heap_mut().track_function(ptr);
510 self.global()
511 .as_object_mut()
512 .set(self.intern(name), crate::value::JSValue::new_function(ptr));
513 }
514
515 pub fn call_builtin(&mut self, name: &str, args: &[JSValue]) -> JSValue {
516 let func = self.builtin_functions.get(name).cloned();
517 if let Some(f) = func {
518 f.call(self, args)
519 } else {
520 JSValue::undefined()
521 }
522 }
523
524 pub fn get_builtin_func(&self, name: &str) -> Option<crate::host::func::HostFunc> {
525 self.builtin_functions.get(name).map(|f| f.func)
526 }
527
528 pub fn call_builtin_direct(
529 &mut self,
530 func: crate::host::func::HostFunc,
531 args: &[JSValue],
532 ) -> JSValue {
533 func(self, args)
534 }
535
536 pub fn set_string_prototype(&mut self, ptr: usize) {
537 self.string_prototype = Some(ptr);
538 }
539
540 pub fn set_number_prototype(&mut self, ptr: usize) {
541 self.number_prototype = Some(ptr);
542 }
543
544 pub fn set_array_prototype(&mut self, ptr: usize) {
545 self.array_prototype = Some(ptr);
546 }
547
548 pub fn set_regexp_prototype(&mut self, ptr: usize) {
549 self.regexp_prototype = Some(ptr);
550 }
551
552 pub fn set_object_prototype(&mut self, ptr: usize) {
553 self.object_prototype = Some(ptr);
554 }
555
556 pub fn set_function_prototype(&mut self, ptr: usize) {
557 self.function_prototype = Some(ptr);
558 }
559
560 pub fn set_map_prototype(&mut self, ptr: usize) {
561 self.map_prototype = Some(ptr);
562 }
563
564 pub fn set_set_prototype(&mut self, ptr: usize) {
565 self.set_prototype = Some(ptr);
566 }
567
568 pub fn get_string_prototype(&self) -> Option<*mut JSObject> {
569 self.string_prototype.map(|p| p as *mut JSObject)
570 }
571
572 pub fn get_number_prototype(&self) -> Option<*mut JSObject> {
573 self.number_prototype.map(|p| p as *mut JSObject)
574 }
575
576 pub fn get_array_prototype(&self) -> Option<*mut JSObject> {
577 self.array_prototype.map(|p| p as *mut JSObject)
578 }
579
580 pub fn get_regexp_prototype(&self) -> Option<*mut JSObject> {
581 self.regexp_prototype.map(|p| p as *mut JSObject)
582 }
583
584 pub fn get_object_prototype(&self) -> Option<*mut JSObject> {
585 self.object_prototype.map(|p| p as *mut JSObject)
586 }
587
588 pub fn get_function_prototype(&self) -> Option<*mut JSObject> {
589 self.function_prototype.map(|p| p as *mut JSObject)
590 }
591
592 pub fn get_map_prototype(&self) -> Option<*mut JSObject> {
593 self.map_prototype.map(|p| p as *mut JSObject)
594 }
595
596 pub fn get_set_prototype(&self) -> Option<*mut JSObject> {
597 self.set_prototype.map(|p| p as *mut JSObject)
598 }
599
600 pub fn set_weakmap_prototype(&mut self, ptr: usize) {
601 self.weakmap_prototype = Some(ptr);
602 }
603
604 pub fn get_weakmap_prototype(&self) -> Option<*mut JSObject> {
605 self.weakmap_prototype.map(|p| p as *mut JSObject)
606 }
607
608 pub fn set_weakset_prototype(&mut self, ptr: usize) {
609 self.weakset_prototype = Some(ptr);
610 }
611
612 pub fn get_weakset_prototype(&self) -> Option<*mut JSObject> {
613 self.weakset_prototype.map(|p| p as *mut JSObject)
614 }
615
616 pub fn set_error_prototype(&mut self, ptr: usize) {
617 self.error_prototype = Some(ptr);
618 }
619
620 pub fn get_error_prototype(&self) -> Option<*mut JSObject> {
621 self.error_prototype.map(|p| p as *mut JSObject)
622 }
623
624 pub fn set_type_error_prototype(&mut self, ptr: usize) {
625 self.type_error_prototype = Some(ptr);
626 }
627
628 pub fn get_type_error_prototype(&self) -> Option<*mut JSObject> {
629 self.type_error_prototype.map(|p| p as *mut JSObject)
630 }
631
632 pub fn set_reference_error_prototype(&mut self, ptr: usize) {
633 self.reference_error_prototype = Some(ptr);
634 }
635
636 pub fn get_reference_error_prototype(&self) -> Option<*mut JSObject> {
637 self.reference_error_prototype.map(|p| p as *mut JSObject)
638 }
639
640 pub fn set_range_error_prototype(&mut self, ptr: usize) {
641 self.range_error_prototype = Some(ptr);
642 }
643
644 pub fn get_range_error_prototype(&self) -> Option<*mut JSObject> {
645 self.range_error_prototype.map(|p| p as *mut JSObject)
646 }
647
648 pub fn set_syntax_error_prototype(&mut self, ptr: usize) {
649 self.syntax_error_prototype = Some(ptr);
650 }
651
652 pub fn get_syntax_error_prototype(&self) -> Option<*mut JSObject> {
653 self.syntax_error_prototype.map(|p| p as *mut JSObject)
654 }
655
656 pub fn set_symbol_prototype(&mut self, ptr: usize) {
657 self.symbol_prototype = Some(ptr);
658 }
659
660 pub fn get_symbol_prototype(&self) -> Option<*mut JSObject> {
661 self.symbol_prototype.map(|p| p as *mut JSObject)
662 }
663
664 pub fn set_weakref_prototype(&mut self, ptr: usize) {
665 self.weakref_prototype = Some(ptr);
666 }
667
668 pub fn get_weakref_prototype(&self) -> Option<*mut JSObject> {
669 self.weakref_prototype.map(|p| p as *mut JSObject)
670 }
671
672 pub fn set_finalization_registry_prototype(&mut self, ptr: usize) {
673 self.finalization_registry_prototype = Some(ptr);
674 }
675
676 pub fn get_finalization_registry_prototype(&self) -> Option<*mut JSObject> {
677 self.finalization_registry_prototype
678 .map(|p| p as *mut JSObject)
679 }
680
681 pub fn set_generator_prototype(&mut self, ptr: usize) {
682 self.generator_prototype = Some(ptr);
683 }
684
685 pub fn get_generator_prototype(&self) -> Option<*mut JSObject> {
686 self.generator_prototype.map(|p| p as *mut JSObject)
687 }
688
689 pub fn set_async_generator_prototype(&mut self, ptr: usize) {
690 self.async_generator_prototype = Some(ptr);
691 }
692
693 pub fn get_async_generator_prototype(&self) -> Option<*mut JSObject> {
694 self.async_generator_prototype.map(|p| p as *mut JSObject)
695 }
696
697 pub fn set_promise_prototype(&mut self, ptr: usize) {
698 self.promise_prototype = Some(ptr);
699 }
700
701 pub fn get_promise_prototype(&self) -> Option<*mut JSObject> {
702 self.promise_prototype.map(|p| p as *mut JSObject)
703 }
704
705 pub fn set_register_vm_ptr(&mut self, ptr: Option<usize>) {
706 self.register_vm_ptr = ptr;
707 }
708
709 pub fn get_register_vm_ptr(&self) -> Option<usize> {
710 self.register_vm_ptr
711 }
712
713 pub fn add_extension(&mut self, ext: Box<dyn MacroTaskExtension>) {
714 self.event_loop_mut().extensions.push(ext);
715 }
716
717 pub fn set_compiler_opt_level(&mut self, opt_level: OptLevel) {
718 self.compiler_opt_level = opt_level;
719 }
720
721 pub fn get_compiler_opt_level(&self) -> OptLevel {
722 self.compiler_opt_level
723 }
724
725 pub fn set_pending_callback(&mut self, callback: PendingCallback) {
726 self.pending_callback = Some(callback);
727 }
728
729 pub fn take_pending_callback(&mut self) -> Option<PendingCallback> {
730 self.pending_callback.take()
731 }
732
733 pub fn has_pending_callback(&self) -> bool {
734 self.pending_callback.is_some()
735 }
736
737 pub fn microtask_enqueue(&mut self, task: Microtask) {
738 self.microtask_queue.enqueue(task);
739 }
740
741 pub fn microtask_is_empty(&self) -> bool {
742 self.microtask_queue.is_empty()
743 }
744
745 pub fn microtask_dequeue(&mut self) -> Option<Microtask> {
746 self.microtask_queue.dequeue()
747 }
748
749 pub fn set_current_module(&mut self, specifier: Option<String>) {
750 self.current_module_specifier = specifier;
751 }
752
753 pub fn get_current_module(&self) -> Option<&str> {
754 self.current_module_specifier.as_deref()
755 }
756
757 pub fn set_import_meta(&mut self, ptr: Option<usize>) {
758 self.import_meta_object = ptr;
759 }
760
761 pub fn get_import_meta(&self) -> Option<usize> {
762 self.import_meta_object
763 }
764
765 pub fn event_loop(&self) -> &EventLoop {
766 &self.event_loop
767 }
768
769 pub fn event_loop_mut(&mut self) -> &mut EventLoop {
770 if let Some(ptr) = self.running_event_loop {
771 unsafe { &mut *ptr }
772 } else {
773 &mut self.event_loop
774 }
775 }
776
777 pub fn run_event_loop(&mut self) -> Result<super::event_loop::EventLoopResult, String> {
778 let mut event_loop = std::mem::take(&mut self.event_loop);
779
780 self.running_event_loop = Some(&mut event_loop as *mut EventLoop);
781 let result = event_loop.run_until_complete(self, None);
782 self.running_event_loop = None;
783 self.event_loop = event_loop;
784 result
785 }
786
787 pub fn run_event_loop_with_timeout(
788 &mut self,
789 timeout_ms: u64,
790 ) -> Result<super::event_loop::EventLoopResult, String> {
791 let mut event_loop = std::mem::take(&mut self.event_loop);
792
793 self.running_event_loop = Some(&mut event_loop as *mut EventLoop);
794 let result = event_loop.run_until_complete(self, Some(timeout_ms));
795 self.running_event_loop = None;
796 self.event_loop = event_loop;
797 result
798 }
799}