Repository: servo/servo
File: components/devtools/actors/breakpoint.rs (Rust)

Code before:
                let column = location
                    .and_then(|location| location.get("column"))
                    .and_then(|column| column.as_number())
                    .and_then(|column| column.as_u64())
                    .ok_or(ActorError::Internal)?;
                let line = location
                    .and_then(|location| location.get("line"))
                    .and_then(|line| line.as_number())
                    .and_then(|line| line.as_u64())
                    .ok_or(ActorError::Internal)?;
                let source_url = location
                    .and_then(|location| location.get("sourceUrl"))
                    .and_then(|source_url| source_url.as_str())
                    .ok_or(ActorError::Internal)?;

                let browsing_context =
                    registry.find::<BrowsingContextActor>(&self.browsing_context);
                let thread = registry.find::<ThreadActor>(&browsing_context.thread);
                let source = thread
                    .source_manager
                    .find_source(registry, source_url)
                    .ok_or(ActorError::Internal)?;
                let offset = source.find_offset(column as u32, line as u32);

                // set-breakpoint
                let (tx, rx) = channel().ok_or(ActorError::Internal)?;
                source
                    .script_sender
                    .send(DevtoolScriptControlMsg::SetBreakpoint(
                        source.spidermonkey_id,
                        offset,
                        tx,
                    ))
                    .map_err(|_| ActorError::Internal)?;
                let _ = rx.recv().map_err(|_| ActorError::Internal)?;

                let msg = EmptyReplyMsg { from: self.name() };
                request.reply_final(&msg)?
            },
            "setActiveEventBreakpoints" => {
                let msg = EmptyReplyMsg { from: self.name() };
                request.reply_final(&msg)?
            },
            "removeBreakpoint" => {
                let msg = EmptyReplyMsg { from: self.name() };
                request.reply_final(&msg)?
            },
            _ => return Err(ActorError::UnrecognizedPacketType),
        };
        Ok(())
    }

Review comment (bug):
not sure, but shall we add this doc here or in the debugger js?
https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.Script.html#setbreakpoint-offset-handler

wdyt?

Code after:

    fn handle_message(
        &self,
        request: ClientRequest,
        registry: &crate::actor::ActorRegistry,
        msg_type: &str,
        msg: &Map<String, serde_json::Value>,
        _stream_id: crate::StreamId,
    ) -> Result<(), ActorError> {
        match msg_type {
            // Client wants to set a breakpoint.
            // Seems to be infallible, unlike the thread actor’s `setBreakpoint`.
            // <https://firefox-source-docs.mozilla.org/devtools/backend/protocol.html#breakpoints>
            "setBreakpoint" => {
                let msg: SetBreakpointRequest =
                    serde_json::from_value(msg.clone().into()).map_err(|_| ActorError::Internal)?;
                let SetBreakpointRequestLocation {
                    line,
                    column,
                    source_url,
                } = msg.location;
                let source_url = source_url.ok_or(ActorError::Internal)?;

                let browsing_context =
                    registry.find::<BrowsingContextActor>(&self.browsing_context);
                let thread = registry.find::<ThreadActor>(&browsing_context.thread);
                let source = thread
                    .source_manager
                    .find_source(registry, &source_url)
                    .ok_or(ActorError::Internal)?;
                let (script_id, offset) = source.find_offset(line, column);

                source
                    .script_sender
                    .send(DevtoolScriptControlMsg::SetBreakpoint(
                        source.spidermonkey_id,
                        script_id,
                        offset,
                    ))
                    .map_err(|_| ActorError::Internal)?;

                let msg = EmptyReplyMsg { from: self.name() };
                request.reply_final(&msg)?
            },
            "setActiveEventBreakpoints" => {
                let msg = EmptyReplyMsg { from: self.name() };
                request.reply_final(&msg)?
            },
            "removeBreakpoint" => {
                let msg = EmptyReplyMsg { from: self.name() };
                request.reply_final(&msg)?