Bug 1660268 - Pass list of resources instead of unique resource from ResourceWatcher. r=nchevobbe

Here, I've tried to be especially careful about replacing `return` by `continue` in the added for..loops.

Differential Revision: https://phabricator.services.mozilla.com/D87768
This commit is contained in:
Alexandre Poirot
2020-09-07 21:13:02 +00:00
parent 79e7c72bd5
commit be66ca08ca
32 changed files with 591 additions and 478 deletions

View File

@@ -79,7 +79,7 @@ class DebuggerPanel {
const resourceWatcher = this.toolbox.resourceWatcher; const resourceWatcher = this.toolbox.resourceWatcher;
await resourceWatcher.watchResources( await resourceWatcher.watchResources(
[resourceWatcher.TYPES.ERROR_MESSAGE], [resourceWatcher.TYPES.ERROR_MESSAGE],
{ onAvailable: actions.addExceptionFromResource } { onAvailable: actions.addExceptionFromResources }
); );
return this; return this;

View File

@@ -9,24 +9,26 @@ import { hasException } from "../selectors";
import type { ThunkArgs } from "./types"; import type { ThunkArgs } from "./types";
import type { Exception } from "../types"; import type { Exception } from "../types";
export function addExceptionFromResource({ resource }: Object) { export function addExceptionFromResources(resources: Array<Object>) {
return async function({ dispatch }: ThunkArgs) { return async function({ dispatch }: ThunkArgs) {
const { pageError } = resource; for (const resource of resources) {
if (!pageError.error) { const { pageError } = resource;
return; if (!pageError.error) {
continue;
}
const { columnNumber, lineNumber, sourceId, errorMessage } = pageError;
const stacktrace = pageError.stacktrace || [];
const exception = {
columnNumber,
lineNumber,
sourceActorId: sourceId,
errorMessage,
stacktrace,
};
dispatch(addException(exception));
} }
const { columnNumber, lineNumber, sourceId, errorMessage } = pageError;
const stacktrace = pageError.stacktrace || [];
const exception = {
columnNumber,
lineNumber,
sourceActorId: sourceId,
errorMessage,
stacktrace,
};
dispatch(addException(exception));
}; };
} }

View File

@@ -428,9 +428,11 @@ class SourceMapURLService {
return; return;
} }
this._onResourceAvailable = async ({ resource }) => { this._onResourceAvailable = async resources => {
if (this._sourcesLoading === sourcesLoading) { if (this._sourcesLoading === sourcesLoading) {
this._onNewStyleSheet(resource); for (const resource of resources) {
this._onNewStyleSheet(resource);
}
} }
}; };

View File

@@ -119,20 +119,22 @@ class ChangesView {
); );
} }
onResourceAvailable({ resource }) { onResourceAvailable(resources) {
if (resource.resourceType === this.resourceWatcher.TYPES.CSS_CHANGE) { for (const resource of resources) {
this.onAddChange(resource); if (resource.resourceType === this.resourceWatcher.TYPES.CSS_CHANGE) {
return; this.onAddChange(resource);
} continue;
}
if (resource.name === "dom-loading" && resource.targetFront.isTopLevel) { if (resource.name === "dom-loading" && resource.targetFront.isTopLevel) {
// will-navigate doesn't work when we navigate to a new process, // will-navigate doesn't work when we navigate to a new process,
// and for now, onTargetAvailable/onTargetDestroyed doesn't fire on navigation and // and for now, onTargetAvailable/onTargetDestroyed doesn't fire on navigation and
// only when navigating to another process. // only when navigating to another process.
// So we fallback on DOCUMENT_EVENTS to be notified when we navigate. When we // So we fallback on DOCUMENT_EVENTS to be notified when we navigate. When we
// navigate within the same process as well as when we navigate to a new process. // navigate within the same process as well as when we navigate to a new process.
// (We would probably revisit that in bug 1632141) // (We would probably revisit that in bug 1632141)
this.onClearChanges(); this.onClearChanges();
}
} }
} }

View File

@@ -256,13 +256,15 @@ class CompatibilityView {
); );
} }
_onResourceAvailable({ resource }) { _onResourceAvailable(resources) {
// Style changes applied inline directly to for (const resource of resources) {
// the element and its changes are monitored by // Style changes applied inline directly to
// _onMarkupMutation via markupmutation events. // the element and its changes are monitored by
// Hence those changes can be ignored here // _onMarkupMutation via markupmutation events.
if (resource.source?.type !== "element") { // Hence those changes can be ignored here
this._onChangeAdded(resource); if (resource.source?.type !== "element") {
this._onChangeAdded(resource);
}
} }
} }

View File

@@ -1300,19 +1300,21 @@ Inspector.prototype = {
} }
}, },
onResourceAvailable: function({ resource }) { onResourceAvailable: function(resources) {
if ( for (const resource of resources) {
resource.resourceType === this.toolbox.resourceWatcher.TYPES.ROOT_NODE if (
) { resource.resourceType === this.toolbox.resourceWatcher.TYPES.ROOT_NODE
const isTopLevelTarget = !!resource.targetFront.isTopLevel; ) {
if (resource.isTopLevelDocument && isTopLevelTarget) { const isTopLevelTarget = !!resource.targetFront.isTopLevel;
// Note: the resource (ie the root node here) will be fetched from the if (resource.isTopLevelDocument && isTopLevelTarget) {
// walker later on in _getDefaultNodeForSelection. // Note: the resource (ie the root node here) will be fetched from the
// We should update the inspector to directly use the node front // walker later on in _getDefaultNodeForSelection.
// provided here. Bug 1635461. // We should update the inspector to directly use the node front
this.onRootNodeAvailable(); // provided here. Bug 1635461.
} else { this.onRootNodeAvailable();
this.emit("frame-root-available", resource); } else {
this.emit("frame-root-available", resource);
}
} }
} }
}, },

View File

