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:: io:: Write ; 3use std:: rc:: Rc ; 4 5use crate :: v8; 6 7type Handler = v8:: Global < v8:: Function >; 8type Handlers =Rc < RefCell < Option <[ Handler ; 3 ]>>>; 9type Processed =Rc < RefCell < Option < v8:: Global < v8:: Value >>>>; 10 11pub ( crate ) fn clear ( isolate : & mut v8:: Isolate ) { 12 isolate. remove_slot ::< Handlers >(); 13 isolate. remove_slot ::< Processed >(); 14} 15 16pub ( crate ) fn has_handlers ( isolate : & v8:: Isolate ) ->bool { 17 isolate. get_slot ::< Handlers >(). unwrap (). borrow (). is_some () 18} 19 20pub ( crate ) fn init ( isolate : & mut v8:: Isolate ) { 21 isolate. set_slot ::< Handlers >( Rc :: new ( RefCell :: new ( None ))); 22 isolate. set_slot ::< Processed >( Rc :: new ( RefCell :: new ( None ))); 23} 24 25pub ( crate ) fn is_promise ( 26scope : & mut v8:: PinScope , 27args : v8:: FunctionCallbackArguments , 28mut result : v8:: ReturnValue , 29) { 30let is_promise = v8:: Local ::< v8:: Promise >:: try_from ( args. get ( 0 )). is_ok (); 31 result. set ( v8:: Boolean :: new ( scope, is_promise). into ()); 32} 33 34pub ( crate ) fn set_event_handlers ( 35scope : & mut v8:: PinScope , 36args : v8:: FunctionCallbackArguments , 37_result : v8:: ReturnValue , 38) { 39let handlers =[ 0 , 1 , 2 ]. map ( |index| v8:: Local ::< v8:: Function >:: try_from ( args. get ( index))); 40let [ Ok ( exception), Ok ( unhandled), Ok ( handled)] = handlerselse { 41let message = v8:: String :: new ( scope, "Expected three event handlers" ). unwrap (); 42 scope. throw_exception ( v8:: Exception :: type_error ( scope, message)); 43return ; 44}; 45let slot = scope. get_slot ::< Handlers >(). unwrap (). clone (); 46let mut slot = slot. borrow_mut (); 47if slot. is_some () { 48let message = v8:: String :: new ( scope, "Event handlers already registered" ). unwrap (); 49 scope. throw_exception ( v8:: Exception :: error ( scope, message)); 50return ; 51} 52* slot =Some ([ 53 v8:: Global :: new ( scope, exception), 54 v8:: Global :: new ( scope, unhandled), 55 v8:: Global :: new ( scope, handled), 56]); 57} 58 59pub ( crate ) fn report_exception_with_location < ' s , ' i >( 60scope : & mut v8:: PinScope < ' s , ' i >, 61error : v8:: Local < ' s , v8:: Value >, 62filename : & str , 63line : u32 , 64column : u32 , 65) ->bool { 66let ( filename, line, column) = 67crate :: modules:: map_source_location ( scope, filename, line, column) 68. unwrap_or_else ( ||( filename. to_owned (), line, column)); 69let filename = v8:: String :: new ( scope, & filename). unwrap (); 70let line = v8:: Integer :: new_from_unsigned ( scope, line); 71let column = v8:: Integer :: new_from_unsigned ( scope, column); 72call_boolean ( 73 scope, 740 , 75& [ error, filename. into (), line. into (), column. into ()], 76) 77} 78 79pub ( crate ) fn report_exception_for_value < ' s , ' i >( 80scope : & mut v8:: PinScope < ' s , ' i >, 81error : v8:: Local < ' s , v8:: Value >, 82) ->bool { 83let message = v8:: Exception :: create_message ( scope, error); 84let filename = message 85. get_script_resource_name ( scope) 86. map ( |name| name. to_rust_string_lossy ( scope)) 87. unwrap_or_default (); 88let line = message 89. get_line_number ( scope) 90. unwrap_or_default () 91. try_into () 92. unwrap_or_default (); 93let column = message 94. get_start_column () 95. saturating_add ( 1 ) 96. try_into () 97. unwrap_or_default (); 98report_exception_with_location ( scope, error, & filename, line, column) 99} 100 101pub ( crate ) fn report_nonfatal_exception < ' s >( 102scope : & mut v8:: PinScope < ' s , ' _ >, 103args : v8:: FunctionCallbackArguments < ' s >, 104_result : v8:: ReturnValue , 105) { 106let error = args. get ( 0 ); 107if report_exception_for_value ( scope, error) { 108return ; 109} 110 v8:: tc_scope!( let scope, scope); 111let stack = v8:: Local ::< v8:: Object >:: try_from ( error) 112. ok () 113. and_then ( |object|{ 114let key = v8:: String :: new ( scope, "stack" ) ?; 115 object. get ( scope, key. into ()) 116}) 117. filter ( |stack| !stack. is_undefined ()); 118// Hostile stack getters or formatters must not turn reporting into a new failure. 119 scope. reset (); 120let text = stack. unwrap_or ( error). to_rust_string_lossy ( scope); 121 scope. reset (); 122let _ =writeln! ( std:: io:: stderr (), "{text}" ); 123} 124 125pub ( crate ) fn suppress_exception ( scope : & mut v8:: PinScope , error : v8:: Local < v8:: Value >) { 126mark_processed_exception ( scope, error); 127} 128 129pub ( crate ) fn mark_processed_exception ( scope : & mut v8:: PinScope , error : v8:: Local < v8:: Value >) { 130* scope. get_slot ::< Processed >(). unwrap (). borrow_mut () =Some ( v8:: Global :: new ( scope, error)); 131} 132 133pub ( crate ) fn was_processed ( scope : & mut v8:: PinScope , error : v8:: Local < v8:: Value >) ->bool { 134let processed = scope. get_slot ::< Processed >(). unwrap (). clone (); 135let mut processed = processed. borrow_mut (); 136if processed 137. as_ref () 138. is_some_and ( |value| v8:: Local :: new ( scope, value) == error) 139{ 140 processed. take (); 141true 142} else { 143false 144} 145} 146 147pub ( crate ) fn clear_processed ( scope : & mut v8:: PinScope ) { 148 scope. get_slot ::< Processed >(). unwrap (). borrow_mut (). take (); 149} 150 151pub ( crate ) fn report_unhandled_rejection < ' s , ' i >( 152scope : & mut v8:: PinScope < ' s , ' i >, 153promise : v8:: Local < ' s , v8:: Promise >, 154reason : v8:: Local < ' s , v8:: Value >, 155) ->bool { 156call_boolean ( scope, 1 , & [ promise. into (), reason]) 157} 158 159pub ( crate ) fn report_rejection_handled < ' s , ' i >( 160scope : & mut v8:: PinScope < ' s , ' i >, 161promise : v8:: Local < ' s , v8:: Promise >, 162reason : v8:: Local < ' s , v8:: Value >, 163) { 164call ( scope, 2 , & [ promise. into (), reason]); 165} 166 167fn call_boolean < ' s , ' i >( 168scope : & mut v8:: PinScope < ' s , ' i >, 169index : usize , 170args : & [ v8:: Local < ' s , v8:: Value >], 171) ->bool { 172call ( scope, index, args). is_some_and ( |value| value. boolean_value ( scope)) 173} 174 175fn call < ' s , ' i >( 176scope : & mut v8:: PinScope < ' s , ' i >, 177index : usize , 178args : & [ v8:: Local < ' s , v8:: Value >], 179) ->Option < v8:: Local < ' s , v8:: Value >> { 180let handlers = scope. get_slot ::< Handlers >() ?. clone (); 181let handler = handlers. borrow (). as_ref () ?. get ( index) ?. clone (); 182let handler = v8:: Local :: new ( scope, & handler); 183 v8:: tc_scope!( let scope, scope); 184let result = handler. call ( scope, v8:: undefined ( scope). into (), args); 185if result. is_none () { 186 scope. reset (); 187} 188 result 189}