char/avril
(wip) why'd you have to go and make things so complicaaaaated?
git clone https://git.t4t.associates/char/avril
5553f00
main
1use std:: convert:: Infallible ; 2 3use avril_core::{ Extension , Op , v8}; 4use scoped_tls_hkt:: scoped_thread_local; 5use urlpattern::{ RegexSyntax , UrlPatternOptions , quirks, regexp:: RegExp }; 6 7// The parser's RegExp trait has no context parameter. Borrow the current op's evaluator 8// only for the synchronous parse, without retaining V8 handles or erasing scope lifetimes. 9type Evaluator < ' a > =dyn FnMut ( & str , & str , Option < & str >) ->Result < bool , ()> +' a ; 10scoped_thread_local! ( static mut EVALUATOR : for <' a >&' a mut Evaluator < ' a >); 11 12struct JsRegExp { 13source : String , 14flags : String , 15} 16 17impl RegExp for JsRegExp { 18fn syntax () ->RegexSyntax { 19RegexSyntax :: EcmaScript 20} 21 22fn parse ( source : & str , flags : & str , _force_eval : bool ) ->Result < Self , ()> { 23EVALUATOR . with ( |evaluate|evaluate ( source, flags, None )) ?; 24Ok ( Self { 25source : source. into (), 26flags : flags. into (), 27}) 28} 29 30fn matches < ' a >( & self , text : &' a str ) ->Option < Vec < Option < &' a str >>> { 31// During parsing, only the existence of a protocol match is used. 32EVALUATOR 33. with ( |evaluate|evaluate ( & self . source , & self . flags , Some ( text))) 34. ok () ? 35. then ( Vec :: new) 36} 37 38fn pattern_string ( & self ) ->& str { 39& self . source 40} 41} 42 43pub fn init () ->Extension { 44Extension { 45name : "ext:urlpattern" , 46dependencies : & [ "ext:web" ], 47ops : vec! [ 48Op :: with_scope ( 49"op_urlpattern_parse" , 50 |scope, 51( input, base, ignore_case): ( 52 quirks:: StringOrInit < ' static >, 53Option < String >, 54bool , 55) |{ 56let mut evaluate = |source : & str , flags : & str , text : Option < & str > |{ 57 v8:: tc_scope!( let scope, scope); 58let source = v8:: String :: new ( scope, source). ok_or (()) ?; 59let mut options = v8:: RegExpCreationFlags :: UNICODE_SETS ; 60if flags. contains ( 'i' ) { 61 options |= v8:: RegExpCreationFlags :: IGNORE_CASE ; 62} 63let regex = v8:: RegExp :: new ( scope, source, options). ok_or (()) ?; 64// V8's Exec API otherwise dispatches through the public exec property. 65let null = v8:: null ( scope). into (); 66 regex. set_prototype ( scope, null). ok_or (()) ?; 67match text{ 68Some ( text) =>{ 69let text = v8:: String :: new ( scope, text). ok_or (()) ?; 70Ok ( regex 71. exec ( scope, text) 72. is_some_and ( |result| !result. is_null ())) 73} 74None =>Ok ( true ), 75} 76}; 77let parsed =EVALUATOR . set ( & mut evaluate, ||{ 78let init =match input{ 79 quirks:: StringOrInit :: String ( input) =>{ 80let base = base 81. as_deref () 82. map ( url:: Url :: parse) 83. transpose () 84. map_err ( urlpattern:: Error :: Url ) ?; 85 urlpattern:: UrlPatternInit :: parse_constructor_string ::< JsRegExp >( 86& input, base, 87) ? 88} 89 input =>{ 90 quirks:: process_construct_pattern_input ( input, base. as_deref ()) ? 91} 92}; 93 urlpattern:: UrlPattern ::< JsRegExp >:: parse ( 94 init, 95UrlPatternOptions { 96regex_syntax : RegexSyntax :: EcmaScript , 97 ignore_case, 98}, 99) 100}); 101let parsed = parsed. and_then ( |pattern|{ 102let has_regexp_groups = pattern. has_regexp_groups (); 103let components =[ 104 pattern. protocol , 105 pattern. username , 106 pattern. password , 107 pattern. hostname , 108 pattern. port , 109 pattern. pathname , 110 pattern. search , 111 pattern. hash , 112] 113. into_iter () 114. map ( |c|{ 115let regex = c. regexp ?; 116let flags =if regex. flags . contains ( 'i' ) { "vi" } else { "v" }; 117Ok (( c. pattern_string , regex. source , c. group_name_list , flags)) 118}) 119. collect ::< Result < Vec < _ >, urlpattern:: Error >>() ?; 120Ok (( components, has_regexp_groups)) 121}); 122let ( pattern, error) =match parsed{ 123Ok ( pattern) =>( Some ( pattern), None ), 124Err ( error) =>( None , Some ( error. to_string ())), 125}; 126Ok ::< _ , Infallible >(( pattern, error)) 127}, 128), 129Op :: new ( 130"op_urlpattern_match_input" , 131 |( input, base): ( quirks:: StringOrInit < ' static >, Option < String >) |{ 132let parsed = quirks:: process_match_input ( input, base. as_deref ()); 133let ( input, error) =match parsed{ 134Ok ( input) =>( 135 input. and_then ( |( input, _) | quirks:: parse_match_input ( input)), 136None , 137), 138Err ( error) =>( None , Some ( error. to_string ())), 139}; 140Ok ::< _ , Infallible >(( input, error)) 141}, 142), 143], 144modules : & [( 145"ext:urlpattern/main.js" , 146include_str! ( concat! ( env! ( "OUT_DIR" ), "/urlpattern.js" )), 147)], 148entry_point : Some ( "ext:urlpattern/main.js" ), 149} 150}