@@ -149,61 +149,69 @@ class FirefoxConnector {
this.responsiveFront = await this.currentTarget.getFront("responsive"); this.responsiveFront = await this.currentTarget.getFront("responsive");
} }
async onResourceAvailable({ resource }) { async onResourceAvailable(resources) {
const { TYPES } = this.toolbox.resourceWatcher; for (const resource of resources) {
const { TYPES } = this.toolbox.resourceWatcher;
if (resource.resourceType === TYPES.DOCUMENT_EVENT) { if (resource.resourceType === TYPES.DOCUMENT_EVENT) {
this.onDocEvent(resource); this.onDocEvent(resource);
return; continue;
} }
if (resource.resourceType === TYPES.NETWORK_EVENT) { if (resource.resourceType === TYPES.NETWORK_EVENT) {
this.dataProvider.onNetworkResourceAvailable(resource); this.dataProvider.onNetworkResourceAvailable(resource);
return; continue;
} }
if (resource.resourceType === TYPES.WEBSOCKET) { if (resource.resourceType === TYPES.WEBSOCKET) {
const { wsMessageType } = resource; const { wsMessageType } = resource;
switch (wsMessageType) { switch (wsMessageType) {
case "webSocketOpened": { case "webSocketOpened": {
this.dataProvider.onWebSocketOpened( this.dataProvider.onWebSocketOpened(
resource.httpChannelId, resource.httpChannelId,
resource.effectiveURI, resource.effectiveURI,
resource.protocols, resource.protocols,
resource.extensions resource.extensions
); );
break; break;
} }
case "webSocketClosed": { case "webSocketClosed": {
this.dataProvider.onWebSocketClosed( this.dataProvider.onWebSocketClosed(
resource.httpChannelId, resource.httpChannelId,
resource.wasClean, resource.wasClean,
resource.code, resource.code,
resource.reason resource.reason
); );
break; break;
} }
case "frameReceived": { case "frameReceived": {
this.dataProvider.onFrameReceived( this.dataProvider.onFrameReceived(
resource.httpChannelId, resource.httpChannelId,
resource.data resource.data
); );
break; break;
} }
case "frameSent": { case "frameSent": {
this.dataProvider.onFrameSent(resource.httpChannelId, resource.data); this.dataProvider.onFrameSent(
break; resource.httpChannelId,
resource.data
);
break;
}
} }
} }
} }
} }
async onResourceUpdated({ targetFront, resource }) { async onResourceUpdated(updates) {
if ( for (const { resource } of updates) {
resource.resourceType === this.toolbox.resourceWatcher.TYPES.NETWORK_EVENT if (
) { resource.resourceType ===
this.dataProvider.onNetworkResourceUpdated(resource); this.toolbox.resourceWatcher.TYPES.NETWORK_EVENT
) {
this.dataProvider.onNetworkResourceUpdated(resource);
}
} }
} }

View File

