mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-10-10 13:23:42 +00:00
170 lines
5.1 KiB
JavaScript
170 lines
5.1 KiB
JavaScript
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||
|
"use strict";
|
||
|
|
||
|
const constants = require('../constants');
|
||
|
const promise = require('promise');
|
||
|
const { asPaused, rdpInvoke } = require('../utils');
|
||
|
const { PROMISE } = require('devtools/client/shared/redux/middleware/promise');
|
||
|
const {
|
||
|
getSource, getBreakpoint, getBreakpoints, makeLocationId
|
||
|
} = require('../queries');
|
||
|
|
||
|
// Because breakpoints are just simple data structures, we still need
|
||
|
// a way to lookup the actual client instance to talk to the server.
|
||
|
// We keep an internal database of clients based off of actor ID.
|
||
|
const BREAKPOINT_CLIENT_STORE = new Map();
|
||
|
|
||
|
function setBreakpointClient(actor, client) {
|
||
|
BREAKPOINT_CLIENT_STORE.set(actor, client);
|
||
|
}
|
||
|
|
||
|
function getBreakpointClient(actor) {
|
||
|
return BREAKPOINT_CLIENT_STORE.get(actor);
|
||
|
}
|
||
|
|
||
|
function enableBreakpoint(location) {
|
||
|
// Enabling is exactly the same as adding. It will use the existing
|
||
|
// breakpoint that still stored.
|
||
|
return addBreakpoint(location);
|
||
|
}
|
||
|
|
||
|
function _breakpointExists(state, location) {
|
||
|
const currentBp = getBreakpoint(state, location);
|
||
|
return currentBp && !currentBp.disabled;
|
||
|
}
|
||
|
|
||
|
function _getOrCreateBreakpoint(state, location, condition) {
|
||
|
return getBreakpoint(state, location) || { location, condition };
|
||
|
}
|
||
|
|
||
|
function addBreakpoint(location, condition) {
|
||
|
return (dispatch, getState) => {
|
||
|
if (_breakpointExists(getState(), location)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const bp = _getOrCreateBreakpoint(getState(), location, condition);
|
||
|
|
||
|
return dispatch({
|
||
|
type: constants.ADD_BREAKPOINT,
|
||
|
breakpoint: bp,
|
||
|
condition: condition,
|
||
|
[PROMISE]: Task.spawn(function*() {
|
||
|
const sourceClient = gThreadClient.source(
|
||
|
getSource(getState(), bp.location.actor)
|
||
|
);
|
||
|
const [response, bpClient] = yield rdpInvoke(sourceClient, sourceClient.setBreakpoint, {
|
||
|
line: bp.location.line,
|
||
|
column: bp.location.column,
|
||
|
condition: bp.condition
|
||
|
});
|
||
|
const { isPending, actualLocation } = response;
|
||
|
|
||
|
// Save the client instance
|
||
|
setBreakpointClient(bpClient.actor, bpClient);
|
||
|
|
||
|
return {
|
||
|
text: DebuggerView.editor.getText(bp.location.line - 1).trim(),
|
||
|
|
||
|
// If the breakpoint response has an "actualLocation" attached, then
|
||
|
// the original requested placement for the breakpoint wasn't
|
||
|
// accepted.
|
||
|
actualLocation: isPending ? null : actualLocation,
|
||
|
actor: bpClient.actor
|
||
|
};
|
||
|
})
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function disableBreakpoint(location) {
|
||
|
return _removeOrDisableBreakpoint(location, true);
|
||
|
}
|
||
|
|
||
|
function removeBreakpoint(location) {
|
||
|
return _removeOrDisableBreakpoint(location);
|
||
|
}
|
||
|
|
||
|
function _removeOrDisableBreakpoint(location, isDisabled) {
|
||
|
return (dispatch, getState) => {
|
||
|
let bp = getBreakpoint(getState(), location);
|
||
|
if (!bp) {
|
||
|
throw new Error('attempt to remove breakpoint that does not exist');
|
||
|
}
|
||
|
if (bp.loading) {
|
||
|
// TODO(jwl): make this wait until the breakpoint is saved if it
|
||
|
// is still loading
|
||
|
throw new Error('attempt to remove unsaved breakpoint');
|
||
|
}
|
||
|
|
||
|
const bpClient = getBreakpointClient(bp.actor);
|
||
|
|
||
|
return dispatch({
|
||
|
type: constants.REMOVE_BREAKPOINT,
|
||
|
breakpoint: bp,
|
||
|
disabled: isDisabled,
|
||
|
[PROMISE]: rdpInvoke(bpClient, bpClient.remove)
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function removeAllBreakpoints() {
|
||
|
return (dispatch, getState) => {
|
||
|
const breakpoints = getBreakpoints(getState());
|
||
|
const activeBreakpoints = breakpoints.filter(bp => !bp.disabled);
|
||
|
activeBreakpoints.forEach(bp => removeBreakpoint(bp.location));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Update the condition of a breakpoint.
|
||
|
*
|
||
|
* @param object aLocation
|
||
|
* @see DebuggerController.Breakpoints.addBreakpoint
|
||
|
* @param string aClients
|
||
|
* The condition to set on the breakpoint
|
||
|
* @return object
|
||
|
* A promise that will be resolved with the breakpoint client
|
||
|
*/
|
||
|
function setBreakpointCondition(location, condition) {
|
||
|
return (dispatch, getState) => {
|
||
|
const bp = getBreakpoint(getState(), location);
|
||
|
if (!bp) {
|
||
|
throw new Error("Breakpoint does not exist at the specified location");
|
||
|
}
|
||
|
if (bp.loading){
|
||
|
// TODO(jwl): when this function is called, make sure the action
|
||
|
// creator waits for the breakpoint to exist
|
||
|
throw new Error("breakpoint must be saved");
|
||
|
}
|
||
|
|
||
|
const bpClient = getBreakpointClient(bp.actor);
|
||
|
|
||
|
return dispatch({
|
||
|
type: constants.SET_BREAKPOINT_CONDITION,
|
||
|
breakpoint: bp,
|
||
|
condition: condition,
|
||
|
[PROMISE]: Task.spawn(function*() {
|
||
|
const newClient = yield bpClient.setCondition(gThreadClient, condition);
|
||
|
|
||
|
// Remove the old instance and save the new one
|
||
|
setBreakpointClient(bpClient.actor, null);
|
||
|
setBreakpointClient(newClient.actor, newClient);
|
||
|
|
||
|
return { actor: newClient.actor };
|
||
|
})
|
||
|
});
|
||
|
};
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
enableBreakpoint,
|
||
|
addBreakpoint,
|
||
|
disableBreakpoint,
|
||
|
removeBreakpoint,
|
||
|
removeAllBreakpoints,
|
||
|
setBreakpointCondition
|
||
|
}
|