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:: Cell ; 2use std:: fs; 3use std:: io; 4use std:: path:: Path ; 5 6# [ path = "../../tests/support/mod.rs" ] 7mod support; 8 9use super ::{ Op , RegisteredOps }; 10 11fn ops ( seed : u32 ) ->Vec < Op > { 12let counter =Cell :: new ( seed); 13vec! [ 14Op :: new ( "next" , move |step : u32 |{ 15 counter. set ( counter. get () + step); 16Ok ::< _ , io:: Error >( counter. get ()) 17}), 18Op :: with_scope ( "read" , move |_, (): () |Ok ::< _ , io:: Error >( seed)), 19Op :: asynchronous ( "asyncRead" , move |offset : u32 |async move { 20Ok ::< _ , io:: Error >( seed + offset) 21}), 22Op :: asynchronous_unreferenced ( "unreferenced" , move |offset : u32 |async move { 23Ok ::< _ , io:: Error >( seed + offset) 24}), 25Op :: try_raw ( "fail" , move |_, _|{ 26Err ( io:: Error :: other ( format! ( "native {seed}" ))) 27}), 28Op :: raw ( "echo" , |_, args|Some ( args. get ( 0 ))), 29Op :: raw ( "invoke" , |scope, args|{ 30let callback = v8:: Local ::< v8:: Function >:: try_from ( args. get ( 0 )). ok () ?; 31 callback. call ( scope, v8:: undefined ( scope). into (), & []) 32}), 33] 34} 35 36fn evaluate < T : serde:: de:: DeserializeOwned >( scope : & mut v8:: PinScope , code : & str ) ->T { 37 v8:: tc_scope!( let scope, scope); 38let source = v8:: String :: new ( scope, code). unwrap (); 39let value = v8:: Script :: compile ( scope, source, None ). and_then ( |script| script. run ( scope)); 40let value = value. unwrap_or_else ( ||{ 41let exception = scope. exception (). unwrap (); 42panic! ( "{}" , exception. to_rust_string_lossy ( scope)); 43}); 44 serde_v8:: from_v8 ( scope, value). unwrap () 45} 46 47fn create_snapshot ( path : & Path ) { 48let ops =RegisteredOps :: new ( ops ( 700 )). unwrap (); 49let mut isolate = 50 v8:: Isolate :: snapshot_creator ( Some ( RegisteredOps :: external_references (). into ()), None ); 51 isolate. set_slot ( ops. clone ()); 52{ 53 v8:: scope!( let scope, & mut isolate); 54let context = v8:: Context :: new ( scope, Default :: default ()); 55let scope =& mut v8:: ContextScope :: new ( scope, context); 56let registry = ops. object ( scope). unwrap (); 57let key = v8:: String :: new ( scope, "ops" ). unwrap (); 58 context 59. global ( scope) 60. set ( scope, key. into (), registry. into ()) 61. unwrap (); 62evaluate ::<()>( 63 scope, 64r#" 65globalThis.saved = (() => { 66const {next, read, asyncRead, unreferenced, fail, echo, invoke} = ops; 67const built = [read(null), next(1)]; 68let calls = 0; 69return { 70built, read, 71run() { 72const marker = {}; 73if (echo(marker) !== marker) throw Error('Lost identity'); 74return [++calls, read(null), invoke(() => next(2))]; 75}, 76async runAsync() { 77return [await asyncRead(3), await unreferenced(4)]; 78}, 79errors() { 80const errors = []; 81try { fail(); } catch (error) { errors.push(error.message); } 82try { next('invalid'); } catch (error) { errors.push(error instanceof TypeError); } 83try { new echo(); } catch (error) { errors.push(error instanceof TypeError); } 84return errors; 85}, 86}; 87})(); 88delete globalThis.ops; 89"# , 90); 91assert_eq! ( evaluate ::< Vec < u32 >>( scope, "saved.run()" ), [ 1 , 700 , 703 ]); 92 scope. set_default_context ( context); 93} 94let snapshot = isolate. create_blob ( v8:: FunctionCodeHandling :: Keep ). unwrap (); 95assert! ( !snapshot. is_empty ()); 96 fs:: write ( path, &* snapshot). unwrap (); 97} 98 99fn restore_snapshot ( path : & Path , seed : u32 ) { 100let mut fresh_ops =ops ( seed); 101 fresh_ops. reverse (); 102let ops =RegisteredOps :: new ( fresh_ops). unwrap (); 103let params = v8:: Isolate :: create_params () 104. snapshot_blob ( fs:: read ( path). unwrap (). into ()) 105. external_references ( RegisteredOps :: external_references (). into ()); 106let mut isolate = v8:: Isolate :: new ( params); 107 isolate. set_microtasks_policy ( v8:: MicrotasksPolicy :: Explicit ); 108super :: init ( & mut isolate); 109crate :: reporting:: init ( & mut isolate); 110crate :: microtasks:: init ( & mut isolate); 111crate :: microtasks:: add_listener ( & mut isolate); 112crate :: tasks:: init ( & mut isolate); 113 v8:: scope!( let scope, & mut isolate); 114let context = v8:: Context :: new ( scope, Default :: default ()); 115let scope =& mut v8:: ContextScope :: new ( scope, context); 116 117// Neither the registry object nor the initialized JS is recreated after loading. 118assert_eq! ( evaluate ::< String >( scope, "typeof ops" ), "undefined" ); 119assert_eq! ( evaluate ::< Vec < u32 >>( scope, "saved.built" ), [ 700 , 701 ]); 120assert_eq! ( 121evaluate ::< String >( 122 scope, 123"try { saved.read(null); } catch (error) { error.message; }" 124), 125"Op is not registered in this isolate" , 126); 127 scope. set_slot ( ops); 128assert_eq! ( 129evaluate ::< Vec < u32 >>( scope, "saved.run()" ), 130[ 2 , seed, seed +2 ] 131); 132 scope. low_memory_notification (); 133assert_eq! ( 134evaluate ::< Vec < u32 >>( scope, "saved.run()" ), 135[ 3 , seed, seed +4 ] 136); 137assert_eq! ( 138evaluate ::< serde_json:: Value >( scope, "saved.errors()" ), 139 serde_json:: json!([ format! ( "native {seed}" ), true , true ]), 140); 141evaluate ::<()>( 142 scope, 143"saved.runAsync().then(value => globalThis.asyncResult = value); undefined" , 144); 145assert! ( super :: run_event_loop ( scope, None , true ). is_some ()); 146assert_eq! ( 147evaluate ::< Vec < u32 >>( scope, "asyncResult" ), 148[ seed +3 , seed +4 ] 149); 150} 151 152# [ test ] 153fn snapshot_round_trip_across_processes () { 154if let Some ( mode) = support:: role () { 155crate :: initialize_v8 ( crate :: Process :: Runtime ); 156let path = support:: directory (). join ( "ops.snapshot" ); 157match mode. as_str () { 158"create" =>create_snapshot ( & path), 159"restore" =>{ 160restore_snapshot ( & path, 10 ); 161restore_snapshot ( & path, 100 ); 162} 163 _ =>panic! ( "Unknown snapshot test mode: {mode}" ), 164} 165return ; 166} 167 168 support:: roles ( 169"op::tests::snapshot_round_trip_across_processes" , 170& [ "create" , "restore" ], 171); 172}