From b20ff14ff9bf81beff9bbfe9da26263a1dd1cf29 Mon Sep 17 00:00:00 2001 From: ldm0 Date: Thu, 12 Nov 2026 03:01:13 +0800 Subject: [PATCH] refactor(inspector): derive response IDs and make parsing explicit --- moli-core/src/page/mod.rs | 23 +++--- moli-core/src/runtime/tests.rs | 2 +- moli-inspector-json/src/lib.rs | 7 -- .../src/cdp_frontend_router/routing/output.rs | 5 +- .../src/cdp_frontend_router/routing/tests.rs | 47 ++++++------ .../routing/tests/target_message.rs | 38 +++++----- moli-protocol/src/conn/output.rs | 26 +++---- moli-protocol/src/conn/runtime_eval.rs | 2 +- .../conn/runtime_eval/inspector_routing.rs | 18 +++-- .../conn/state/devtools_renderer_channel.rs | 1 + .../domains/runtime/dispatcher/dispatch.rs | 45 ++++++++++-- moli-protocol/src/domains/runtime/native.rs | 6 +- moli-renderer-v8/src/lib.rs | 32 ++++----- moli-renderer-v8/src/runtime/mod.rs | 27 ++++--- moli-renderer-v8/src/runtime/page_dom.rs | 8 +-- moli-renderer-v8/src/runtime/page_surface.rs | 71 ++++--------------- .../tests/extracted/runtime_scripts.rs | 22 +++--- .../src/script_vm/inspector/agent_sessions.rs | 15 ++-- .../src/script_vm/inspector/tests.rs | 26 ++++++- .../src/service_worker_runtime/service.rs | 2 +- .../host_target_output.rs | 2 +- .../src/worker/thread/runtime_inspector.rs | 2 +- 22 files changed, 219 insertions(+), 208 deletions(-) diff --git a/moli-core/src/page/mod.rs b/moli-core/src/page/mod.rs index 1f6d092a6b..1d311e9b65 100644 --- a/moli-core/src/page/mod.rs +++ b/moli-core/src/page/mod.rs @@ -126,18 +126,17 @@ pub use moli_renderer_v8::{ RendererRuntimeInspectorIoCommandClaim, RendererRuntimeInspectorIoCommandRoute, RendererRuntimeInspectorMainCommandCompletion, RendererRuntimeInspectorMainCommandRoute, RendererRuntimeInspectorMessage, RendererRuntimeInspectorMessageBatch, - RendererRuntimeInspectorProtocolMessage, RendererRuntimeInspectorProtocolMessageValueMut, - RendererRuntimeObservableSourceItem, RendererRuntimeObservableSourceSummary, - RendererRuntimeRealmInfo, RendererScreenshotClip, RendererScreenshotFormat, - RendererScreenshotRegion, RendererScrollIntoViewResult, RendererServiceWorkerConsoleMessage, - RendererServiceWorkerExceptionMessage, RendererServiceWorkerFetchDiagnostic, - RendererServiceWorkerFetchDiagnosticResult, RendererServiceWorkerRunIdentity, - RendererServiceWorkerTargetEvent, RendererServiceWorkerTargetInfo, - RendererServiceWorkerVersionStatus, RendererSetDocumentContentResult, - RendererSharedWorkerConsoleMessage, RendererSharedWorkerTargetEvent, - RendererSharedWorkerTargetInfo, RendererSyntheticResponseBody, RendererTextSearchMatch, - RendererTouchPoint, RendererVisualStateToken, RendererWindowDocumentSource, - RuntimeConsoleMessageSnapshot, WorkerInspectorError, + RendererRuntimeInspectorProtocolMessage, RendererRuntimeObservableSourceItem, + RendererRuntimeObservableSourceSummary, RendererRuntimeRealmInfo, RendererScreenshotClip, + RendererScreenshotFormat, RendererScreenshotRegion, RendererScrollIntoViewResult, + RendererServiceWorkerConsoleMessage, RendererServiceWorkerExceptionMessage, + RendererServiceWorkerFetchDiagnostic, RendererServiceWorkerFetchDiagnosticResult, + RendererServiceWorkerRunIdentity, RendererServiceWorkerTargetEvent, + RendererServiceWorkerTargetInfo, RendererServiceWorkerVersionStatus, + RendererSetDocumentContentResult, RendererSharedWorkerConsoleMessage, + RendererSharedWorkerTargetEvent, RendererSharedWorkerTargetInfo, RendererSyntheticResponseBody, + RendererTextSearchMatch, RendererTouchPoint, RendererVisualStateToken, + RendererWindowDocumentSource, RuntimeConsoleMessageSnapshot, WorkerInspectorError, }; pub use moli_renderer_v8::{ RendererAppManifest, RendererAppManifestDisplayMode, RendererAppManifestError, diff --git a/moli-core/src/runtime/tests.rs b/moli-core/src/runtime/tests.rs index 2169be4a27..23485b3f5c 100644 --- a/moli-core/src/runtime/tests.rs +++ b/moli-core/src/runtime/tests.rs @@ -5597,7 +5597,7 @@ fn runtime_protocol_response_by_id( ) -> Option<&serde_json::Value> { messages.iter().find_map(|message| match message { RendererRuntimeInspectorMessage::Protocol(value) - if value.get("id").and_then(serde_json::Value::as_i64) == Some(response_id) => + if value.payload().id_i64() == Some(response_id) => { Some(value.value()) } diff --git a/moli-inspector-json/src/lib.rs b/moli-inspector-json/src/lib.rs index 4a15ab593b..303b4c4133 100644 --- a/moli-inspector-json/src/lib.rs +++ b/moli-inspector-json/src/lib.rs @@ -13,7 +13,6 @@ use serde_json::{Number, Value, value::RawValue}; use std::{ collections::BTreeMap, fmt, - ops::Deref, sync::{Arc, OnceLock}, }; @@ -336,12 +335,6 @@ impl From for InspectorJson { Self::Parsed(value) } } -impl Deref for InspectorJson { - type Target = Value; - fn deref(&self) -> &Value { - self.value() - } -} impl Serialize for InspectorJson { fn serialize(&self, serializer: S) -> Result { match self { diff --git a/moli-protocol-server/src/cdp_frontend_router/routing/output.rs b/moli-protocol-server/src/cdp_frontend_router/routing/output.rs index 04a5a98bc7..eeb501f52b 100644 --- a/moli-protocol-server/src/cdp_frontend_router/routing/output.rs +++ b/moli-protocol-server/src/cdp_frontend_router/routing/output.rs @@ -40,6 +40,7 @@ impl CdpFrontendRoutingState { flattened_protocol, } => { if let Some(child_session_id) = message + .value() .pointer("/result/sessionId") .and_then(Value::as_str) .map(str::to_owned) @@ -77,11 +78,11 @@ impl CdpFrontendRoutingState { let target_event_session_id = method .as_deref() .filter(|method| method.starts_with("Target.")) - .and_then(|_| message.pointer("/params/sessionId")) + .and_then(|_| message.value().pointer("/params/sessionId")) .and_then(Value::as_str) .map(str::to_owned); let target_event_target_id = (method.as_deref() == Some("Target.attachedToTarget")) - .then(|| message.pointer("/params/targetInfo/targetId")) + .then(|| message.value().pointer("/params/targetInfo/targetId")) .flatten() .and_then(Value::as_str) .map(str::to_owned); diff --git a/moli-protocol-server/src/cdp_frontend_router/routing/tests.rs b/moli-protocol-server/src/cdp_frontend_router/routing/tests.rs index e04fc8b5bf..483f30b294 100644 --- a/moli-protocol-server/src/cdp_frontend_router/routing/tests.rs +++ b/moli-protocol-server/src/cdp_frontend_router/routing/tests.rs @@ -126,8 +126,8 @@ fn browser_and_page_client_command_ids_are_isolated_and_restored() { ) .expect("route browser response"); assert_eq!(browser_frontend.frontend_id, 5); - assert_eq!(browser_response["id"], json!(7)); - assert!(browser_response.get("sessionId").is_none()); + assert_eq!(browser_response.id_u64(), Some(7)); + assert!(browser_response.session_id().is_none()); let (page_frontend, page_response) = routing .route_message( @@ -141,8 +141,8 @@ fn browser_and_page_client_command_ids_are_isolated_and_restored() { ) .expect("route page response"); assert_eq!(page_frontend.frontend_id, 10); - assert_eq!(page_response["id"], json!(7)); - assert!(page_response.get("sessionId").is_none()); + assert_eq!(page_response.id_u64(), Some(7)); + assert!(page_response.session_id().is_none()); } #[test] @@ -187,9 +187,9 @@ fn browser_frontends_with_the_same_client_command_id_route_independently() { ) .expect("route second response"); assert_eq!(frontend.frontend_id(), 6); - assert_eq!(response["id"], json!(7)); - assert_eq!(response["result"]["product"], json!("second")); - assert!(response.get("sessionId").is_none()); + assert_eq!(response.id_u64(), Some(7)); + assert_eq!(response.value()["result"]["product"], json!("second")); + assert!(response.session_id().is_none()); let (frontend, response) = routing .route_message( @@ -203,9 +203,9 @@ fn browser_frontends_with_the_same_client_command_id_route_independently() { ) .expect("route first response"); assert_eq!(frontend.frontend_id(), 5); - assert_eq!(response["id"], json!(7)); - assert_eq!(response["result"]["product"], json!("first")); - assert!(response.get("sessionId").is_none()); + assert_eq!(response.id_u64(), Some(7)); + assert_eq!(response.value()["result"]["product"], json!("first")); + assert!(response.session_id().is_none()); } #[test] @@ -230,7 +230,7 @@ fn browser_base_session_events_are_private_and_frontend_scoped() { ) .expect("route first browser event"); assert_eq!(frontend.frontend_id(), 5); - assert!(event.get("sessionId").is_none()); + assert!(event.session_id().is_none()); assert!( routing @@ -273,7 +273,7 @@ fn root_detach_with_a_known_child_routes_to_its_exact_frontend() { ) .expect("route owner-qualified root detach"); assert_eq!(frontend.frontend_id(), 5); - assert!(event.get("sessionId").is_none()); + assert!(event.session_id().is_none()); assert!(matches!( routing.prepare_command( @@ -333,7 +333,7 @@ fn root_detach_restores_visible_parent_for_nested_child() { None, ) .expect("route nested root detach"); - assert_eq!(event["sessionId"], json!("SID-child")); + assert_eq!(event.session_id(), Some("SID-child")); } #[test] @@ -397,7 +397,7 @@ fn unregistering_one_browser_drops_only_its_pending_commands() { ) .expect("second browser response remains routable"); assert_eq!(frontend.frontend_id(), 6); - assert_eq!(response["id"], json!(1)); + assert_eq!(response.id_u64(), Some(1)); } #[test] @@ -444,7 +444,7 @@ fn browser_child_session_is_preserved_on_browser_frontend() { None, ) .expect("route child response"); - assert_eq!(response["sessionId"], json!("SID-client-child")); + assert_eq!(response.session_id(), Some("SID-client-child")); } #[test] @@ -779,8 +779,8 @@ fn attached_event_registers_child_before_attach_response() { ) .expect("route attached event"); assert_eq!(frontend.frontend_id(), 5); - assert!(event.get("sessionId").is_none()); - assert_eq!(event["params"]["sessionId"], json!("SID-child")); + assert!(event.session_id().is_none()); + assert_eq!(event.value()["params"]["sessionId"], json!("SID-child")); let child_command = expect_prepared_command( routing.prepare_command( @@ -813,8 +813,8 @@ fn attached_event_registers_child_before_attach_response() { None, ) .expect("route attach response"); - assert_eq!(response["id"], json!(30)); - assert!(response.get("sessionId").is_none()); + assert_eq!(response.id_u64(), Some(30)); + assert!(response.session_id().is_none()); } #[test] @@ -847,8 +847,8 @@ fn browser_frontend_hides_base_session_on_wire() { None, ) .expect("route browser response"); - assert_eq!(response["id"], json!(9)); - assert!(response.get("sessionId").is_none()); + assert_eq!(response.id_u64(), Some(9)); + assert!(response.session_id().is_none()); } #[test] @@ -975,7 +975,10 @@ fn private_page_session_detach_does_not_fall_back_to_browser_frontend() { ) .expect("route browser-owned target detach"); assert_eq!(frontend.frontend_id, 5); - assert_eq!(message["params"]["sessionId"], json!("SID-browser-child")); + assert_eq!( + message.value()["params"]["sessionId"], + json!("SID-browser-child") + ); } #[test] diff --git a/moli-protocol-server/src/cdp_frontend_router/routing/tests/target_message.rs b/moli-protocol-server/src/cdp_frontend_router/routing/tests/target_message.rs index f37727802b..36c7bd36e8 100644 --- a/moli-protocol-server/src/cdp_frontend_router/routing/tests/target_message.rs +++ b/moli-protocol-server/src/cdp_frontend_router/routing/tests/target_message.rs @@ -83,9 +83,9 @@ fn legacy_transport_admits_actual_command_and_routes_its_background_reply_once() .route_message(background.clone(), Some("SID-page-1"), None) .unwrap(); assert_eq!(frontend.frontend_id(), 5); - assert!(event.get("sessionId").is_none()); + assert!(event.session_id().is_none()); assert_eq!( - unwrap_message(&event, "SID-page-1"), + unwrap_message(event.value(), "SID-page-1"), json!({"id":42,"result":{"loaderId":"LID-1"}}) ); assert!( @@ -132,7 +132,7 @@ fn recursive_transport_preserves_ack_paths_and_explicit_payload_session() { None, ) .unwrap(); - let inner = unwrap_message(&response, "SID-page-1"); + let inner = unwrap_message(response.value(), "SID-page-1"); assert!(inner.get("sessionId").is_none()); assert_eq!( unwrap_message(&inner, "SID-worker"), @@ -163,9 +163,9 @@ fn transport_with_explicit_carrier_keeps_only_that_carrier_on_outer_event() { let (_, response) = routing .route_message(json!({"id":command.request().id(),"result":{}}), None, None) .unwrap(); - assert_eq!(response["sessionId"], "SID-page-1"); + assert_eq!(response.session_id(), Some("SID-page-1")); assert_eq!( - unwrap_message(&response, "SID-worker"), + unwrap_message(response.value(), "SID-worker"), json!({"id":42,"result":{}}) ); } @@ -247,7 +247,7 @@ fn nested_attach_keeps_normal_registration_and_disconnect_retires_pending_reply( ) .unwrap(); assert_eq!( - unwrap_message(&response, "SID-page-1"), + unwrap_message(response.value(), "SID-page-1"), json!({"id":42,"result":{"sessionId":"SID-other"}}) ); let (_, command) = target_command( @@ -286,7 +286,7 @@ fn root_received_target_event_uses_owning_frontend_and_parent_carrier() { "method":"Target.receivedMessageFromTarget","params":{"sessionId":session,"message":"{}"}, }),None, None).unwrap(); assert_eq!(frontend.frontend_id(), 5); - assert_eq!(response.get("sessionId").and_then(Value::as_str), parent); + assert_eq!(response.session_id(), parent); } assert!(routing.route_message(json!({"method":"Target.receivedMessageFromTarget","params":{"sessionId":"SID-missing","message":"{}"}}),None, None).is_none()); } @@ -306,7 +306,7 @@ fn nonflat_attachment_routes_events_before_and_after_reply_without_losing_parent Some(false), ) .unwrap(); - assert_eq!(attached["sessionId"], "SID-page-1"); + assert_eq!(attached.session_id(), Some("SID-page-1")); let enable = expect_prepared_command( routing.prepare_command( 5, @@ -335,18 +335,18 @@ fn nonflat_attachment_routes_events_before_and_after_reply_without_losing_parent None, ) .unwrap(); - assert_eq!(event["sessionId"], "SID-page-1"); + assert_eq!(event.session_id(), Some("SID-page-1")); assert_eq!( - unwrap_message(&event, "SID-nonflat"), + unwrap_message(event.value(), "SID-nonflat"), json!({"method":method,"params":params}) ); if method == "Runtime.executionContextCreated" { let (_, reply) = routing .route_message(json!({"id":enable.request().id(),"result":{}}), None, None) .unwrap(); - assert_eq!(reply["sessionId"], "SID-page-1"); + assert_eq!(reply.session_id(), Some("SID-page-1")); assert_eq!( - unwrap_message(&reply, "SID-nonflat"), + unwrap_message(reply.value(), "SID-nonflat"), json!({"id":80,"result":{}}) ); } @@ -382,8 +382,8 @@ fn nonflat_attachment_routes_events_before_and_after_reply_without_losing_parent None, ) .unwrap(); - assert_eq!(reply["sessionId"], "SID-page-1"); - assert_eq!(unwrap_message(&reply, "SID-nonflat")["id"], 81); + assert_eq!(reply.session_id(), Some("SID-page-1")); + assert_eq!(unwrap_message(reply.value(), "SID-nonflat")["id"], 81); } #[test] @@ -401,8 +401,8 @@ fn mixed_flat_and_nonflat_ancestors_share_one_event_and_response_encoder() { let (_, event) = routing.route_message(json!({ "method":"Runtime.executionContextCreated","sessionId":"SID-inner","params":{"context":{"id":3}}, }), Some("SID-inner"), None).unwrap(); - assert!(event.get("sessionId").is_none()); - let middle = unwrap_message(&event, "SID-outer"); + assert!(event.session_id().is_none()); + let middle = unwrap_message(event.value(), "SID-outer"); assert_eq!(middle["sessionId"], "SID-flat"); let inner = unwrap_message(&middle, "SID-inner"); assert!(inner.get("sessionId").is_none()); @@ -415,7 +415,7 @@ fn mixed_flat_and_nonflat_ancestors_share_one_event_and_response_encoder() { ) .unwrap(); assert_eq!( - unwrap_message(&flat_event, "SID-outer")["sessionId"], + unwrap_message(flat_event.value(), "SID-outer")["sessionId"], "SID-flat" ); let (_, detached) = routing @@ -426,7 +426,7 @@ fn mixed_flat_and_nonflat_ancestors_share_one_event_and_response_encoder() { ) .unwrap(); assert_eq!( - unwrap_message(&detached, "SID-outer")["sessionId"], + unwrap_message(detached.value(), "SID-outer")["sessionId"], "SID-flat" ); assert!(routing.frontends.session("SID-inner").is_none()); @@ -464,7 +464,7 @@ fn nested_target_commands_share_implicit_session_policy_with_the_adapter() { let (_, wrapped) = routing .route_message(json!({"id":command.request().id(),"result":{}}), None, None) .unwrap(); - let reply = unwrap_message(&wrapped, "SID-page-1"); + let reply = unwrap_message(wrapped.value(), "SID-page-1"); assert_eq!(reply["id"], 42); assert_eq!(reply.get("sessionId").and_then(Value::as_str), explicit); } diff --git a/moli-protocol/src/conn/output.rs b/moli-protocol/src/conn/output.rs index 73901a55a0..90a3dda32c 100644 --- a/moli-protocol/src/conn/output.rs +++ b/moli-protocol/src/conn/output.rs @@ -236,12 +236,12 @@ impl RuntimeInspectorResponseReady { Ok(completion) => { let message = runtime_command_output_response_message(&completion.output, completion.call_id) - .cloned() - .unwrap_or_else(|| Value::Null.into()); + .map(InspectorJson::value) + .unwrap_or(&Value::Null); let payload = runtime_inspector_mismatched_completion_payload( command_id, completion.call_id, - &message, + message, ); ( completion.renderer_agent_attachment_id(), @@ -287,12 +287,12 @@ impl RuntimeInspectorResponseReady { Ok(completion) => { let message = runtime_command_output_response_message(&completion.output, completion.call_id) - .cloned() - .unwrap_or_else(|| Value::Null.into()); + .map(InspectorJson::value) + .unwrap_or(&Value::Null); runtime_inspector_mismatched_completion_payload( self.frontend_command_id.get(), completion.call_id, - &message, + message, ) } Err(message) => BackgroundCommandResponsePayload::internal_error(message.to_string()), @@ -3077,10 +3077,10 @@ impl ProtocolDeliveryEnvelope { ) -> bool { match &self.payload { BackgroundProtocolEventPayload::Protocol(event) => { - event.message["method"] == json!("Console.messageAdded") - && event.message["params"]["message"]["source"] == json!(source) - && event.message["params"]["message"]["level"] == json!(level) - && event.message["params"]["message"]["text"] == json!(text) + event.message.method() == Some("Console.messageAdded") + && event.message.value()["params"]["message"]["source"] == json!(source) + && event.message.value()["params"]["message"]["level"] == json!(level) + && event.message.value()["params"]["message"]["text"] == json!(text) } BackgroundProtocolEventPayload::ConsoleMessageAdded(event) => { event.source == source && event.level == level && event.text == text @@ -5960,10 +5960,10 @@ mod tests { }}); assert!(InspectorJson::from_slice(host.to_string().as_bytes()).is_err()); let wire = BackgroundProtocolEvent::immediate(host).into_cdp_message(); - assert_eq!(wire["params"]["requestId"], "public-id"); + assert_eq!(wire.value()["params"]["requestId"], "public-id"); for key in PRIVATE_PROTOCOL_PARAM_FIELDS { assert_eq!( - wire["params"].get(*key).is_some(), + wire.value()["params"].get(*key).is_some(), method == "Fetch.requestPaused" && *key == "__moliBlockedInterceptors" ); } @@ -5974,7 +5974,7 @@ mod tests { .unwrap(); inspector.value_mut()["params"]["__moliFetchRequestId"] = json!("private-id"); let wire = BackgroundProtocolEvent::immediate(inspector).into_cdp_message(); - assert!(wire["params"].get("__moliFetchRequestId").is_none()); + assert!(wire.value()["params"].get("__moliFetchRequestId").is_none()); let inspector = InspectorJson::from_slice( br#"{"method":"Runtime.consoleAPICalled","params":{"args":[{"value":{"__moliFetchRequestId":"\ud800"}}]}}"#, ) diff --git a/moli-protocol/src/conn/runtime_eval.rs b/moli-protocol/src/conn/runtime_eval.rs index 1fb049c521..29995c462c 100644 --- a/moli-protocol/src/conn/runtime_eval.rs +++ b/moli-protocol/src/conn/runtime_eval.rs @@ -199,7 +199,7 @@ fn runtime_inspector_frontend_response( let RendererRuntimeInspectorMessage::Protocol(message) = message else { return None; }; - (message.get("id").and_then(Value::as_u64) == Some(command_id)).then(|| message.value()) + (message.payload().id_u64() == Some(command_id)).then(|| message.value()) }) } diff --git a/moli-protocol/src/conn/runtime_eval/inspector_routing.rs b/moli-protocol/src/conn/runtime_eval/inspector_routing.rs index c310ba8bc0..f095cc7a36 100644 --- a/moli-protocol/src/conn/runtime_eval/inspector_routing.rs +++ b/moli-protocol/src/conn/runtime_eval/inspector_routing.rs @@ -202,7 +202,10 @@ impl CdpConnection { ); } if Some(id) == current_cmd_id { - self.register_runtime_remote_object_ids_from_value_for_owner(owner, &message); + self.register_runtime_remote_object_ids_from_value_for_owner( + owner, + message.value(), + ); if matches!(message, InspectorJson::Raw(_)) { message.set_session_id(current_session_id); response_events.push(BackgroundProtocolEvent::immediate(message)); @@ -226,7 +229,7 @@ impl CdpConnection { } None => { if message.method() == Some("Page.windowOpen") { - let params = message.get("params").unwrap_or(&Value::Null); + let params = message.value().get("params").unwrap_or(&Value::Null); let Some(url) = params.get("url").and_then(Value::as_str) else { tracing::warn!("dropping Page.windowOpen without a string url"); return false; @@ -282,7 +285,10 @@ impl CdpConnection { | "Runtime.executionContextsCleared" ) ) { - self.register_runtime_remote_object_ids_from_value_for_owner(owner, &message); + self.register_runtime_remote_object_ids_from_value_for_owner( + owner, + message.value(), + ); } if matches!( message.method(), @@ -712,13 +718,13 @@ impl CdpConnection { if let Some(object_group) = response.object_group() { self.register_runtime_remote_object_ids_from_value_for_owner_with_group( response.owner(), - &response.message, + response.message.value(), object_group, ); } else { self.register_runtime_remote_object_ids_from_value_for_owner( response.owner(), - &response.message, + response.message.value(), ); } let mut message = response.into_protocol_message(); @@ -767,7 +773,7 @@ impl CdpConnection { return BidiChannelListenerRoute::Consumed; } let listener = residence.listener(); - let message = &response.message; + let message = response.message.value(); if let Some(error) = message.get("error") { tracing::debug!( ?error, diff --git a/moli-protocol/src/conn/state/devtools_renderer_channel.rs b/moli-protocol/src/conn/state/devtools_renderer_channel.rs index 5673428ad6..e62ba01d90 100644 --- a/moli-protocol/src/conn/state/devtools_renderer_channel.rs +++ b/moli-protocol/src/conn/state/devtools_renderer_channel.rs @@ -354,6 +354,7 @@ mod tests { return None; }; message + .value() .get("params") .and_then(|params| params.get("marker")) .and_then(serde_json::Value::as_str) diff --git a/moli-protocol/src/domains/runtime/dispatcher/dispatch.rs b/moli-protocol/src/domains/runtime/dispatcher/dispatch.rs index 535929e4fb..9b337822d3 100644 --- a/moli-protocol/src/domains/runtime/dispatcher/dispatch.rs +++ b/moli-protocol/src/domains/runtime/dispatcher/dispatch.rs @@ -13,8 +13,7 @@ pub(super) fn command_response_succeeded( let RendererRuntimeInspectorMessage::Protocol(message) = message else { return false; }; - message.get("id").and_then(Value::as_u64) == Some(command_id) - && message.get("result").is_some() + message.payload().id_u64() == Some(command_id) && message.payload().has_field("result") }) } @@ -31,9 +30,8 @@ pub(super) fn command_response_succeeded_for_events( { return matches!(payload, BackgroundCommandResponsePayloadRef::Success { .. }); } - event.protocol_message().is_some_and(|message| { - message.get("id").and_then(Value::as_u64) == Some(command_id) - && message.get("result").is_some() + event.protocol_json().is_some_and(|message| { + message.id_u64() == Some(command_id) && message.has_field("result") }) }) } @@ -1102,3 +1100,40 @@ pub(super) fn forget_pre_registered_runtime_await( conn.forget_pending_inspector_await_for_owner(command_id, owner); } } + +#[cfg(test)] +mod raw_response_tests { + use super::*; + use moli_inspector_json::InspectorJson; + + #[test] + fn command_success_checks_use_raw_metadata_without_parsing_the_body() { + for (body, succeeded) in [ + ( + format!(r#""result":{{"value":"{}"}}"#, "x".repeat(1024 * 1024)), + true, + ), + ( + format!(r#""result":{}0{}"#, "[".repeat(150), "]".repeat(150)), + true, + ), + ( + r#""error":{"code":-32603,"message":"\ud800"}"#.to_owned(), + false, + ), + ] { + let source = + InspectorJson::from_slice(format!(r#"{{"id":7,{body}}}"#).as_bytes()).unwrap(); + let messages = [RendererRuntimeInspectorMessage::protocol(source.clone())]; + assert_eq!(command_response_succeeded(&messages, Some(7)), succeeded); + assert!(!command_response_succeeded(&messages, Some(8))); + let events = [BackgroundProtocolEvent::immediate(source.clone())]; + assert_eq!( + command_response_succeeded_for_events(&events, Some(7)), + succeeded + ); + assert!(!command_response_succeeded_for_events(&events, Some(8))); + assert!(!source.is_materialized()); + } + } +} diff --git a/moli-protocol/src/domains/runtime/native.rs b/moli-protocol/src/domains/runtime/native.rs index 434b679721..20a72dfab7 100644 --- a/moli-protocol/src/domains/runtime/native.rs +++ b/moli-protocol/src/domains/runtime/native.rs @@ -105,7 +105,11 @@ fn try_start_binding(conn: &mut CdpConnection, cmd: &Cmd<'_>) -> Option { if let Some(error) = output.messages().iter().find_map(|message| match message { - RendererRuntimeInspectorMessage::Protocol(message) => message.get("error"), + RendererRuntimeInspectorMessage::Protocol(message) + if message.payload().has_field("error") => + { + message.value().get("error") + } _ => None, }) { return RendererNativeProtocolResponse::error( diff --git a/moli-renderer-v8/src/lib.rs b/moli-renderer-v8/src/lib.rs index 98270641f1..0883e186eb 100644 --- a/moli-renderer-v8/src/lib.rs +++ b/moli-renderer-v8/src/lib.rs @@ -324,22 +324,22 @@ pub use runtime::{ RendererRuntimeInspectorIoCommandRoute, RendererRuntimeInspectorMainCommandCompletion, RendererRuntimeInspectorMainCommandRoute, RendererRuntimeInspectorMessage, RendererRuntimeInspectorMessageBatch, RendererRuntimeInspectorProtocolMessage, - RendererRuntimeInspectorProtocolMessageValueMut, RendererRuntimeInspectorResponseChannel, - RendererRuntimeInspectorResponseSender, RendererRuntimeObservableSourceItem, - RendererRuntimeObservableSourceSummary, RendererRuntimeRealmInfo, RendererRuntimeRemoteObject, - RendererRuntimeRemoteObjectResolution, RendererScreenshotClip, RendererScreenshotFormat, - RendererScreenshotRegion, RendererScriptExecutionMemoryDiagnostics, - RendererScriptSourceMemoryDiagnostics, RendererScrollIntoViewResult, - RendererServiceWorkerConsoleMessage, RendererServiceWorkerExceptionMessage, - RendererServiceWorkerFetchDiagnostic, RendererServiceWorkerFetchDiagnosticResult, - RendererServiceWorkerMainResourceFetch, RendererServiceWorkerRunIdentity, - RendererServiceWorkerTargetEvent, RendererServiceWorkerTargetInfo, - RendererServiceWorkerVersionStatus, RendererSetDocumentContentResult, - RendererSharedWorkerConsoleMessage, RendererSharedWorkerTargetEvent, - RendererSharedWorkerTargetInfo, RendererStyleSheetHeader, RendererStyleSheetInventoryUpdate, - RendererStyleSheetPayload, RendererSyntheticResponseBody, RendererTextSearchMatch, - RendererTouchPoint, RendererVisualStateToken, RendererWindowDocumentSource, - RuntimeConsoleMessageSnapshot, WorkerInspectorError, renderer_output_transport_channel, + RendererRuntimeInspectorResponseChannel, RendererRuntimeInspectorResponseSender, + RendererRuntimeObservableSourceItem, RendererRuntimeObservableSourceSummary, + RendererRuntimeRealmInfo, RendererRuntimeRemoteObject, RendererRuntimeRemoteObjectResolution, + RendererScreenshotClip, RendererScreenshotFormat, RendererScreenshotRegion, + RendererScriptExecutionMemoryDiagnostics, RendererScriptSourceMemoryDiagnostics, + RendererScrollIntoViewResult, RendererServiceWorkerConsoleMessage, + RendererServiceWorkerExceptionMessage, RendererServiceWorkerFetchDiagnostic, + RendererServiceWorkerFetchDiagnosticResult, RendererServiceWorkerMainResourceFetch, + RendererServiceWorkerRunIdentity, RendererServiceWorkerTargetEvent, + RendererServiceWorkerTargetInfo, RendererServiceWorkerVersionStatus, + RendererSetDocumentContentResult, RendererSharedWorkerConsoleMessage, + RendererSharedWorkerTargetEvent, RendererSharedWorkerTargetInfo, RendererStyleSheetHeader, + RendererStyleSheetInventoryUpdate, RendererStyleSheetPayload, RendererSyntheticResponseBody, + RendererTextSearchMatch, RendererTouchPoint, RendererVisualStateToken, + RendererWindowDocumentSource, RuntimeConsoleMessageSnapshot, WorkerInspectorError, + renderer_output_transport_channel, }; pub use runtime::{ RendererElementClickError, RendererElementClickTarget, RendererPreparedPointerClick, diff --git a/moli-renderer-v8/src/runtime/mod.rs b/moli-renderer-v8/src/runtime/mod.rs index 30a8e309b0..f1edd9fa07 100644 --- a/moli-renderer-v8/src/runtime/mod.rs +++ b/moli-renderer-v8/src/runtime/mod.rs @@ -386,20 +386,19 @@ pub use self::page_surface::{ RendererRuntimeCommandOutput, RendererRuntimeEvaluationResult, RendererRuntimeHeapSpaceUsage, RendererRuntimeHeapUsage, RendererRuntimeInspectorAsyncCompletion, RendererRuntimeInspectorMessage, RendererRuntimeInspectorMessageBatch, - RendererRuntimeInspectorProtocolMessage, RendererRuntimeInspectorProtocolMessageValueMut, - RendererRuntimeInspectorResponseChannel, RendererRuntimeInspectorResponseSender, - RendererRuntimeObservableSourceItem, RendererRuntimeObservableSourceSummary, - RendererRuntimeRealmInfo, RendererRuntimeRemoteObject, RendererRuntimeRemoteObjectResolution, - RendererScriptExecutionMemoryDiagnostics, RendererScriptSourceMemoryDiagnostics, - RendererScrollIntoViewResult, RendererServiceWorkerConsoleMessage, - RendererServiceWorkerExceptionMessage, RendererServiceWorkerFetchDiagnostic, - RendererServiceWorkerFetchDiagnosticResult, RendererServiceWorkerTargetEvent, - RendererServiceWorkerTargetInfo, RendererServiceWorkerVersionStatus, - RendererSetDocumentContentResult, RendererSharedWorkerConsoleMessage, - RendererSharedWorkerTargetEvent, RendererSharedWorkerTargetInfo, RendererStyleSheetHeader, - RendererStyleSheetInventoryUpdate, RendererStyleSheetPayload, RendererSyntheticResponseBody, - RendererTextSearchMatch, RendererTouchPoint, RendererWindowDocumentSource, - RuntimeConsoleMessageSnapshot, + RendererRuntimeInspectorProtocolMessage, RendererRuntimeInspectorResponseChannel, + RendererRuntimeInspectorResponseSender, RendererRuntimeObservableSourceItem, + RendererRuntimeObservableSourceSummary, RendererRuntimeRealmInfo, RendererRuntimeRemoteObject, + RendererRuntimeRemoteObjectResolution, RendererScriptExecutionMemoryDiagnostics, + RendererScriptSourceMemoryDiagnostics, RendererScrollIntoViewResult, + RendererServiceWorkerConsoleMessage, RendererServiceWorkerExceptionMessage, + RendererServiceWorkerFetchDiagnostic, RendererServiceWorkerFetchDiagnosticResult, + RendererServiceWorkerTargetEvent, RendererServiceWorkerTargetInfo, + RendererServiceWorkerVersionStatus, RendererSetDocumentContentResult, + RendererSharedWorkerConsoleMessage, RendererSharedWorkerTargetEvent, + RendererSharedWorkerTargetInfo, RendererStyleSheetHeader, RendererStyleSheetInventoryUpdate, + RendererStyleSheetPayload, RendererSyntheticResponseBody, RendererTextSearchMatch, + RendererTouchPoint, RendererWindowDocumentSource, RuntimeConsoleMessageSnapshot, }; pub(crate) use self::page_surface::{ RendererCommandTurnOutputRecorder, RendererDevToolsSessionOutputHost, diff --git a/moli-renderer-v8/src/runtime/page_dom.rs b/moli-renderer-v8/src/runtime/page_dom.rs index ba3beff192..5645cf11bd 100644 --- a/moli-renderer-v8/src/runtime/page_dom.rs +++ b/moli-renderer-v8/src/runtime/page_dom.rs @@ -103,7 +103,7 @@ fn renderer_inspector_response_succeeded( let RendererRuntimeInspectorMessage::Protocol(message) = message else { return false; }; - message.get("id").and_then(Value::as_u64) == Some(call_id) && message.get("error").is_none() + message.payload().id_u64() == Some(call_id) && !message.payload().has_field("error") }) } const DOM_STABLE_COMPLETE_BASE_WINDOW: std::time::Duration = std::time::Duration::from_millis(350); @@ -119,7 +119,7 @@ fn runtime_inspector_response_message( let RendererRuntimeInspectorMessage::Protocol(message) = message else { return None; }; - (message.get("id").and_then(Value::as_u64) == Some(response_id)).then_some(message.value()) + (message.payload().id_u64() == Some(response_id)).then(|| message.value()) }) } @@ -1854,7 +1854,7 @@ impl PageVm { .filter(|message| { message.has_v8_inspector_method() || matches!(message, RendererRuntimeInspectorMessage::Protocol(message) - if message.get("error").is_some()) + if message.payload().has_field("error")) }) .collect(), ); @@ -1873,7 +1873,7 @@ impl PageVm { let output = output.map_err(anyhow::Error::msg)?; if !output.messages().iter().any(|message| { matches!(message, RendererRuntimeInspectorMessage::Protocol(message) - if message.get("error").is_some()) + if message.payload().has_field("error")) }) { let session_key = DevToolsSessionKey::from_wire_session_id(inspector_session_id); let mut session_bindings = self diff --git a/moli-renderer-v8/src/runtime/page_surface.rs b/moli-renderer-v8/src/runtime/page_surface.rs index e570592fb0..312af6cfa7 100644 --- a/moli-renderer-v8/src/runtime/page_surface.rs +++ b/moli-renderer-v8/src/runtime/page_surface.rs @@ -911,12 +911,7 @@ pub enum RendererRuntimeInspectorMessage { #[derive(Debug, Clone, PartialEq)] pub struct RendererRuntimeInspectorProtocolMessage { - renderer_call_id: Option, - value: InspectorJson, -} - -pub struct RendererRuntimeInspectorProtocolMessageValueMut<'a> { - message: &'a mut RendererRuntimeInspectorProtocolMessage, + payload: InspectorJson, } #[derive(Debug, Clone, Default, PartialEq)] @@ -1026,16 +1021,8 @@ impl RendererRuntimeCommandOutput { } pub fn protocol_response(&self, call_id: i32) -> Option<&Value> { - self.messages.iter().find_map(|message| match message { - RendererRuntimeInspectorMessage::Protocol(message) - if message - .renderer_call_id() - .is_some_and(|id| id.get() == call_id) => - { - Some(message.value()) - } - _ => None, - }) + self.protocol_response_payload(call_id) + .map(InspectorJson::value) } pub fn into_protocol_response(self, call_id: i32) -> Option { @@ -1153,70 +1140,38 @@ impl RendererRuntimeInspectorMessage { } impl RendererRuntimeInspectorProtocolMessage { - pub fn new(value: impl Into) -> Self { - let value = value.into(); - let renderer_call_id = renderer_call_id_from_protocol_message(&value); + pub fn new(payload: impl Into) -> Self { Self { - renderer_call_id, - value, + payload: payload.into(), } } pub fn renderer_call_id(&self) -> Option { - self.renderer_call_id + renderer_call_id_from_protocol_message(&self.payload) } pub fn value(&self) -> &Value { - self.value.value() + self.payload.value() } pub fn payload(&self) -> &InspectorJson { - &self.value + &self.payload } pub fn into_payload(self) -> InspectorJson { - self.value + self.payload } pub fn set_frontend_id(&mut self, id: u64) { - self.value.set_id(id); - self.renderer_call_id = renderer_call_id_from_protocol_message(&self.value); + self.payload.set_id(id); } - pub fn value_mut(&mut self) -> RendererRuntimeInspectorProtocolMessageValueMut<'_> { - RendererRuntimeInspectorProtocolMessageValueMut { message: self } + pub fn value_mut(&mut self) -> &mut Value { + self.payload.value_mut() } pub fn into_value(self) -> Value { - self.value.into_value() - } -} - -impl std::ops::Deref for RendererRuntimeInspectorProtocolMessageValueMut<'_> { - type Target = Value; - - fn deref(&self) -> &Self::Target { - self.message.value.value() - } -} - -impl std::ops::DerefMut for RendererRuntimeInspectorProtocolMessageValueMut<'_> { - fn deref_mut(&mut self) -> &mut Self::Target { - self.message.value.value_mut() - } -} - -impl Drop for RendererRuntimeInspectorProtocolMessageValueMut<'_> { - fn drop(&mut self) { - self.message.renderer_call_id = renderer_call_id_from_protocol_message(&self.message.value); - } -} - -impl std::ops::Deref for RendererRuntimeInspectorProtocolMessage { - type Target = Value; - - fn deref(&self) -> &Self::Target { - self.value() + self.payload.into_value() } } diff --git a/moli-renderer-v8/src/runtime/tests/extracted/runtime_scripts.rs b/moli-renderer-v8/src/runtime/tests/extracted/runtime_scripts.rs index 773c85893f..9811307f75 100644 --- a/moli-renderer-v8/src/runtime/tests/extracted/runtime_scripts.rs +++ b/moli-renderer-v8/src/runtime/tests/extracted/runtime_scripts.rs @@ -1002,7 +1002,8 @@ async fn runtime_enable_events_include_renderer_root_frame_id_for_default_contex let default_contexts = events .iter() .filter(|message| { - message.get("method") == Some(&serde_json::json!("Runtime.executionContextCreated")) + message.get("method").and_then(serde_json::Value::as_str) + == Some("Runtime.executionContextCreated") && message["params"]["context"]["auxData"]["isDefault"] == serde_json::json!(true) && message["params"]["context"]["auxData"]["type"] == serde_json::json!("default") }) @@ -1230,7 +1231,7 @@ async fn inspector_output_flushes_v8_state_for_commands_and_notifications() { ) if batch.messages.iter().any(|message| matches!( message, RendererRuntimeInspectorMessage::Protocol(message) - if message.get("id").and_then(serde_json::Value::as_i64) == Some(701) + if message.payload().id_i64() == Some(701) )) ) }) @@ -1255,8 +1256,7 @@ async fn inspector_output_flushes_v8_state_for_commands_and_notifications() { && batch.messages.iter().any(|message| matches!( message, RendererRuntimeInspectorMessage::Protocol(message) - if message.get("method") - == Some(&serde_json::json!("Runtime.consoleAPICalled")) + if message.payload().method() == Some("Runtime.consoleAPICalled") )) )) }), @@ -1315,8 +1315,7 @@ async fn owner_command_fences_exact_cursor_when_later_output_is_already_publishe if batch.messages.iter().any(|message| matches!( message, RendererRuntimeInspectorMessage::Protocol(message) - if message.get("method") - == Some(&serde_json::json!("Runtime.consoleAPICalled")) + if message.payload().method() == Some("Runtime.consoleAPICalled") )) )), "the early publication must own the Runtime notification emitted by the owner command" @@ -1419,8 +1418,7 @@ async fn page_diagnostics_snapshot_is_read_only_for_current_inspector_output() { if batch.messages.iter().any(|message| matches!( message, RendererRuntimeInspectorMessage::Protocol(message) - if message.get("method") - == Some(&serde_json::json!("Runtime.consoleAPICalled")) + if message.payload().method() == Some("Runtime.consoleAPICalled") )) )) }), @@ -4171,9 +4169,9 @@ async fn pending_expression_publishes_console_output_before_settlement() { let RendererRuntimeInspectorMessage::Protocol(message) = message else { continue; }; - if message.get("method").and_then(serde_json::Value::as_str) + if message.payload().method() == Some("Runtime.consoleAPICalled") - && let Some(value) = message["params"]["args"][0]["value"].as_str() + && let Some(value) = message.value()["params"]["args"][0]["value"].as_str() { observed.push(value.to_owned()); } @@ -4277,8 +4275,8 @@ async fn navigation_follow_publishes_command_output_before_replacing_document() if batch.messages.iter().any(|message| matches!( message, RendererRuntimeInspectorMessage::Protocol(message) - if message["method"] == "Runtime.consoleAPICalled" - && message["params"]["args"][0]["value"] == "command-output-before-navigation" + if message.payload().method() == Some("Runtime.consoleAPICalled") + && message.value()["params"]["args"][0]["value"] == "command-output-before-navigation" )) )) }) diff --git a/moli-renderer-v8/src/script_vm/inspector/agent_sessions.rs b/moli-renderer-v8/src/script_vm/inspector/agent_sessions.rs index 9d68240dda..fd06ca8fe0 100644 --- a/moli-renderer-v8/src/script_vm/inspector/agent_sessions.rs +++ b/moli-renderer-v8/src/script_vm/inspector/agent_sessions.rs @@ -798,7 +798,7 @@ mod tests { let restored_context = restored_messages .iter() .find(|message| { - message.get("method").and_then(Value::as_str) + message.method() == Some("Runtime.executionContextCreated") }) .unwrap_or_else(|| { @@ -807,7 +807,8 @@ mod tests { ) }); assert_eq!( - restored_context["params"]["context"]["origin"], "https://example.test", + restored_context.value()["params"]["context"]["origin"], + "https://example.test", "V8ContextInfo must carry the embedder-bound origin without outbound JSON rewriting" ); let formatter_probe = serde_json::json!({ @@ -934,19 +935,13 @@ mod tests { let messages = restored.outbound.values_after(0); let cleared_index = messages .iter() - .position(|message| { - message.get("method").and_then(Value::as_str) - == Some("Runtime.executionContextsCleared") - }) + .position(|message| message.method() == Some("Runtime.executionContextsCleared")) .unwrap_or_else(|| { panic!("restored Runtime session should clear old contexts: {messages:?}") }); let created_index = messages .iter() - .position(|message| { - message.get("method").and_then(Value::as_str) - == Some("Runtime.executionContextCreated") - }) + .position(|message| message.method() == Some("Runtime.executionContextCreated")) .unwrap_or_else(|| { panic!("restored Runtime session should report the new context: {messages:?}") }); diff --git a/moli-renderer-v8/src/script_vm/inspector/tests.rs b/moli-renderer-v8/src/script_vm/inspector/tests.rs index b3ac843b88..4b47e2d7b5 100644 --- a/moli-renderer-v8/src/script_vm/inspector/tests.rs +++ b/moli-renderer-v8/src/script_vm/inspector/tests.rs @@ -52,7 +52,7 @@ fn inspector_protocol_message_has_typed_and_consistent_response_id() { Some(moli_page_types::RendererCallId::new(0)) ); { - let mut value = response.value_mut(); + let value = response.value_mut(); value["id"] = json!(-7); } assert_eq!( @@ -249,7 +249,7 @@ fn runtime_command_output_only_parks_its_own_response_callback() { assert!(matches!( ¤t.messages()[0], crate::runtime::RendererRuntimeInspectorMessage::Protocol(message) - if message["method"] == json!("Runtime.consoleAPICalled") + if message.payload().method() == Some("Runtime.consoleAPICalled") )); assert_eq!( current.protocol_response(8), @@ -549,3 +549,25 @@ fn inspector_outbound_raw_utf16_and_response_id_validation_keep_call_authority() assert_eq!(outbound.response_callback_counts(), (0, 0)); } } + +#[test] +fn inspector_response_id_reads_opaque_metadata_and_tracks_explicit_mutation() { + let body = format!("{}0{}", "[".repeat(150), "]".repeat(150)); + let source = + InspectorJson::from_slice(format!(r#"{{"id":7,"result":{body}}}"#).as_bytes()).unwrap(); + let mut message = crate::runtime::RendererRuntimeInspectorProtocolMessage::new(source.clone()); + assert_eq!(message.renderer_call_id().map(|id| id.get()), Some(7)); + message.set_frontend_id(u64::MAX); + assert_eq!(message.renderer_call_id(), None); + assert_eq!(message.payload().id_u64(), Some(u64::MAX)); + message.set_frontend_id(9); + assert_eq!(message.renderer_call_id().map(|id| id.get()), Some(9)); + assert!(!source.is_materialized()); + assert!(!message.payload().is_materialized()); + message.value_mut()["id"] = json!(-7); + assert_eq!(message.renderer_call_id().map(|id| id.get()), Some(-7)); + message.value_mut().as_object_mut().unwrap().remove("id"); + assert_eq!(message.renderer_call_id(), None); + message.value_mut()["id"] = json!(i64::MAX); + assert_eq!(message.renderer_call_id(), None); +} diff --git a/moli-renderer-v8/src/service_worker_runtime/service.rs b/moli-renderer-v8/src/service_worker_runtime/service.rs index 77f71e6f95..3ad35cfb7e 100644 --- a/moli-renderer-v8/src/service_worker_runtime/service.rs +++ b/moli-renderer-v8/src/service_worker_runtime/service.rs @@ -479,7 +479,7 @@ impl ServiceWorkerRuntimeService { .into_iter() .partition(|message| match message { RendererRuntimeInspectorMessage::Protocol(message) => { - message.get("id").is_some() + message.payload().has_field("id") } RendererRuntimeInspectorMessage::RuntimeContext(_) => false, }); diff --git a/moli-renderer-v8/src/shared_worker_runtime/host_target_output.rs b/moli-renderer-v8/src/shared_worker_runtime/host_target_output.rs index 0c393c9eb6..ffd18b42a2 100644 --- a/moli-renderer-v8/src/shared_worker_runtime/host_target_output.rs +++ b/moli-renderer-v8/src/shared_worker_runtime/host_target_output.rs @@ -119,7 +119,7 @@ impl RendererSharedWorkerHost { .into_iter() .partition(|message| match message { RendererRuntimeInspectorMessage::Protocol(message) => { - message.get("id").is_some() + message.payload().has_field("id") } RendererRuntimeInspectorMessage::RuntimeContext(_) => false, }); diff --git a/moli-renderer-v8/src/worker/thread/runtime_inspector.rs b/moli-renderer-v8/src/worker/thread/runtime_inspector.rs index 5b9a26c501..f0c0ed9a79 100644 --- a/moli-renderer-v8/src/worker/thread/runtime_inspector.rs +++ b/moli-renderer-v8/src/worker/thread/runtime_inspector.rs @@ -942,7 +942,7 @@ mod tests { .iter() .find_map(|message| match message { RendererRuntimeInspectorMessage::Protocol(message) - if message.value().get("id").and_then(Value::as_i64) == Some(call_id) => + if message.payload().id_i64() == Some(call_id) => { Some(message.value().clone()) }