@@ -166,136 +166,140 @@ HarCollector.prototype = {
// Event Handlers // Event Handlers
onResourceAvailable: function({ resource }) { onResourceAvailable: function(resources) {
trace.log("HarCollector.onNetworkEvent; ", resource); for (const resource of resources) {
trace.log("HarCollector.onNetworkEvent; ", resource);
const { const {
actor, actor,
startedDateTime, startedDateTime,
request: { method, url }, request: { method, url },
isXHR, isXHR,
} = resource; } = resource;
const startTime = Date.parse(startedDateTime); const startTime = Date.parse(startedDateTime);
if (this.firstRequestStart == -1) { if (this.firstRequestStart == -1) {
this.firstRequestStart = startTime; this.firstRequestStart = startTime;
}
if (this.lastRequestEnd < startTime) {
this.lastRequestEnd = startTime;
}
let file = this.getFile(actor);
if (file) {
console.error(
"HarCollector.onNetworkEvent; ERROR " + "existing file conflict!"
);
continue;
}
file = {
id: actor,
startedDeltaMs: startTime - this.firstRequestStart,
startedMs: startTime,
method: method,
url: url,
isXHR: isXHR,
};
this.files.set(actor, file);
// Mimic the Net panel data structure
this.items.push(file);
} }
if (this.lastRequestEnd < startTime) {
this.lastRequestEnd = startTime;
}
let file = this.getFile(actor);
if (file) {
console.error(
"HarCollector.onNetworkEvent; ERROR " + "existing file conflict!"
);
return;
}
file = {
id: actor,
startedDeltaMs: startTime - this.firstRequestStart,
startedMs: startTime,
method: method,
url: url,
isXHR: isXHR,
};
this.files.set(actor, file);
// Mimic the Net panel data structure
this.items.push(file);
}, },
onResourceUpdated: function({ resource }) { onResourceUpdated: function(updates) {
// Skip events from unknown actors (not in the list). for (const { resource } of updates) {
// It can happen when there are zombie requests received after // Skip events from unknown actors (not in the list).
// the target is closed or multiple tabs are attached through // It can happen when there are zombie requests received after
// one connection (one DevToolsClient object). // the target is closed or multiple tabs are attached through
const file = this.getFile(resource.actor); // one connection (one DevToolsClient object).
if (!file) { const file = this.getFile(resource.actor);
return; if (!file) {
} return;
}
trace.log( trace.log(
"HarCollector.onNetworkEventUpdate; " + resource.updateType, "HarCollector.onNetworkEventUpdate; " + resource.updateType,
resource resource
); );
const includeResponseBodies = Services.prefs.getBoolPref( const includeResponseBodies = Services.prefs.getBoolPref(
"devtools.netmonitor.har.includeResponseBodies" "devtools.netmonitor.har.includeResponseBodies"
); );
let request; let request;
switch (resource.updateType) { switch (resource.updateType) {
case "requestHeaders": case "requestHeaders":
request = this.getData(
resource.actor,
"getRequestHeaders",
this.onRequestHeaders
);
break;
case "requestCookies":
request = this.getData(
resource.actor,
"getRequestCookies",
this.onRequestCookies
);
break;
case "requestPostData":
request = this.getData(
resource.actor,
"getRequestPostData",
this.onRequestPostData
);
break;
case "responseHeaders":
request = this.getData(
resource.actor,
"getResponseHeaders",
this.onResponseHeaders
);
break;
case "responseCookies":
request = this.getData(
resource.actor,
"getResponseCookies",
this.onResponseCookies
);
break;
case "responseStart":
file.httpVersion = resource.response.httpVersion;
file.status = resource.response.status;
file.statusText = resource.response.statusText;
break;
case "responseContent":
file.contentSize = resource.contentSize;
file.mimeType = resource.mimeType;
file.transferredSize = resource.transferredSize;
if (includeResponseBodies) {
request = this.getData( request = this.getData(
resource.actor, resource.actor,
"getResponseContent", "getRequestHeaders",
this.onResponseContent this.onRequestHeaders
); );
} break;
break; case "requestCookies":
case "eventTimings": request = this.getData(
request = this.getData( resource.actor,
resource.actor, "getRequestCookies",
"getEventTimings", this.onRequestCookies
this.onEventTimings );
); break;
break; case "requestPostData":
} request = this.getData(
resource.actor,
"getRequestPostData",
this.onRequestPostData
);
break;
case "responseHeaders":
request = this.getData(
resource.actor,
"getResponseHeaders",
this.onResponseHeaders
);
break;
case "responseCookies":
request = this.getData(
resource.actor,
"getResponseCookies",
this.onResponseCookies
);
break;
case "responseStart":
file.httpVersion = resource.response.httpVersion;
file.status = resource.response.status;
file.statusText = resource.response.statusText;
break;
case "responseContent":
file.contentSize = resource.contentSize;
file.mimeType = resource.mimeType;
file.transferredSize = resource.transferredSize;
if (request) { if (includeResponseBodies) {
this.requests.push(request); request = this.getData(
} resource.actor,
"getResponseContent",
this.onResponseContent
);
}
break;
case "eventTimings":
request = this.getData(
resource.actor,
"getEventTimings",
this.onEventTimings
);
break;
}
this.resetPageLoadTimeout(); if (request) {
this.requests.push(request);
}
this.resetPageLoadTimeout();
}
}, },
getData: function(actor, method, callback) { getData: function(actor, method, callback) {

View File

@@ -1187,8 +1187,8 @@ function getCurrentTestFilePath() {
*/ */
function waitForResourceOnce(resourceWatcher, resourceType) { function waitForResourceOnce(resourceWatcher, resourceType) {
return new Promise(resolve => { return new Promise(resolve => {
const onAvailable = ({ resource }) => { const onAvailable = resources => {
resolve({ resource }); resolve(resources[0]);
resourceWatcher.unwatchResources([resourceType], { onAvailable }); resourceWatcher.unwatchResources([resourceType], { onAvailable });
}; };
resourceWatcher.watchResources([resourceType], { resourceWatcher.watchResources([resourceType], {

View File

@@ -1201,62 +1201,68 @@ StyleEditorUI.prototype = {
} }
}, },
async _onResourceAvailable({ resource }) { async _onResourceAvailable(resources) {
if ( for (const resource of resources) {
resource.resourceType === this._toolbox.resourceWatcher.TYPES.STYLESHEET if (
) { resource.resourceType === this._toolbox.resourceWatcher.TYPES.STYLESHEET
const onStyleSheetHandled = this._handleStyleSheetResource(resource); ) {
const onStyleSheetHandled = this._handleStyleSheetResource(resource);
if (this._loadingStyleSheets) { if (this._loadingStyleSheets) {
// In case of reloading/navigating and panel's opening // In case of reloading/navigating and panel's opening
this._loadingStyleSheets.push(onStyleSheetHandled); this._loadingStyleSheets.push(onStyleSheetHandled);
}
await onStyleSheetHandled;
continue;
} }
await onStyleSheetHandled; if (!resource.targetFront.isTopLevel) {
return; continue;
} }
if (!resource.targetFront.isTopLevel) { if (resource.name === "dom-loading") {
return; // will-navigate doesn't work when we navigate to a new process,
} // and for now, onTargetAvailable/onTargetDestroyed doesn't fire on navigation and
// only when navigating to another process.
if (resource.name === "dom-loading") { // So we fallback on DOCUMENT_EVENTS to be notified when we navigates. When we
// will-navigate doesn't work when we navigate to a new process, // navigate within the same process as well as when we navigate to a new process.
// and for now, onTargetAvailable/onTargetDestroyed doesn't fire on navigation and // (We would probably revisit that in bug 1632141)
// only when navigating to another process. this._startLoadingStyleSheets();
// So we fallback on DOCUMENT_EVENTS to be notified when we navigates. When we this._clear();
// navigate within the same process as well as when we navigate to a new process. } else if (resource.name === "dom-complete") {
// (We would probably revisit that in bug 1632141) await this._waitForLoadingStyleSheets();
this._startLoadingStyleSheets(); }
this._clear();
} else if (resource.name === "dom-complete") {
await this._waitForLoadingStyleSheets();
} }
}, },
async _onResourceUpdated({ update }) { async _onResourceUpdated(updates) {
if ( for (const { update } of updates) {
update.resourceType === this._toolbox.resourceWatcher.TYPES.STYLESHEET if (
) { update.resourceType === this._toolbox.resourceWatcher.TYPES.STYLESHEET
const editor = this.editors.find(e => e.resourceId === update.resourceId); ) {
const editor = this.editors.find(
e => e.resourceId === update.resourceId
);
switch (update.updateType) { switch (update.updateType) {
case "style-applied": { case "style-applied": {
editor.onStyleApplied(); editor.onStyleApplied();
break; break;
} }
case "property-change": { case "property-change": {
for (const [property, value] of Object.entries( for (const [property, value] of Object.entries(
update.resourceUpdates update.resourceUpdates
)) { )) {
editor.onPropertyChange(property, value); editor.onPropertyChange(property, value);
}
break;
}
case "media-rules-changed": {
const { mediaRules } = update.resourceUpdates;
editor.onMediaRulesChanged(mediaRules);
break;
} }
break;
}
case "media-rules-changed": {
const { mediaRules } = update.resourceUpdates;
editor.onMediaRulesChanged(mediaRules);
break;
} }
} }
} }

View File

@@ -70,8 +70,10 @@ async function generateConsoleApiStubs() {
// resource to `handleConsoleMessage`, dynamically updated for each command. // resource to `handleConsoleMessage`, dynamically updated for each command.
let handleConsoleMessage = function() {}; let handleConsoleMessage = function() {};
const onConsoleMessage = ({ resource }) => { const onConsoleMessage = resources => {
handleConsoleMessage(resource); for (const resource of resources) {
handleConsoleMessage(resource);
}
}; };
await resourceWatcher.watchResources( await resourceWatcher.watchResources(
[resourceWatcher.TYPES.CONSOLE_MESSAGE], [resourceWatcher.TYPES.CONSOLE_MESSAGE],

View File

@@ -68,8 +68,10 @@ async function generateCssMessageStubs() {
// resource to `handleErrorMessage`, dynamically updated for each command. // resource to `handleErrorMessage`, dynamically updated for each command.
let handleCSSMessage = function() {}; let handleCSSMessage = function() {};
const onCSSMessageAvailable = ({ resource }) => { const onCSSMessageAvailable = resources => {
handleCSSMessage(resource); for (const resource of resources) {
handleCSSMessage(resource);
}
}; };
await resourceWatcher.watchResources([resourceWatcher.TYPES.CSS_MESSAGE], { await resourceWatcher.watchResources([resourceWatcher.TYPES.CSS_MESSAGE], {

View File

@@ -70,11 +70,15 @@ async function generateNetworkEventStubs() {
let addNetworkStub = function() {}; let addNetworkStub = function() {};
let addNetworkUpdateStub = function() {}; let addNetworkUpdateStub = function() {};
const onAvailable = resource => { const onAvailable = resources => {
addNetworkStub(resource); for (const resource of resources) {
addNetworkStub(resource);
}
}; };
const onUpdated = resource => { const onUpdated = updates => {
addNetworkUpdateStub(resource); for (const { resource } of updates) {
addNetworkUpdateStub(resource);
}
}; };
await resourceWatcher.watchResources([resourceWatcher.TYPES.NETWORK_EVENT], { await resourceWatcher.watchResources([resourceWatcher.TYPES.NETWORK_EVENT], {
@@ -85,14 +89,14 @@ async function generateNetworkEventStubs() {
for (const [key, code] of getCommands()) { for (const [key, code] of getCommands()) {
const noExpectedUpdates = 7; const noExpectedUpdates = 7;
const networkEventDone = new Promise(resolve => { const networkEventDone = new Promise(resolve => {
addNetworkStub = ({ resource }) => { addNetworkStub = resource => {
stubs.set(key, getCleanedPacket(key, getOrderedResource(resource))); stubs.set(key, getCleanedPacket(key, getOrderedResource(resource)));
resolve(); resolve();
}; };
}); });
const networkEventUpdateDone = new Promise(resolve => { const networkEventUpdateDone = new Promise(resolve => {
let updateCount = 0; let updateCount = 0;
addNetworkUpdateStub = ({ resource }) => { addNetworkUpdateStub = resource => {
const updateKey = `${key} update`; const updateKey = `${key} update`;
// make sure all the updates have been happened // make sure all the updates have been happened
if (updateCount >= noExpectedUpdates) { if (updateCount >= noExpectedUpdates) {

View File

@@ -72,8 +72,10 @@ async function generatePageErrorStubs() {
// resource to `handleErrorMessage`, dynamically updated for each command. // resource to `handleErrorMessage`, dynamically updated for each command.
let handleErrorMessage = function() {}; let handleErrorMessage = function() {};
const onErrorMessageAvailable = ({ resource }) => { const onErrorMessageAvailable = resources => {
handleErrorMessage(resource); for (const resource of resources) {
handleErrorMessage(resource);
}
}; };
await resourceWatcher.watchResources([resourceWatcher.TYPES.ERROR_MESSAGE], { await resourceWatcher.watchResources([resourceWatcher.TYPES.ERROR_MESSAGE], {
onAvailable: onErrorMessageAvailable, onAvailable: onErrorMessageAvailable,

View File

@@ -80,8 +80,10 @@ async function generatePlatformMessagesStubs() {
// resource to `handlePlatformMessage`, dynamically updated for each command. // resource to `handlePlatformMessage`, dynamically updated for each command.
let handlePlatformMessage = function() {}; let handlePlatformMessage = function() {};
const onPlatformMessageAvailable = ({ resource }) => { const onPlatformMessageAvailable = resources => {
handlePlatformMessage(resource); for (const resource of resources) {
handlePlatformMessage(resource);
}
}; };
await resourceWatcher.watchResources( await resourceWatcher.watchResources(
[resourceWatcher.TYPES.PLATFORM_MESSAGE], [resourceWatcher.TYPES.PLATFORM_MESSAGE],

View File

@@ -998,7 +998,7 @@ async function openMessageInNetmonitor(toolbox, hud, url, urlInConsole) {
await waitFor(() => { await waitFor(() => {
const selected = getSelectedRequest(store.getState()); const selected = getSelectedRequest(store.getState());
return selected && selected.url === url; return selected && selected.url === url;
}, "network entry for the URL wasn't found"); }, `network entry for the URL "${url}" wasn't found`);
ok(true, "The attached url is correct."); ok(true, "The attached url is correct.");

View File

@@ -353,28 +353,34 @@ class WebConsoleUI {
}); });
} }
_onResourceAvailable({ resource }) { _onResourceAvailable(resources) {
if (!this.hud) { if (!this.hud) {
return; return;
} }
const { TYPES } = this.hud.resourceWatcher; for (const resource of resources) {
// Ignore messages forwarded from content processes if we're in fission browser toolbox. const { TYPES } = this.hud.resourceWatcher;
if ( // Ignore messages forwarded from content processes if we're in fission browser toolbox.
!this.wrapper || if (
((resource.resourceType === TYPES.ERROR_MESSAGE || !this.wrapper ||
resource.resourceType === TYPES.CSS_MESSAGE) && ((resource.resourceType === TYPES.ERROR_MESSAGE ||
resource.pageError?.isForwardedFromContentProcess && resource.resourceType === TYPES.CSS_MESSAGE) &&
(this.isBrowserToolboxConsole || this.isBrowserConsole) && resource.pageError?.isForwardedFromContentProcess &&
this.fissionSupport) (this.isBrowserToolboxConsole || this.isBrowserConsole) &&
) { this.fissionSupport)
return; ) {
continue;
}
this.wrapper.dispatchMessageAdd(resource);
} }
this.wrapper.dispatchMessageAdd(resource);
} }
_onResourceUpdated({ resource }) { _onResourceUpdated(updates) {
if (resource.resourceType == this.hud.resourceWatcher.TYPES.NETWORK_EVENT) { for (const { resource } of updates) {
this.wrapper.dispatchMessageUpdate(resource); if (
resource.resourceType == this.hud.resourceWatcher.TYPES.NETWORK_EVENT
) {
this.wrapper.dispatchMessageUpdate(resource);
}
} }
} }

View File

@@ -295,6 +295,8 @@ class ResourceWatcher {
* which describes the resource. * which describes the resource.
*/ */
async _onResourceAvailable({ targetFront, watcherFront }, resources) { async _onResourceAvailable({ targetFront, watcherFront }, resources) {
let currentType = null;
let resourceBuffer = [];
for (let resource of resources) { for (let resource of resources) {
const { resourceType } = resource; const { resourceType } = resource;
@@ -320,12 +322,24 @@ class ResourceWatcher {
}); });
} }
this._availableListeners.emit(resourceType, { if (!currentType) {
resource, currentType = resourceType;
}); }
// Flush the current list of buffered resource if we switch to another type
else if (currentType != resourceType) {
this._availableListeners.emit(currentType, resourceBuffer);
currentType = resourceType;
resourceBuffer = [];
}
resourceBuffer.push(resource);
this._cache.push(resource); this._cache.push(resource);
} }
// Flush the buffered resources if there is any
if (resourceBuffer.length > 0) {
this._availableListeners.emit(currentType, resourceBuffer);
}
} }
/** /**
@@ -361,6 +375,8 @@ class ResourceWatcher {
* } * }
*/ */
async _onResourceUpdated({ targetFront, watcherFront }, updates) { async _onResourceUpdated({ targetFront, watcherFront }, updates) {
let currentType = null;
let resourceBuffer = [];
for (const update of updates) { for (const update of updates) {
const { resourceType, resourceId, resourceUpdates } = update; const { resourceType, resourceId, resourceUpdates } = update;
@@ -385,11 +401,25 @@ class ResourceWatcher {
Object.assign(existingResource, resourceUpdates); Object.assign(existingResource, resourceUpdates);
} }
this._updatedListeners.emit(resourceType, { if (!currentType) {
currentType = resourceType;
}
// Flush the current list of buffered resource if we switch to another type
if (currentType != resourceType) {
this._updatedListeners.emit(currentType, resourceBuffer);
currentType = resourceType;
resourceBuffer = [];
}
resourceBuffer.push({
resource: existingResource, resource: existingResource,
update, update,
}); });
} }
// Flush the buffered resources if there is any
if (resourceBuffer.length > 0) {
this._updatedListeners.emit(currentType, resourceBuffer);
}
} }
/** /**
@@ -397,6 +427,8 @@ class ResourceWatcher {
* See _onResourceAvailable for the argument description. * See _onResourceAvailable for the argument description.
*/ */
async _onResourceDestroyed({ targetFront, watcherFront }, resources) { async _onResourceDestroyed({ targetFront, watcherFront }, resources) {
let currentType = null;
let resourceBuffer = [];
for (const resource of resources) { for (const resource of resources) {
const { resourceType, resourceId } = resource; const { resourceType, resourceId } = resource;
@@ -425,9 +457,21 @@ class ResourceWatcher {
); );
} }
this._destroyedListeners.emit(resourceType, { if (!currentType) {
resource, currentType = resourceType;
}); }
// Flush the current list of buffered resource if we switch to another type
if (currentType != resourceType) {
this._destroyedListeners.emit(currentType, resourceBuffer);
currentType = resourceType;
resourceBuffer = [];
}
resourceBuffer.push(resource);
}
// Flush the buffered resources if there is any
if (resourceBuffer.length > 0) {
this._destroyedListeners.emit(currentType, resourceBuffer);
} }
} }
@@ -508,15 +552,11 @@ class ResourceWatcher {
} }
async _forwardCachedResources(resourceTypes, onAvailable) { async _forwardCachedResources(resourceTypes, onAvailable) {
for (const resource of this._cache) { await onAvailable(
if (resourceTypes.includes(resource.resourceType)) { this._cache.filter(resource =>
await onAvailable({ resourceTypes.includes(resource.resourceType)
resourceType: resource.resourceType, )
targetFront: resource.targetFront, );
resource,
});
}
}
} }
/** /**

View File

@@ -31,7 +31,7 @@ add_task(async function() {
await resourceWatcher.watchResources( await resourceWatcher.watchResources(
[ResourceWatcher.TYPES.CONSOLE_MESSAGE], [ResourceWatcher.TYPES.CONSOLE_MESSAGE],
{ {
onAvailable: ({ resource }) => cachedResources1.push(resource), onAvailable: resources => cachedResources1.push(...resources),
} }
); );
@@ -40,7 +40,7 @@ add_task(async function() {
await resourceWatcher.watchResources( await resourceWatcher.watchResources(
[ResourceWatcher.TYPES.CONSOLE_MESSAGE], [ResourceWatcher.TYPES.CONSOLE_MESSAGE],
{ {
onAvailable: ({ resource }) => cachedResources2.push(resource), onAvailable: resources => cachedResources2.push(...resources),
} }
); );
@@ -73,7 +73,7 @@ add_task(async function() {
await resourceWatcher.watchResources( await resourceWatcher.watchResources(
[ResourceWatcher.TYPES.CONSOLE_MESSAGE], [ResourceWatcher.TYPES.CONSOLE_MESSAGE],
{ {
onAvailable: ({ resource }) => availableResources.push(resource), onAvailable: resources => availableResources.push(...resources),
} }
); );
@@ -90,7 +90,7 @@ add_task(async function() {
await resourceWatcher.watchResources( await resourceWatcher.watchResources(
[ResourceWatcher.TYPES.CONSOLE_MESSAGE], [ResourceWatcher.TYPES.CONSOLE_MESSAGE],
{ {
onAvailable: ({ resource }) => cachedResources.push(resource), onAvailable: resources => cachedResources.push(...resources),
} }
); );
@@ -134,7 +134,7 @@ add_task(async function() {
await resourceWatcher.watchResources( await resourceWatcher.watchResources(
[ResourceWatcher.TYPES.CONSOLE_MESSAGE], [ResourceWatcher.TYPES.CONSOLE_MESSAGE],
{ {
onAvailable: ({ resource }) => cachedResources.push(resource), onAvailable: resources => cachedResources.push(...resources),
} }
); );
@@ -163,7 +163,7 @@ add_task(async function() {
ResourceWatcher.TYPES.ERROR_MESSAGE, ResourceWatcher.TYPES.ERROR_MESSAGE,
], ],
{ {
onAvailable: ({ resource }) => availableResources.push(resource), onAvailable: resources => availableResources.push(...resources),
} }
); );
@@ -194,7 +194,7 @@ add_task(async function() {
ResourceWatcher.TYPES.ERROR_MESSAGE, ResourceWatcher.TYPES.ERROR_MESSAGE,
], ],
{ {
onAvailable: ({ resource }) => cachedResources.push(resource), onAvailable: resources => cachedResources.push(...resources),
} }
); );
@@ -228,7 +228,7 @@ async function testIgnoreExistingResources(isFirstListenerIgnoreExisting) {
await resourceWatcher.watchResources( await resourceWatcher.watchResources(
[ResourceWatcher.TYPES.CONSOLE_MESSAGE], [ResourceWatcher.TYPES.CONSOLE_MESSAGE],
{ {
onAvailable: ({ resource }) => cachedResources1.push(resource), onAvailable: resources => cachedResources1.push(...resources),
ignoreExistingResources: isFirstListenerIgnoreExisting, ignoreExistingResources: isFirstListenerIgnoreExisting,
} }
); );
@@ -238,7 +238,7 @@ async function testIgnoreExistingResources(isFirstListenerIgnoreExisting) {
await resourceWatcher.watchResources( await resourceWatcher.watchResources(
[ResourceWatcher.TYPES.CONSOLE_MESSAGE], [ResourceWatcher.TYPES.CONSOLE_MESSAGE],
{ {
onAvailable: ({ resource }) => cachedResources2.push(resource), onAvailable: resources => cachedResources2.push(...resources),
ignoreExistingResources: !isFirstListenerIgnoreExisting, ignoreExistingResources: !isFirstListenerIgnoreExisting,
} }
); );

View File

@@ -35,20 +35,22 @@ async function testConsoleMessagesResources() {
const expectedExistingCalls = [...expectedExistingConsoleCalls]; const expectedExistingCalls = [...expectedExistingConsoleCalls];
const expectedRuntimeCalls = [...expectedRuntimeConsoleCalls]; const expectedRuntimeCalls = [...expectedRuntimeConsoleCalls];
const onRuntimeDone = new Promise(resolve => (runtimeDoneResolve = resolve)); const onRuntimeDone = new Promise(resolve => (runtimeDoneResolve = resolve));
const onAvailable = ({ resource }) => { const onAvailable = resources => {
is( for (const resource of resources) {
resource.resourceType, is(
ResourceWatcher.TYPES.CONSOLE_MESSAGE, resource.resourceType,
"Received a message" ResourceWatcher.TYPES.CONSOLE_MESSAGE,
); "Received a message"
ok(resource.message, "message is wrapped into a message attribute"); );
const expected = (expectedExistingCalls.length > 0 ok(resource.message, "message is wrapped into a message attribute");
? expectedExistingCalls const expected = (expectedExistingCalls.length > 0
: expectedRuntimeCalls ? expectedExistingCalls
).shift(); : expectedRuntimeCalls
checkConsoleAPICall(resource.message, expected); ).shift();
if (expectedRuntimeCalls.length == 0) { checkConsoleAPICall(resource.message, expected);
runtimeDoneResolve(); if (expectedRuntimeCalls.length == 0) {
runtimeDoneResolve();
}
} }
}; };
@@ -101,7 +103,7 @@ async function testConsoleMessagesResourcesWithIgnoreExistingResources() {
await resourceWatcher.watchResources( await resourceWatcher.watchResources(
[ResourceWatcher.TYPES.CONSOLE_MESSAGE], [ResourceWatcher.TYPES.CONSOLE_MESSAGE],
{ {
onAvailable: ({ resource }) => availableResources.push(resource), onAvailable: resources => availableResources.push(...resources),
ignoreExistingResources: true, ignoreExistingResources: true,
} }
); );

View File

@@ -43,7 +43,7 @@ add_task(async function() {
const availableResources = []; const availableResources = [];
await resourceWatcher.watchResources([ResourceWatcher.TYPES.CSS_CHANGE], { await resourceWatcher.watchResources([ResourceWatcher.TYPES.CSS_CHANGE], {
onAvailable: ({ resource }) => availableResources.push(resource), onAvailable: resources => availableResources.push(...resources),
}); });
assertResource( assertResource(
availableResources[0], availableResources[0],
@@ -83,7 +83,7 @@ add_task(async function() {
info("Check whether ResourceWatcher sends all resources added in this test"); info("Check whether ResourceWatcher sends all resources added in this test");
const existingResources = []; const existingResources = [];
await resourceWatcher.watchResources([ResourceWatcher.TYPES.CSS_CHANGE], { await resourceWatcher.watchResources([ResourceWatcher.TYPES.CSS_CHANGE], {
onAvailable: ({ resource }) => existingResources.push(resource), onAvailable: resources => existingResources.push(...resources),
}); });
await waitUntil(() => existingResources.length === 4); await waitUntil(() => existingResources.length === 4);
is(availableResources[0], existingResources[0], "1st resource is correct"); is(availableResources[0], existingResources[0], "1st resource is correct");

View File

@@ -163,29 +163,33 @@ function setupOnAvailableFunction(targetList, receivedMessages) {
let done; let done;
const onAllMessagesReceived = new Promise(resolve => (done = resolve)); const onAllMessagesReceived = new Promise(resolve => (done = resolve));
const onAvailable = ({ resource }) => { const onAvailable = resources => {
const { pageError } = resource; for (const resource of resources) {
const { pageError } = resource;
is( is(
resource.targetFront, resource.targetFront,
targetList.targetFront, targetList.targetFront,
"The targetFront property is the expected one" "The targetFront property is the expected one"
); );
if (!pageError.sourceName.includes("test_css_messages")) { if (!pageError.sourceName.includes("test_css_messages")) {
info(`Ignore error from unknown source: "${pageError.sourceName}"`); info(`Ignore error from unknown source: "${pageError.sourceName}"`);
return; continue;
} }
const index = receivedMessages.length; const index = receivedMessages.length;
receivedMessages.push(pageError); receivedMessages.push(pageError);
info(`checking received css message #${index}: ${pageError.errorMessage}`); info(
ok(pageError, "The resource has a pageError attribute"); `checking received css message #${index}: ${pageError.errorMessage}`
checkObject(resource, expectedMessages[index]); );
ok(pageError, "The resource has a pageError attribute");
checkObject(resource, expectedMessages[index]);
if (receivedMessages.length == expectedMessages.length) { if (receivedMessages.length == expectedMessages.length) {
done(); done();
}
} }
}; };
return { onAvailable, onAllMessagesReceived }; return { onAvailable, onAllMessagesReceived };

View File

@@ -77,7 +77,7 @@ async function testDocumentEventResourcesWithIgnoreExistingResources() {
info("Check whether the existing document events will not be fired"); info("Check whether the existing document events will not be fired");
const documentEvents = []; const documentEvents = [];
await resourceWatcher.watchResources([ResourceWatcher.TYPES.DOCUMENT_EVENT], { await resourceWatcher.watchResources([ResourceWatcher.TYPES.DOCUMENT_EVENT], {
onAvailable: ({ resource }) => documentEvents.push(resource), onAvailable: resources => documentEvents.push(...resources),
ignoreExistingResources: true, ignoreExistingResources: true,
}); });
is(documentEvents.length, 0, "Existing document events are not fired"); is(documentEvents.length, 0, "Existing document events are not fired");
@@ -129,11 +129,13 @@ function assertEvents(loadingEvent, interactiveEvent, completeEvent) {
class ResourceListener { class ResourceListener {
_listeners = new Map(); _listeners = new Map();
dispatch({ resource }) { dispatch(resources) {
const resolve = this._listeners.get(resource.name); for (const resource of resources) {
if (resolve) { const resolve = this._listeners.get(resource.name);
resolve(resource); if (resolve) {
this._listeners.delete(resource.name); resolve(resource);
this._listeners.delete(resource.name);
}
} }
} }

View File

@@ -52,29 +52,31 @@ async function testErrorMessagesResources() {
let done; let done;
const onAllErrorReceived = new Promise(resolve => (done = resolve)); const onAllErrorReceived = new Promise(resolve => (done = resolve));
const onAvailable = ({ resource }) => { const onAvailable = resources => {
const { pageError } = resource; for (const resource of resources) {
const { pageError } = resource;
is( is(
resource.targetFront, resource.targetFront,
targetList.targetFront, targetList.targetFront,
"The targetFront property is the expected one" "The targetFront property is the expected one"
); );
if (!pageError.sourceName.includes("test_page_errors")) { if (!pageError.sourceName.includes("test_page_errors")) {
info(`Ignore error from unknown source: "${pageError.sourceName}"`); info(`Ignore error from unknown source: "${pageError.sourceName}"`);
return; continue;
} }
const index = receivedMessages.length; const index = receivedMessages.length;
receivedMessages.push(pageError); receivedMessages.push(pageError);
info(`checking received page error #${index}: ${pageError.errorMessage}`); info(`checking received page error #${index}: ${pageError.errorMessage}`);
ok(pageError, "The resource has a pageError attribute"); ok(pageError, "The resource has a pageError attribute");
checkPageErrorResource(pageError, expectedMessages[index]); checkPageErrorResource(pageError, expectedMessages[index]);
if (receivedMessages.length == expectedMessages.length) { if (receivedMessages.length == expectedMessages.length) {
done(); done();
}
} }
}; };
@@ -117,7 +119,7 @@ async function testErrorMessagesResourcesWithIgnoreExistingResources() {
const availableResources = []; const availableResources = [];
await resourceWatcher.watchResources([ResourceWatcher.TYPES.ERROR_MESSAGE], { await resourceWatcher.watchResources([ResourceWatcher.TYPES.ERROR_MESSAGE], {
onAvailable: ({ resource }) => availableResources.push(resource), onAvailable: resources => availableResources.push(...resources),
ignoreExistingResources: true, ignoreExistingResources: true,
}); });
is( is(

View File

@@ -32,7 +32,7 @@ add_task(async function() {
"Start to watch the available resources in order to compare with resources gotten from getAllResources" "Start to watch the available resources in order to compare with resources gotten from getAllResources"
); );
const availableResources = []; const availableResources = [];
const onAvailable = ({ resource }) => availableResources.push(resource); const onAvailable = resources => availableResources.push(...resources);
await resourceWatcher.watchResources( await resourceWatcher.watchResources(
[ResourceWatcher.TYPES.CONSOLE_MESSAGE], [ResourceWatcher.TYPES.CONSOLE_MESSAGE],
{ onAvailable } { onAvailable }

View File

@@ -128,38 +128,42 @@ async function testNetworkEventResources(options) {
const waitOnAllExpectedUpdatesForExistingRequests = new Promise(resolve => { const waitOnAllExpectedUpdatesForExistingRequests = new Promise(resolve => {
const existingRequestUrl = `${EXAMPLE_DOMAIN}existing_post.html`; const existingRequestUrl = `${EXAMPLE_DOMAIN}existing_post.html`;
onResourceAvailable = ({ resource }) => { onResourceAvailable = resources => {
// A blocked request would only have two updates so lets also resolve here for (const resource of resources) {
if ( // A blocked request would only have two updates so lets also resolve here
resource.request.url == existingRequestUrl && if (
resource.blockedReason && resource.request.url == existingRequestUrl &&
resource.updates.length == 2 resource.blockedReason &&
) { resource.updates.length == 2
// Reset the updates expectation as the request is blocked ) {
if (options.expectedResourcesOnAvailable[resource.request.url]) { // Reset the updates expectation as the request is blocked
options.expectedResourcesOnAvailable[resource.request.url].updates = [ if (options.expectedResourcesOnAvailable[resource.request.url]) {
...resource.updates, options.expectedResourcesOnAvailable[
]; resource.request.url
].updates = [...resource.updates];
}
resolve();
} }
resolve();
} }
}; };
onResourceUpdated = ({ resource }) => { onResourceUpdated = updates => {
// Wait until all the update events have fired for the existing request. for (const { resource } of updates) {
// Handle both blocked and unblocked requests // Wait until all the update events have fired for the existing request.
if ( // Handle both blocked and unblocked requests
resource.request.url == existingRequestUrl && if (
(resource.updates.length == 8 || resource.request.url == existingRequestUrl &&
(resource.blockedReason && resource.updates.length == 2)) (resource.updates.length == 8 ||
) { (resource.blockedReason && resource.updates.length == 2))
// Makes sure the expectation always correct (for either blocked or unblocked requests) ) {
if (options.expectedResourcesOnAvailable[resource.request.url]) { // Makes sure the expectation always correct (for either blocked or unblocked requests)
options.expectedResourcesOnAvailable[resource.request.url].updates = [ if (options.expectedResourcesOnAvailable[resource.request.url]) {
...resource.updates, options.expectedResourcesOnAvailable[
]; resource.request.url
].updates = [...resource.updates];
}
resolve();
} }
resolve();
} }
}; };
@@ -190,34 +194,38 @@ async function testNetworkEventResources(options) {
() => expectedOnUpdatedCounts == 0 () => expectedOnUpdatedCounts == 0
); );
const onAvailable = ({ targetFront, resource }) => { const onAvailable = resources => {
is( for (const resource of resources) {
resource.resourceType, is(
ResourceWatcher.TYPES.NETWORK_EVENT, resource.resourceType,
"Received a network event resource" ResourceWatcher.TYPES.NETWORK_EVENT,
); "Received a network event resource"
actualResourcesOnAvailable[resource.request.url] = { );
resourceId: resource.resourceId, actualResourcesOnAvailable[resource.request.url] = {
resourceType: resource.resourceType, resourceId: resource.resourceId,
request: resource.request, resourceType: resource.resourceType,
updates: [...resource.updates], request: resource.request,
}; updates: [...resource.updates],
expectedOnAvailableCounts--; };
expectedOnAvailableCounts--;
}
}; };
const onUpdated = ({ targetFront, resource }) => { const onUpdated = updates => {
is( for (const { resource } of updates) {
resource.resourceType, is(
ResourceWatcher.TYPES.NETWORK_EVENT, resource.resourceType,
"Received a network update event resource" ResourceWatcher.TYPES.NETWORK_EVENT,
); "Received a network update event resource"
actualResourcesOnUpdated[resource.request.url] = { );
resourceId: resource.resourceId, actualResourcesOnUpdated[resource.request.url] = {
resourceType: resource.resourceType, resourceId: resource.resourceId,
request: resource.request, resourceType: resource.resourceType,
updates: [...resource.updates], request: resource.request,
}; updates: [...resource.updates],
expectedOnUpdatedCounts--; };
expectedOnUpdatedCounts--;
}
}; };
await resourceWatcher.watchResources([ResourceWatcher.TYPES.NETWORK_EVENT], { await resourceWatcher.watchResources([ResourceWatcher.TYPES.NETWORK_EVENT], {

View File

@@ -42,31 +42,33 @@ async function testPlatformMessagesResources() {
let done; let done;
const onAllMessagesReceived = new Promise(resolve => (done = resolve)); const onAllMessagesReceived = new Promise(resolve => (done = resolve));
const onAvailable = ({ resource }) => { const onAvailable = resources => {
if (!expectedMessages.includes(resource.message)) { for (const resource of resources) {
return; if (!expectedMessages.includes(resource.message)) {
} continue;
}
is( is(
resource.targetFront, resource.targetFront,
targetList.targetFront, targetList.targetFront,
"The targetFront property is the expected one" "The targetFront property is the expected one"
); );
receivedMessages.push(resource.message); receivedMessages.push(resource.message);
is( is(
resource.message, resource.message,
expectedMessages[receivedMessages.length - 1], expectedMessages[receivedMessages.length - 1],
`Received the expected «${resource.message}» message, in the expected order` `Received the expected «${resource.message}» message, in the expected order`
); );
ok( ok(
resource.timeStamp.toString().match(/^\d+$/), resource.timeStamp.toString().match(/^\d+$/),
"The resource has a timeStamp property" "The resource has a timeStamp property"
); );
if (receivedMessages.length == expectedMessages.length) { if (receivedMessages.length == expectedMessages.length) {
done(); done();
}
} }
}; };
@@ -110,12 +112,14 @@ async function testPlatformMessagesResourcesWithIgnoreExistingResources() {
await resourceWatcher.watchResources( await resourceWatcher.watchResources(
[ResourceWatcher.TYPES.PLATFORM_MESSAGE], [ResourceWatcher.TYPES.PLATFORM_MESSAGE],
{ {
onAvailable: ({ resource }) => { onAvailable: resources => {
if (!expectedMessages.includes(resource.message)) { for (const resource of resources) {
return; if (!expectedMessages.includes(resource.message)) {
} continue;
}
availableResources.push(resource); availableResources.push(resource);
}
}, },
ignoreExistingResources: true, ignoreExistingResources: true,
} }

View File

@@ -34,7 +34,7 @@ add_task(async function() {
info("Call watchResources([ROOT_NODE], ...)"); info("Call watchResources([ROOT_NODE], ...)");
let onAvailableCounter = 0; let onAvailableCounter = 0;
const onAvailable = () => onAvailableCounter++; const onAvailable = resources => (onAvailableCounter += resources.length);
await resourceWatcher.watchResources([ResourceWatcher.TYPES.ROOT_NODE], { await resourceWatcher.watchResources([ResourceWatcher.TYPES.ROOT_NODE], {
onAvailable, onAvailable,
}); });
@@ -91,13 +91,13 @@ add_task(async function testRootNodeFrontIsCorrect() {
let rootNodeResolve; let rootNodeResolve;
let rootNodePromise = new Promise(r => (rootNodeResolve = r)); let rootNodePromise = new Promise(r => (rootNodeResolve = r));
const onAvailable = rootNodeFront => rootNodeResolve(rootNodeFront); const onAvailable = ([rootNodeFront]) => rootNodeResolve(rootNodeFront);
await resourceWatcher.watchResources([ResourceWatcher.TYPES.ROOT_NODE], { await resourceWatcher.watchResources([ResourceWatcher.TYPES.ROOT_NODE], {
onAvailable, onAvailable,
}); });
info("Wait until onAvailable has been called"); info("Wait until onAvailable has been called");
const { resource: root1 } = await rootNodePromise; const root1 = await rootNodePromise;
ok(!!root1, "onAvailable has been called with a valid argument"); ok(!!root1, "onAvailable has been called with a valid argument");
is( is(
root1.resourceType, root1.resourceType,
@@ -113,7 +113,7 @@ add_task(async function testRootNodeFrontIsCorrect() {
rootNodePromise = new Promise(r => (rootNodeResolve = r)); rootNodePromise = new Promise(r => (rootNodeResolve = r));
browser.reload(); browser.reload();
const { resource: root2 } = await rootNodePromise; const root2 = await rootNodePromise;
ok( ok(
root1 !== root2, root1 !== root2,
"onAvailable has been called with a different node front after reload" "onAvailable has been called with a different node front after reload"
@@ -122,7 +122,7 @@ add_task(async function testRootNodeFrontIsCorrect() {
info("Navigate to another URL"); info("Navigate to another URL");
rootNodePromise = new Promise(r => (rootNodeResolve = r)); rootNodePromise = new Promise(r => (rootNodeResolve = r));
BrowserTestUtils.loadURI(browser, `data:text/html,<div id=div3>`); BrowserTestUtils.loadURI(browser, `data:text/html,<div id=div3>`);
const { resource: root3 } = await rootNodePromise; const root3 = await rootNodePromise;
info("Check we can query an expected node under the retrieved root"); info("Check we can query an expected node under the retrieved root");
const div3 = await root3.walkerFront.querySelector(root3, "div"); const div3 = await root3.walkerFront.querySelector(root3, "div");
is(div3.getAttribute("id"), "div3", "Correct root node retrieved"); is(div3.getAttribute("id"), "div3", "Correct root node retrieved");

View File

@@ -32,9 +32,11 @@ add_task(async function() {
// We are only interested in console messages as a resource, the ROOT_NODE one // We are only interested in console messages as a resource, the ROOT_NODE one
// is here to test the ResourceWatcher::unwatchResources API with several resources. // is here to test the ResourceWatcher::unwatchResources API with several resources.
const receivedMessages = []; const receivedMessages = [];
const onAvailable = ({ resource }) => { const onAvailable = resources => {
if (resource.resourceType === CONSOLE_MESSAGE) { for (const resource of resources) {
receivedMessages.push(resource); if (resource.resourceType === CONSOLE_MESSAGE) {
receivedMessages.push(resource);
}
} }
}; };

View File

@@ -106,7 +106,7 @@ add_task(async function() {
info("Check whether ResourceWatcher gets existing stylesheet"); info("Check whether ResourceWatcher gets existing stylesheet");
const availableResources = []; const availableResources = [];
await resourceWatcher.watchResources([ResourceWatcher.TYPES.STYLESHEET], { await resourceWatcher.watchResources([ResourceWatcher.TYPES.STYLESHEET], {
onAvailable: ({ resource }) => availableResources.push(resource), onAvailable: resources => availableResources.push(...resources),
}); });
is( is(
@@ -176,8 +176,8 @@ add_task(async function() {
const availableResources = []; const availableResources = [];
const updates = []; const updates = [];
await resourceWatcher.watchResources([ResourceWatcher.TYPES.STYLESHEET], { await resourceWatcher.watchResources([ResourceWatcher.TYPES.STYLESHEET], {
onAvailable: ({ resource }) => availableResources.push(resource), onAvailable: resources => availableResources.push(...resources),
onUpdated: ({ resource, update }) => updates.push({ resource, update }), onUpdated: newUpdates => updates.push(...newUpdates),
}); });
is( is(
availableResources.length, availableResources.length,

View File

@@ -24,7 +24,7 @@ add_task(async function() {
info("Check available resources at initial"); info("Check available resources at initial");
const availableResources = []; const availableResources = [];
await resourceWatcher.watchResources([ResourceWatcher.TYPES.WEBSOCKET], { await resourceWatcher.watchResources([ResourceWatcher.TYPES.WEBSOCKET], {
onAvailable: ({ resource }) => availableResources.push(resource), onAvailable: resources => availableResources.push(...resources),
}); });
is( is(
availableResources.length, availableResources.length,
@@ -101,7 +101,7 @@ add_task(async function() {
info("Check existing resources"); info("Check existing resources");
const existingResources = []; const existingResources = [];
await resourceWatcher.watchResources([ResourceWatcher.TYPES.WEBSOCKET], { await resourceWatcher.watchResources([ResourceWatcher.TYPES.WEBSOCKET], {
onAvailable: ({ resource }) => existingResources.push(resource), onAvailable: resources => existingResources.push(...resources),
}); });
is( is(
availableResources.length, availableResources.length,

View File

@@ -742,11 +742,14 @@ class DevToolsExtensionPageContextParent extends ExtensionPageContextParent {
await this._currentDevToolsTarget.attach(); await this._currentDevToolsTarget.attach();
} }
async _onResourceAvailable({ targetFront, resource }) { async _onResourceAvailable(resources) {
if (targetFront.isTopLevel && resource.name === "dom-complete") { for (const resource of resources) {
const url = targetFront.localTab.linkedBrowser.currentURI.spec; const { targetFront } = resource;
for (const listener of this._onNavigatedListeners) { if (targetFront.isTopLevel && resource.name === "dom-complete") {
listener(url); const url = targetFront.localTab.linkedBrowser.currentURI.spec;
for (const listener of this._onNavigatedListeners) {
listener(url);
}
} }
} }
} }