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 ; 3 4pub ( crate ) struct UncaughtException { 5pub ( crate ) value : v8:: Global < v8:: Value >, 6pub ( crate ) filename : String , 7pub ( crate ) line : u32 , 8pub ( crate ) column : u32 , 9} 10type ExceptionSlot =RefCell < VecDeque < UncaughtException >>; 11 12extern "C" fn uncaught_exception ( message : v8:: Local < v8:: Message >, exception : v8:: Local < v8:: Value >) { 13// V8 reports microtask exceptions to message listeners instead of the enclosing TryCatch. 14// SAFETY: V8 invokes this listener with a valid message from the active isolate. 15 v8:: callback_scope!( unsafe scope, message); 16let exception =UncaughtException { 17value : v8:: Global :: new ( scope, exception), 18filename : message 19. get_script_resource_name ( scope) 20. map ( |name| name. to_rust_string_lossy ( scope)) 21. unwrap_or_default (), 22line : message 23. get_line_number ( scope) 24. unwrap_or_default () 25. try_into () 26. unwrap_or_default (), 27column : message 28. get_start_column () 29. saturating_add ( 1 ) 30. try_into () 31. unwrap_or_default (), 32}; 33 scope 34. get_slot ::< ExceptionSlot >() 35. unwrap () 36. borrow_mut () 37. push_back ( exception); 38} 39 40pub ( crate ) fn clear ( isolate : & mut v8:: Isolate ) { 41 isolate. remove_slot ::< ExceptionSlot >(); 42} 43 44pub ( crate ) fn external_references () ->Vec < v8:: ExternalReference > { 45vec! [ v8:: ExternalReference { 46pointer : uncaught_exceptionas * mut std:: ffi:: c_void , 47}] 48} 49 50pub ( crate ) fn init ( isolate : & mut v8:: Isolate ) { 51 isolate. set_slot ::< ExceptionSlot >( RefCell :: new ( VecDeque :: new ())); 52} 53 54/// Message listeners belong to the isolate heap, and V8 serializes them into snapshots. 55pub ( crate ) fn add_listener ( isolate : & mut v8:: Isolate ) { 56 isolate. add_message_listener ( uncaught_exception); 57} 58 59pub ( crate ) fn enqueue < ' s >( 60scope : & mut v8:: PinScope < ' s , ' _ >, 61args : v8:: FunctionCallbackArguments < ' s >, 62_result : v8:: ReturnValue , 63) { 64let Ok ( callback) = v8:: Local ::< v8:: Function >:: try_from ( args. get ( 0 )) else { 65let message = v8:: String :: new ( scope, "Expected a microtask callback" ). unwrap (); 66let error = v8:: Exception :: type_error ( scope, message); 67 scope. throw_exception ( error); 68return ; 69}; 70 scope. enqueue_microtask ( callback); 71} 72 73pub ( crate ) fn process_exceptions ( scope : & mut v8:: PinScope ) ->Option < v8:: Global < v8:: Value >> { 74let mut fatal =None ; 75loop { 76let exceptions = 77 std:: mem:: take ( & mut * scope. get_slot ::< ExceptionSlot >(). unwrap (). borrow_mut ()); 78if exceptions. is_empty () { 79return fatal; 80} 81for exceptionin exceptions{ 82let error = v8:: Local :: new ( scope, & exception. value ); 83if !crate :: reporting:: report_exception_with_location ( 84 scope, 85 error, 86& exception. filename , 87 exception. line , 88 exception. column , 89) && fatal. is_none () 90{ 91 fatal =Some ( v8:: Global :: new ( scope, error)); 92} 93} 94crate :: op:: checkpoint ( scope); 95} 96}