1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
/* 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 { asPaused } = require("../utils");
const { reportException } = require("devtools/shared/DevToolsUtils");
const { setNamedTimeout } = require("devtools/client/shared/widgets/view-helpers");
const { Task } = require("devtools/shared/task");
const FETCH_EVENT_LISTENERS_DELAY = 200; // ms
function fetchEventListeners() {
return (dispatch, getState) => {
// Make sure we"re not sending a batch of closely repeated requests.
// This can easily happen whenever new sources are fetched.
setNamedTimeout("event-listeners-fetch", FETCH_EVENT_LISTENERS_DELAY, () => {
// In case there is still a request of listeners going on (it
// takes several RDP round trips right now), make sure we wait
// on a currently running request
if (getState().eventListeners.fetchingListeners) {
dispatch({
type: services.WAIT_UNTIL,
predicate: action => (
action.type === constants.FETCH_EVENT_LISTENERS &&
action.status === "done"
),
run: dispatch => dispatch(fetchEventListeners())
});
return;
}
dispatch({
type: constants.FETCH_EVENT_LISTENERS,
status: "begin"
});
asPaused(gThreadClient, _getListeners).then(listeners => {
// Notify that event listeners were fetched and shown in the view,
// and callback to resume the active thread if necessary.
window.emit(EVENTS.EVENT_LISTENERS_FETCHED);
dispatch({
type: constants.FETCH_EVENT_LISTENERS,
status: "done",
listeners: listeners
});
});
});
};
}
const _getListeners = Task.async(function* () {
const response = yield gThreadClient.eventListeners();
// Make sure all the listeners are sorted by the event type, since
// they"re not guaranteed to be clustered together.
response.listeners.sort((a, b) => a.type > b.type ? 1 : -1);
// Add all the listeners in the debugger view event linsteners container.
let fetchedDefinitions = new Map();
let listeners = [];
for (let listener of response.listeners) {
let definitionSite;
if (fetchedDefinitions.has(listener.function.actor)) {
definitionSite = fetchedDefinitions.get(listener.function.actor);
} else if (listener.function.class == "Function") {
definitionSite = yield _getDefinitionSite(listener.function);
if (!definitionSite) {
// We don"t know where this listener comes from so don"t show it in
// the UI as breaking on it doesn"t work (bug 942899).
continue;
}
fetchedDefinitions.set(listener.function.actor, definitionSite);
}
listener.function.url = definitionSite;
listeners.push(listener);
}
fetchedDefinitions.clear();
return listeners;
});
const _getDefinitionSite = Task.async(function* (aFunction) {
const grip = gThreadClient.pauseGrip(aFunction);
let response;
try {
response = yield grip.getDefinitionSite();
}
catch (e) {
// Don't make this error fatal, because it would break the entire events pane.
reportException("_getDefinitionSite", e);
return null;
}
return response.source.url;
});
function updateEventBreakpoints(eventNames) {
return dispatch => {
setNamedTimeout("event-breakpoints-update", 0, () => {
gThreadClient.pauseOnDOMEvents(eventNames, function () {
// Notify that event breakpoints were added/removed on the server.
window.emit(EVENTS.EVENT_BREAKPOINTS_UPDATED);
dispatch({
type: constants.UPDATE_EVENT_BREAKPOINTS,
eventNames: eventNames
});
});
});
};
}
module.exports = { updateEventBreakpoints, fetchEventListeners };
|