@@ -3162,6 +3162,16 @@ enum WaitRoute {
31623162 SameProcessFrame ( String ) ,
31633163}
31643164
3165+ fn wait_route ( state : & DaemonState ) -> WaitRoute {
3166+ match state. active_frame_id . as_deref ( ) {
3167+ Some ( frame_id) => match state. iframe_sessions . get ( frame_id) {
3168+ Some ( frame_session) => WaitRoute :: FrameSession ( frame_session. clone ( ) ) ,
3169+ None => WaitRoute :: SameProcessFrame ( frame_id. to_string ( ) ) ,
3170+ } ,
3171+ None => WaitRoute :: Main ,
3172+ }
3173+ }
3174+
31653175async fn handle_wait ( cmd : & Value , state : & mut DaemonState ) -> Result < Value , String > {
31663176 let mgr = state. browser . as_ref ( ) . ok_or ( "Browser not launched" ) ?;
31673177 let session_id = mgr. active_session_id ( ) ?. to_string ( ) ;
@@ -3170,13 +3180,7 @@ async fn handle_wait(cmd: &Value, state: &mut DaemonState) -> Result<Value, Stri
31703180 // Honor an active `frame <sel>` selection for content waits, like element
31713181 // resolution does: an OOPIF polls on its dedicated session, a same-process
31723182 // frame polls through the owner element's contentDocument.
3173- let frame_route = match state. active_frame_id . as_deref ( ) {
3174- Some ( frame_id) => match state. iframe_sessions . get ( frame_id) {
3175- Some ( frame_session) => WaitRoute :: FrameSession ( frame_session. clone ( ) ) ,
3176- None => WaitRoute :: SameProcessFrame ( frame_id. to_string ( ) ) ,
3177- } ,
3178- None => WaitRoute :: Main ,
3179- } ;
3183+ let frame_route = wait_route ( state) ;
31803184
31813185 if let Some ( text) = cmd. get ( "text" ) . and_then ( |v| v. as_str ( ) ) {
31823186 let quoted = serde_json:: to_string ( text) . unwrap_or_default ( ) ;
@@ -3225,37 +3229,20 @@ async fn handle_wait(cmd: &Value, state: &mut DaemonState) -> Result<Value, Stri
32253229 }
32263230
32273231 if let Some ( url_pattern) = cmd. get ( "url" ) . and_then ( |v| v. as_str ( ) ) {
3228- match & frame_route {
3229- WaitRoute :: Main => {
3230- wait_for_url ( & mgr. client , & session_id, url_pattern, timeout_ms) . await ?
3231- }
3232- WaitRoute :: FrameSession ( frame_session) => {
3233- wait_for_url ( & mgr. client , frame_session, url_pattern, timeout_ms) . await ?
3234- }
3235- WaitRoute :: SameProcessFrame ( frame_id) => {
3236- let check = url_check_expression ( "doc.location.href" , url_pattern) ;
3237- poll_in_frame_until_true ( & mgr. client , & session_id, frame_id, & check, timeout_ms)
3238- . await ?
3239- }
3240- }
3232+ wait_for_url_on_route (
3233+ & mgr. client ,
3234+ & session_id,
3235+ & frame_route,
3236+ url_pattern,
3237+ timeout_ms,
3238+ )
3239+ . await ?;
32413240 return Ok ( json ! ( { "waited" : "url" , "url" : url_pattern } ) ) ;
32423241 }
32433242
32443243 if let Some ( fn_str) = cmd. get ( "function" ) . and_then ( |v| v. as_str ( ) ) {
3245- match & frame_route {
3246- WaitRoute :: Main => {
3247- wait_for_function ( & mgr. client , & session_id, fn_str, timeout_ms) . await ?
3248- }
3249- WaitRoute :: FrameSession ( frame_session) => {
3250- wait_for_function ( & mgr. client , frame_session, fn_str, timeout_ms) . await ?
3251- }
3252- WaitRoute :: SameProcessFrame ( frame_id) => {
3253- let quoted = serde_json:: to_string ( fn_str) . unwrap_or_default ( ) ;
3254- let check = format ! ( "!!(doc.defaultView.eval({quoted}))" ) ;
3255- poll_in_frame_until_true ( & mgr. client , & session_id, frame_id, & check, timeout_ms)
3256- . await ?
3257- }
3258- }
3244+ wait_for_function_on_route ( & mgr. client , & session_id, & frame_route, fn_str, timeout_ms)
3245+ . await ?;
32593246 return Ok ( json ! ( { "waited" : "function" } ) ) ;
32603247 }
32613248
@@ -3506,6 +3493,25 @@ async fn wait_for_url(
35063493 poll_until_true ( client, session_id, & check_fn, timeout_ms) . await
35073494}
35083495
3496+ async fn wait_for_url_on_route (
3497+ client : & super :: cdp:: client:: CdpClient ,
3498+ session_id : & str ,
3499+ route : & WaitRoute ,
3500+ pattern : & str ,
3501+ timeout_ms : u64 ,
3502+ ) -> Result < ( ) , String > {
3503+ match route {
3504+ WaitRoute :: Main => wait_for_url ( client, session_id, pattern, timeout_ms) . await ,
3505+ WaitRoute :: FrameSession ( frame_session) => {
3506+ wait_for_url ( client, frame_session, pattern, timeout_ms) . await
3507+ }
3508+ WaitRoute :: SameProcessFrame ( frame_id) => {
3509+ let check = url_check_expression ( "doc.location.href" , pattern) ;
3510+ poll_in_frame_until_true ( client, session_id, frame_id, & check, timeout_ms) . await
3511+ }
3512+ }
3513+ }
3514+
35093515/// `wait --url` accepts the glob patterns the docs advertise ("**/dashboard")
35103516/// as well as plain substrings. A glob used to be matched literally via
35113517/// includes(), so it could never succeed.
@@ -3577,6 +3583,115 @@ async fn wait_for_function(
35773583 poll_until_true ( client, session_id, & check_fn, timeout_ms) . await
35783584}
35793585
3586+ async fn wait_for_function_on_route (
3587+ client : & super :: cdp:: client:: CdpClient ,
3588+ session_id : & str ,
3589+ route : & WaitRoute ,
3590+ fn_str : & str ,
3591+ timeout_ms : u64 ,
3592+ ) -> Result < ( ) , String > {
3593+ match route {
3594+ WaitRoute :: Main => wait_for_function ( client, session_id, fn_str, timeout_ms) . await ,
3595+ WaitRoute :: FrameSession ( frame_session) => {
3596+ wait_for_function ( client, frame_session, fn_str, timeout_ms) . await
3597+ }
3598+ WaitRoute :: SameProcessFrame ( frame_id) => {
3599+ let quoted = serde_json:: to_string ( fn_str) . unwrap_or_default ( ) ;
3600+ let check = format ! ( "!!(doc.defaultView.eval({quoted}))" ) ;
3601+ poll_in_frame_until_true ( client, session_id, frame_id, & check, timeout_ms) . await
3602+ }
3603+ }
3604+ }
3605+
3606+ async fn evaluate_wait_expression_on_session (
3607+ client : & super :: cdp:: client:: CdpClient ,
3608+ session_id : & str ,
3609+ expression : & str ,
3610+ ) -> Result < Value , String > {
3611+ let result: super :: cdp:: types:: EvaluateResult = client
3612+ . send_command_typed (
3613+ "Runtime.evaluate" ,
3614+ & super :: cdp:: types:: EvaluateParams {
3615+ expression : format ! ( "({})" , expression) ,
3616+ return_by_value : Some ( true ) ,
3617+ await_promise : Some ( true ) ,
3618+ } ,
3619+ Some ( session_id) ,
3620+ )
3621+ . await ?;
3622+
3623+ if let Some ( details) = result. exception_details {
3624+ let msg = details
3625+ . exception
3626+ . as_ref ( )
3627+ . and_then ( |e| e. description . as_deref ( ) )
3628+ . unwrap_or ( & details. text ) ;
3629+ return Err ( format ! ( "Evaluation error: {}" , msg) ) ;
3630+ }
3631+
3632+ Ok ( result. result . value . unwrap_or ( Value :: Null ) )
3633+ }
3634+
3635+ async fn evaluate_wait_expression_on_route (
3636+ client : & super :: cdp:: client:: CdpClient ,
3637+ session_id : & str ,
3638+ route : & WaitRoute ,
3639+ expression : & str ,
3640+ ) -> Result < Value , String > {
3641+ match route {
3642+ WaitRoute :: Main => {
3643+ evaluate_wait_expression_on_session ( client, session_id, expression) . await
3644+ }
3645+ WaitRoute :: FrameSession ( frame_session) => {
3646+ evaluate_wait_expression_on_session ( client, frame_session, expression) . await
3647+ }
3648+ WaitRoute :: SameProcessFrame ( frame_id) => {
3649+ evaluate_in_same_process_frame ( client, session_id, frame_id, expression) . await
3650+ }
3651+ }
3652+ }
3653+
3654+ async fn current_url_on_route (
3655+ client : & super :: cdp:: client:: CdpClient ,
3656+ session_id : & str ,
3657+ route : & WaitRoute ,
3658+ ) -> Result < String , String > {
3659+ match route {
3660+ WaitRoute :: Main => evaluate_wait_expression_on_session ( client, session_id, "location.href" )
3661+ . await
3662+ . map ( |v| v. as_str ( ) . unwrap_or ( "" ) . to_string ( ) ) ,
3663+ WaitRoute :: FrameSession ( frame_session) => {
3664+ evaluate_wait_expression_on_session ( client, frame_session, "location.href" )
3665+ . await
3666+ . map ( |v| v. as_str ( ) . unwrap_or ( "" ) . to_string ( ) )
3667+ }
3668+ WaitRoute :: SameProcessFrame ( frame_id) => {
3669+ let owner_object_id =
3670+ super :: element:: frame_owner_object_id ( client, session_id, frame_id) . await ?;
3671+ let result = client
3672+ . send_command (
3673+ "Runtime.callFunctionOn" ,
3674+ Some ( json ! ( {
3675+ "objectId" : owner_object_id,
3676+ "functionDeclaration" : "function() {
3677+ const doc = this.contentDocument;
3678+ return doc ? doc.location.href : '';
3679+ }" ,
3680+ "returnByValue" : true ,
3681+ } ) ) ,
3682+ Some ( session_id) ,
3683+ )
3684+ . await ?;
3685+ Ok ( result
3686+ . get ( "result" )
3687+ . and_then ( |r| r. get ( "value" ) )
3688+ . and_then ( |v| v. as_str ( ) )
3689+ . unwrap_or ( "" )
3690+ . to_string ( ) )
3691+ }
3692+ }
3693+ }
3694+
35803695/// wait_for_selector inside a same-process iframe selected via `frame <sel>`.
35813696async fn wait_for_selector_in_frame (
35823697 client : & super :: cdp:: client:: CdpClient ,
@@ -5836,14 +5951,24 @@ async fn handle_screencast_stop(state: &mut DaemonState) -> Result<Value, String
58365951async fn handle_waitforurl ( cmd : & Value , state : & DaemonState ) -> Result < Value , String > {
58375952 let mgr = state. browser . as_ref ( ) . ok_or ( "Browser not launched" ) ?;
58385953 let session_id = mgr. active_session_id ( ) ?. to_string ( ) ;
5954+ let frame_route = wait_route ( state) ;
58395955 let url_pattern = cmd
58405956 . get ( "url" )
58415957 . and_then ( |v| v. as_str ( ) )
58425958 . ok_or ( "Missing 'url' parameter" ) ?;
58435959 let timeout_ms = state. timeout_ms ( cmd) ;
58445960
5845- wait_for_url ( & mgr. client , & session_id, url_pattern, timeout_ms) . await ?;
5846- let url = mgr. get_url ( ) . await . unwrap_or_default ( ) ;
5961+ wait_for_url_on_route (
5962+ & mgr. client ,
5963+ & session_id,
5964+ & frame_route,
5965+ url_pattern,
5966+ timeout_ms,
5967+ )
5968+ . await ?;
5969+ let url = current_url_on_route ( & mgr. client , & session_id, & frame_route)
5970+ . await
5971+ . unwrap_or_default ( ) ;
58475972 Ok ( json ! ( { "url" : url } ) )
58485973}
58495974
@@ -5867,28 +5992,27 @@ async fn handle_waitforloadstate(cmd: &Value, state: &DaemonState) -> Result<Val
58675992async fn handle_waitforfunction ( cmd : & Value , state : & DaemonState ) -> Result < Value , String > {
58685993 let mgr = state. browser . as_ref ( ) . ok_or ( "Browser not launched" ) ?;
58695994 let session_id = mgr. active_session_id ( ) ?. to_string ( ) ;
5995+ let frame_route = wait_route ( state) ;
58705996 let expression = cmd
58715997 . get ( "expression" )
58725998 . and_then ( |v| v. as_str ( ) )
58735999 . ok_or ( "Missing 'expression' parameter" ) ?;
58746000 let timeout_ms = state. timeout_ms ( cmd) ;
58756001
5876- wait_for_function ( & mgr. client , & session_id, expression, timeout_ms) . await ?;
6002+ wait_for_function_on_route (
6003+ & mgr. client ,
6004+ & session_id,
6005+ & frame_route,
6006+ expression,
6007+ timeout_ms,
6008+ )
6009+ . await ?;
58776010
5878- let result: super :: cdp:: types:: EvaluateResult = mgr
5879- . client
5880- . send_command_typed (
5881- "Runtime.evaluate" ,
5882- & super :: cdp:: types:: EvaluateParams {
5883- expression : format ! ( "({})" , expression) ,
5884- return_by_value : Some ( true ) ,
5885- await_promise : Some ( true ) ,
5886- } ,
5887- Some ( & session_id) ,
5888- )
5889- . await ?;
6011+ let result =
6012+ evaluate_wait_expression_on_route ( & mgr. client , & session_id, & frame_route, expression)
6013+ . await ?;
58906014
5891- Ok ( json ! ( { "result" : result. result . value . unwrap_or ( Value :: Null ) } ) )
6015+ Ok ( json ! ( { "result" : result } ) )
58926016}
58936017
58946018// ---------------------------------------------------------------------------
0 commit comments