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 std:: cell:: Cell ; 2use std:: convert:: Infallible ; 3use std:: rc:: Rc ; 4 5use avril_core::{ Extension , Op , Runtime , RuntimeOptions , v8}; 6 7fn runtime () ->Runtime { 8Runtime :: new ( RuntimeOptions { 9extensions : vec! [ Extension { 10name : "ext:test" , 11dependencies : & [], 12ops : vec! [], 13modules : & [( 14"ext:test/main.js" , 15"import {markPromiseHandled} from 'ext:core/promises'; globalThis.markPromiseHandled = markPromiseHandled;" , 16)], 17entry_point : Some ( "ext:test/main.js" ), 18}], 19 ..Default :: default () 20}) 21. unwrap () 22} 23 24# [ test ] 25fn marking_rejected_promises_clears_tracking_without_changing_their_results () { 26let mut runtime =runtime (); 27 runtime 28. execute_script ::<()>( 29"rejected" , 30r#" 31globalThis.reason = {failure: true}; 32globalThis.promise = Promise.reject(reason); 33if (markPromiseHandled(promise) !== undefined) throw Error('Unexpected result'); 34markPromiseHandled(promise); 35"# , 36) 37. unwrap (); 38 runtime 39. execute_script ::<()>( 40"observe" , 41"globalThis.observed = false; promise.catch(error => observed = error === reason);" , 42) 43. unwrap (); 44assert! ( 45 runtime 46. execute_script ::< bool >( "result" , "observed" ) 47. unwrap () 48); 49 runtime. run_event_loop (). unwrap (); 50} 51 52# [ test ] 53fn marking_pending_promises_suppresses_later_rejections_without_property_access () { 54let mut runtime =runtime (); 55 runtime 56. execute_script ::<()>( 57"pending" , 58r#" 59let reject; 60const promise = new Promise((resolve, failure) => reject = failure); 61const poison = () => {throw Error('Inspected promise property');}; 62Object.defineProperties(promise, { 63constructor: {get: poison}, 64then: {get: poison} 65}); 66markPromiseHandled(promise); 67Promise.resolve().then(() => reject('later failure')); 68"# , 69) 70. unwrap (); 71 runtime. run_event_loop (). unwrap (); 72} 73 74# [ test ] 75fn marking_one_promise_does_not_suppress_unrelated_rejections () { 76let mut runtime =runtime (); 77let error = runtime 78. execute_script ::<()>( 79"unrelated" , 80"Promise.reject('unrelated failure'); markPromiseHandled(Promise.reject('suppressed failure'));" , 81) 82. unwrap_err () 83. to_string (); 84assert! ( error. contains ( "unrelated failure" ), "{error}" ); 85 runtime. run_event_loop (). unwrap (); 86} 87 88# [ test ] 89fn marking_promises_does_not_allocate_derived_promises () { 90extern "C" fn created ( 91event : v8:: PromiseHookType , 92promise : v8:: Local < v8:: Promise >, 93_parent : v8:: Local < v8:: Value >, 94) { 95if event == v8:: PromiseHookType :: Init { 96// SAFETY: V8 supplies a valid promise belonging to the active isolate. 97 v8:: callback_scope!( unsafe scope, promise); 98let count = scope. get_slot ::< Rc < Cell < u32 >>>(). unwrap (); 99 count. set ( count. get () +1 ); 100} 101} 102 103let count =Rc :: new ( Cell :: new ( 0_u32 )); 104let counter = count. clone (); 105let mut runtime =Runtime :: new ( RuntimeOptions { 106extensions : vec! [ Extension { 107name : "ext:test" , 108dependencies : & [], 109ops : vec! [ Op :: with_scope ( "count_promises" , move |scope, (): () |{ 110 scope. set_slot ( counter. clone ()); 111 scope. set_promise_hook ( created); 112Ok ::< _ , Infallible >(()) 113})], 114modules : & [( 115"ext:test/main.js" , 116"import {markPromiseHandled} from 'ext:core/promises'; import {count_promises} from 'ext:core/ops'; globalThis.markPromiseHandled = markPromiseHandled; globalThis.countPromises = count_promises;" , 117)], 118entry_point : Some ( "ext:test/main.js" ), 119}], 120 ..Default :: default () 121}) 122. unwrap (); 123 runtime 124. execute_script ::<()>( 125"allocations" , 126r#" 127countPromises(null); 128const promises = [new Promise(() => {}), Promise.resolve(), Promise.reject('handled')]; 129for (const promise of promises) { 130markPromiseHandled(promise); 131markPromiseHandled(promise); 132} 133"# , 134) 135. unwrap (); 136assert_eq! ( count. get (), 3 ); 137} 138 139# [ test ] 140fn native_promise_handling_accepts_subclasses_but_rejects_impostors () { 141let mut runtime =runtime (); 142 runtime 143. execute_script ::<()>( 144"brands" , 145r#" 146class Derived extends Promise {} 147markPromiseHandled(Derived.resolve()); 148markPromiseHandled(Derived.reject('subclass failure')); 149for (const value of [ 150undefined, null, 42, {}, {then() {}}, 151Object.create(Promise.prototype), new Proxy(Promise.resolve(), {}) 152]) { 153try {markPromiseHandled(value); throw Error('Accepted impostor');} 154catch (error) {if (!(error instanceof TypeError)) throw error;} 155} 156try {new markPromiseHandled(Promise.resolve()); throw Error('Constructible helper');} 157catch (error) {if (!(error instanceof TypeError)) throw error;} 158"# , 159) 160. unwrap (); 161}