char/avril
(wip) why'd you have to go and make things so complicaaaaated?
git clone https://git.t4t.associates/char/avril
d71572b
main
1use std:: cell:: RefCell ; 2use std:: collections:: VecDeque ; 3use std:: rc:: Rc ; 4 5struct Task { 6run : v8:: Global < v8:: Function >, 7finish : v8:: Global < v8:: Function >, 8} 9 10type Tasks =Rc < RefCell < VecDeque < Task >>>; 11 12pub ( crate ) fn clear ( isolate : & mut v8:: Isolate ) { 13 isolate. remove_slot ::< Tasks >(); 14} 15 16pub ( crate ) fn init ( isolate : & mut v8:: Isolate ) { 17 isolate. set_slot ::< Tasks >( Rc :: new ( RefCell :: new ( VecDeque :: new ()))); 18} 19 20pub ( crate ) fn enqueue < ' s >( 21scope : & mut v8:: PinScope < ' s , ' _ >, 22args : v8:: FunctionCallbackArguments < ' s >, 23_result : v8:: ReturnValue , 24) { 25let ( Ok ( run), Ok ( finish)) =( 26 v8:: Local ::< v8:: Function >:: try_from ( args. get ( 0 )), 27 v8:: Local ::< v8:: Function >:: try_from ( args. get ( 1 )), 28) else { 29let message = v8:: String :: new ( scope, "Tasks require run and finish callbacks" ). unwrap (); 30let error = v8:: Exception :: type_error ( scope, message); 31 scope. throw_exception ( error); 32return ; 33}; 34let task =Task { 35run : v8:: Global :: new ( scope, run), 36finish : v8:: Global :: new ( scope, finish), 37}; 38 scope 39. get_slot ::< Tasks >() 40. unwrap () 41. borrow_mut () 42. push_back ( task); 43if let Some ( waker) = scope. get_slot ::< std:: task:: Waker >() { 44 waker. wake_by_ref (); 45} 46} 47 48pub ( crate ) fn has_pending ( isolate : & v8:: Isolate ) ->bool { 49 !isolate. get_slot ::< Tasks >(). unwrap (). borrow (). is_empty () 50} 51 52pub ( crate ) fn run_next ( scope : & mut v8:: PinScope ) ->Option < bool > { 53let task = scope. get_slot ::< Tasks >(). unwrap (). borrow_mut (). pop_front (); 54let Some ( task) = taskelse { 55return Some ( false ); 56}; 57 v8:: tc_scope!( let scope, scope); 58let receiver = v8:: undefined ( scope). into (); 59let run = v8:: Local :: new ( scope, task. run ); 60let error =if run. call ( scope, receiver, & []). is_none () { 61let error = v8:: Global :: new ( scope, scope. exception () ?); 62 scope. reset (); 63Some ( error) 64} else { 65None 66}; 67// Post-callback steps such as repeating a timer follow its full microtask checkpoint. 68crate :: op:: checkpoint ( scope); 69let finish = v8:: Local :: new ( scope, task. finish ); 70let finished = finish. call ( scope, receiver, & []). is_some (); 71if let Some ( error) = error{ 72 scope. reset (); 73let error = v8:: Local :: new ( scope, error); 74 scope. throw_exception ( error); 75 scope. rethrow (); 76return None ; 77} 78if !finished{ 79 scope. rethrow (); 80return None ; 81} 82Some ( true ) 83}