char/avril
(wip) why'd you have to go and make things so complicaaaaated?
git clone https://git.t4t.associates/char/avril
81eaeb3
main
1use avril_core::{ Extension , Runtime , RuntimeOptions , v8}; 2 3fn collect_garbage ( 4scope : & mut v8:: PinScope , 5_args : v8:: FunctionCallbackArguments , 6_result : v8:: ReturnValue , 7) { 8 scope. low_memory_notification (); 9} 10 11fn runtime () ->Runtime { 12Runtime :: new ( RuntimeOptions { 13extensions : vec! [ Extension { 14name : "ext:test" , 15dependencies : & [], 16ops : vec! [], 17modules : & [( 18"ext:test/main.js" , 19r#" 20import {setEventHandlers} from 'ext:core/event_hooks'; 21import {enqueueMicrotask} from 'ext:core/microtasks'; 22globalThis.testQueueMicrotask = enqueueMicrotask; 23globalThis.reported = []; 24globalThis.cancelErrors = true; 25globalThis.captureRejections = true; 26globalThis.cancelRejections = true; 27globalThis.catchDuringUnhandled = false; 28setEventHandlers( 29(error, filename, line, column) => { 30reported.push(['error', error, filename, line, column]); 31return cancelErrors; 32}, 33(promise, reason) => { 34if (captureRejections) reported.push(['unhandled', promise, reason]); 35if (catchDuringUnhandled) { 36catchDuringUnhandled = false; 37promise.catch(() => {}); 38} 39return cancelRejections; 40}, 41(promise, reason) => reported.push(['handled', promise, reason]), 42); 43"# , 44)], 45entry_point : Some ( "ext:test/main.js" ), 46}], 47 ..Default :: default () 48}) 49. unwrap () 50} 51 52# [ test ] 53fn native_event_hooks_report_exceptions_and_late_rejections () { 54let mut runtime =runtime (); 55assert! ( 56 runtime 57. execute_script ::<()>( "direct.js" , "throw 'direct exception';" ) 58. is_err () 59); 60assert! ( runtime 61. execute_script ::< bool >( 62"direct-reported.js" , 63"reported.length === 1 && reported[0][0] === 'error' && reported[0][1] === 'direct exception'" , 64) 65. unwrap ()); 66 67 runtime 68. execute_script ::<()>( 69"same-turn.js" , 70r#" 71const handledBeforeReport = Promise.reject('same turn'); 72Promise.resolve().then(() => handledBeforeReport.catch(() => {})); 73testQueueMicrotask(() => {throw 'reported exception';}); 74testQueueMicrotask(() => {throw 'second reported exception';}); 75"# , 76) 77. unwrap (); 78assert! ( 79 runtime 80. execute_script ::< bool >( 81"first.js" , 82"reported.length === 3 && reported[1][0] === 'error' && reported[1][1] === 'reported exception' && reported[2][1] === 'second reported exception'" , 83) 84. unwrap () 85); 86 87let error = runtime 88. execute_script ::<()>( 89"fatal-errors.js" , 90"cancelErrors = false; testQueueMicrotask(() => {throw 'fatal first';}); testQueueMicrotask(() => {throw 'fatal second';});" , 91) 92. unwrap_err (); 93assert! ( error. to_string (). contains ( "fatal first" ), "{error}" ); 94assert! ( runtime 95. execute_script ::< bool >( 96"fatal-errors-reported.js" , 97"reported.length === 5 && reported[3][1] === 'fatal first' && reported[4][1] === 'fatal second'" , 98) 99. unwrap ()); 100 runtime 101. execute_script ::<()>( "enable-cancellation.js" , "cancelErrors = true;" ) 102. unwrap (); 103 104 runtime 105. execute_script ::<()>( 106"caught-in-unhandled-listener.js" , 107"catchDuringUnhandled = true; Promise.reject('caught in listener');" , 108) 109. unwrap (); 110assert! ( runtime 111. execute_script ::< bool >( 112"caught-in-unhandled-listener-reported.js" , 113"reported.length === 6 && reported[5][0] === 'unhandled' && reported.filter(event => event[0] === 'handled').length === 0" , 114) 115. unwrap ()); 116 117 runtime 118. execute_script ::<()>( 119"late.js" , 120"globalThis.reason = {}; globalThis.promise = Promise.reject(reason);" , 121) 122. unwrap (); 123assert! ( 124 runtime 125. execute_script ::< bool >( 126"unhandled.js" , 127"reported.length === 7 && reported[6][0] === 'unhandled' && reported[6][1] === promise && reported[6][2] === reason" , 128) 129. unwrap () 130); 131 132 runtime 133. execute_script ::<()>( "catch.js" , "promise.catch(() => {});" ) 134. unwrap (); 135assert! ( 136 runtime 137. execute_script ::< bool >( 138"handled.js" , 139"reported.length === 8 && reported[7][0] === 'handled' && reported[7][1] === promise && reported[7][2] === reason" , 140) 141. unwrap () 142); 143 144let error = runtime 145. execute_script ::<()>( 146"fatal-rejection.js" , 147"cancelRejections = false; Promise.reject('fatal rejection');" , 148) 149. unwrap_err (); 150assert! ( error. to_string (). contains ( "fatal rejection" ), "{error}" ); 151assert! ( runtime 152. execute_script ::< bool >( 153"fatal-rejection-reported.js" , 154"reported.length === 9 && reported[8][0] === 'unhandled' && reported[8][2] === 'fatal rejection'" , 155) 156. unwrap ()); 157 runtime 158. execute_script ::<()>( 159"enable-rejection-cancellation.js" , 160"cancelRejections = true;" , 161) 162. unwrap (); 163 164 runtime 165. register_module ( "test:gc" , |scope|{ 166let global = scope. get_current_context (). global ( scope); 167let collect = v8:: Function :: builder ( collect_garbage). build ( scope) ?; 168let key = v8:: String :: new ( scope, "collectGarbage" ) ?; 169 global. set ( scope, key. into (), collect. into ()); 170Some ( v8:: Object :: new ( scope)) 171}) 172. unwrap (); 173 runtime 174. execute_script ::<()>( 175"unretained-rejections.js" , 176"captureRejections = false; globalThis.promiseRefs = []; globalThis.reasonRefs = []; for (let i = 0; i < 256; i++) { const reason = {}; const promise = Promise.reject(reason); promiseRefs.push(new WeakRef(promise)); reasonRefs.push(new WeakRef(reason)); }" , 177) 178. unwrap (); 179 runtime 180. execute_script ::<()>( "collect.js" , "collectGarbage();" ) 181. unwrap (); 182let collected = runtime 183. execute_script ::< bool >( 184"collected.js" , 185"promiseRefs.every(reference => reference.deref() === undefined) && reasonRefs.every(reference => reference.deref() === undefined)" , 186) 187. unwrap (); 188assert! ( collected); 189}