Bug 1305161 - New console frontend: Improve performance of showing cached messages. r=bgrins

MozReview-Commit-ID: 8NIDqj5nRol
This commit is contained in:
Lin Clark 2016-09-27 10:09:51 -07:00
Родитель 700269e5cd
Коммит 0a27dfb295
19 изменённых файлов: 130 добавлений и 48 удалений

Просмотреть файл

@ -0,0 +1,20 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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 { BATCH_ACTIONS } = require("../constants");
function batchActions(batchedActions) {
return {
type: BATCH_ACTIONS,
actions: batchedActions,
};
}
module.exports = {
batchActions
};

Просмотреть файл

@ -0,0 +1,18 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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 actionModules = [
"enhancers",
"filters",
"messages",
"ui",
].map(filename => require(`./${filename}`));
const actions = Object.assign({}, ...actionModules);
module.exports = actions;

Просмотреть файл

@ -10,7 +10,7 @@ const {
prepareMessage prepareMessage
} = require("devtools/client/webconsole/new-console-output/utils/messages"); } = require("devtools/client/webconsole/new-console-output/utils/messages");
const { IdGenerator } = require("devtools/client/webconsole/new-console-output/utils/id-generator"); const { IdGenerator } = require("devtools/client/webconsole/new-console-output/utils/id-generator");
const { batchActions } = require("devtools/client/webconsole/new-console-output/actions/enhancers");
const { const {
MESSAGE_ADD, MESSAGE_ADD,
MESSAGES_CLEAR, MESSAGES_CLEAR,
@ -22,21 +22,22 @@ const {
const defaultIdGenerator = new IdGenerator(); const defaultIdGenerator = new IdGenerator();
function messageAdd(packet, idGenerator = null) { function messageAdd(packet, idGenerator = null) {
return (dispatch) => { if (idGenerator == null) {
if (idGenerator == null) { idGenerator = defaultIdGenerator;
idGenerator = defaultIdGenerator; }
} let message = prepareMessage(packet, idGenerator);
let message = prepareMessage(packet, idGenerator); const addMessageAction = {
type: MESSAGE_ADD,
if (message.type === MESSAGE_TYPE.CLEAR) { message
dispatch(messagesClear());
}
dispatch({
type: MESSAGE_ADD,
message
});
}; };
if (message.type === MESSAGE_TYPE.CLEAR) {
return batchActions([
messagesClear(),
addMessageAction,
]);
}
return addMessageAction;
} }
function messagesClear() { function messagesClear() {
@ -59,7 +60,9 @@ function messageClose(id) {
}; };
} }
exports.messageAdd = messageAdd; module.exports = {
exports.messagesClear = messagesClear; messageAdd,
exports.messageOpen = messageOpen; messagesClear,
exports.messageClose = messageClose; messageOpen,
messageClose,
};

Просмотреть файл

@ -4,7 +4,9 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules( DevToolsModules(
'enhancers.js',
'filters.js', 'filters.js',
'index.js',
'messages.js', 'messages.js',
'ui.js', 'ui.js',
) )

Просмотреть файл

@ -12,9 +12,9 @@ const {
const { connect } = require("devtools/client/shared/vendor/react-redux"); const { connect } = require("devtools/client/shared/vendor/react-redux");
const { getAllFilters } = require("devtools/client/webconsole/new-console-output/selectors/filters"); const { getAllFilters } = require("devtools/client/webconsole/new-console-output/selectors/filters");
const { getAllUi } = require("devtools/client/webconsole/new-console-output/selectors/ui"); const { getAllUi } = require("devtools/client/webconsole/new-console-output/selectors/ui");
const { filterTextSet, filtersClear } = require("devtools/client/webconsole/new-console-output/actions/filters"); const { filterTextSet, filtersClear } = require("devtools/client/webconsole/new-console-output/actions/index");
const { messagesClear } = require("devtools/client/webconsole/new-console-output/actions/messages"); const { messagesClear } = require("devtools/client/webconsole/new-console-output/actions/index");
const uiActions = require("devtools/client/webconsole/new-console-output/actions/ui"); const uiActions = require("devtools/client/webconsole/new-console-output/actions/index");
const { const {
MESSAGE_LEVEL MESSAGE_LEVEL
} = require("../constants"); } = require("../constants");

Просмотреть файл

@ -8,7 +8,7 @@ const {
DOM: dom, DOM: dom,
PropTypes PropTypes
} = require("devtools/client/shared/vendor/react"); } = require("devtools/client/shared/vendor/react");
const actions = require("devtools/client/webconsole/new-console-output/actions/filters"); const actions = require("devtools/client/webconsole/new-console-output/actions/index");
const FilterButton = createClass({ const FilterButton = createClass({

Просмотреть файл

@ -18,7 +18,7 @@ const GripMessageBody = createFactory(require("devtools/client/webconsole/new-co
const MessageRepeat = createFactory(require("devtools/client/webconsole/new-console-output/components/message-repeat").MessageRepeat); const MessageRepeat = createFactory(require("devtools/client/webconsole/new-console-output/components/message-repeat").MessageRepeat);
const MessageIcon = createFactory(require("devtools/client/webconsole/new-console-output/components/message-icon").MessageIcon); const MessageIcon = createFactory(require("devtools/client/webconsole/new-console-output/components/message-icon").MessageIcon);
const CollapseButton = createFactory(require("devtools/client/webconsole/new-console-output/components/collapse-button").CollapseButton); const CollapseButton = createFactory(require("devtools/client/webconsole/new-console-output/components/collapse-button").CollapseButton);
const actions = require("devtools/client/webconsole/new-console-output/actions/messages"); const actions = require("devtools/client/webconsole/new-console-output/actions/index");
ConsoleApiCall.displayName = "ConsoleApiCall"; ConsoleApiCall.displayName = "ConsoleApiCall";

Просмотреть файл

@ -15,7 +15,7 @@ const {
const MessageIcon = createFactory(require("devtools/client/webconsole/new-console-output/components/message-icon").MessageIcon); const MessageIcon = createFactory(require("devtools/client/webconsole/new-console-output/components/message-icon").MessageIcon);
const CollapseButton = createFactory(require("devtools/client/webconsole/new-console-output/components/collapse-button").CollapseButton); const CollapseButton = createFactory(require("devtools/client/webconsole/new-console-output/components/collapse-button").CollapseButton);
const { l10n } = require("devtools/client/webconsole/new-console-output/utils/messages"); const { l10n } = require("devtools/client/webconsole/new-console-output/utils/messages");
const actions = require("devtools/client/webconsole/new-console-output/actions/messages"); const actions = require("devtools/client/webconsole/new-console-output/actions/index");
NetworkEventMessage.displayName = "NetworkEventMessage"; NetworkEventMessage.displayName = "NetworkEventMessage";

Просмотреть файл

@ -18,7 +18,7 @@ const CollapseButton = createFactory(require("devtools/client/webconsole/new-con
const MessageRepeat = createFactory(require("devtools/client/webconsole/new-console-output/components/message-repeat").MessageRepeat); const MessageRepeat = createFactory(require("devtools/client/webconsole/new-console-output/components/message-repeat").MessageRepeat);
const MessageIcon = createFactory(require("devtools/client/webconsole/new-console-output/components/message-icon").MessageIcon); const MessageIcon = createFactory(require("devtools/client/webconsole/new-console-output/components/message-icon").MessageIcon);
const actions = require("devtools/client/webconsole/new-console-output/actions/messages"); const actions = require("devtools/client/webconsole/new-console-output/actions/index");
PageError.displayName = "PageError"; PageError.displayName = "PageError";

Просмотреть файл

@ -6,6 +6,7 @@
"use strict"; "use strict";
const actionTypes = { const actionTypes = {
BATCH_ACTIONS: "BATCH_ACTIONS",
MESSAGE_ADD: "MESSAGE_ADD", MESSAGE_ADD: "MESSAGE_ADD",
MESSAGES_CLEAR: "MESSAGES_CLEAR", MESSAGES_CLEAR: "MESSAGES_CLEAR",
MESSAGE_OPEN: "MESSAGE_OPEN", MESSAGE_OPEN: "MESSAGE_OPEN",

Просмотреть файл

@ -8,7 +8,7 @@ const React = require("devtools/client/shared/vendor/react");
const ReactDOM = require("devtools/client/shared/vendor/react-dom"); const ReactDOM = require("devtools/client/shared/vendor/react-dom");
const { Provider } = require("devtools/client/shared/vendor/react-redux"); const { Provider } = require("devtools/client/shared/vendor/react-redux");
const actions = require("devtools/client/webconsole/new-console-output/actions/messages"); const actions = require("devtools/client/webconsole/new-console-output/actions/index");
const { configureStore } = require("devtools/client/webconsole/new-console-output/store"); const { configureStore } = require("devtools/client/webconsole/new-console-output/store");
const ConsoleOutput = React.createFactory(require("devtools/client/webconsole/new-console-output/components/console-output")); const ConsoleOutput = React.createFactory(require("devtools/client/webconsole/new-console-output/components/console-output"));
@ -51,6 +51,10 @@ NewConsoleOutputWrapper.prototype = {
dispatchMessageAdd: (message) => { dispatchMessageAdd: (message) => {
store.dispatch(actions.messageAdd(message)); store.dispatch(actions.messageAdd(message));
}, },
dispatchMessagesAdd: (messages) => {
const batchedActions = messages.map(message => actions.messageAdd(message));
store.dispatch(actions.batchActions(batchedActions));
},
dispatchMessagesClear: () => { dispatchMessagesClear: () => {
store.dispatch(actions.messagesClear()); store.dispatch(actions.messagesClear());
}, },

Просмотреть файл

@ -5,8 +5,14 @@
const {FilterState} = require("devtools/client/webconsole/new-console-output/reducers/filters"); const {FilterState} = require("devtools/client/webconsole/new-console-output/reducers/filters");
const {PrefState} = require("devtools/client/webconsole/new-console-output/reducers/prefs"); const {PrefState} = require("devtools/client/webconsole/new-console-output/reducers/prefs");
const { applyMiddleware, combineReducers, createStore } = require("devtools/client/shared/vendor/redux"); const {
applyMiddleware,
combineReducers,
compose,
createStore
} = require("devtools/client/shared/vendor/redux");
const { thunk } = require("devtools/client/shared/redux/middleware/thunk"); const { thunk } = require("devtools/client/shared/redux/middleware/thunk");
const constants = require("devtools/client/webconsole/new-console-output/constants");
const { reducers } = require("./reducers/index"); const { reducers } = require("./reducers/index");
const Services = require("Services"); const Services = require("Services");
@ -28,10 +34,33 @@ function configureStore() {
return createStore( return createStore(
combineReducers(reducers), combineReducers(reducers),
initialState, initialState,
applyMiddleware(thunk) compose(applyMiddleware(thunk), enableBatching())
); );
} }
/**
* A enhancer for the store to handle batched actions.
*/
function enableBatching() {
return next => (reducer, initialState, enhancer) => {
function batchingReducer(state, action) {
switch (action.type) {
case constants.BATCH_ACTIONS:
return action.actions.reduce(batchingReducer, state);
default:
return reducer(state, action);
}
}
if (typeof initialState === "function" && typeof enhancer === "undefined") {
enhancer = initialState;
initialState = undefined;
}
return next(batchingReducer, initialState, enhancer);
};
}
// Provide the store factory for test code so that each test is working with // Provide the store factory for test code so that each test is working with
// its own instance. // its own instance.
module.exports.configureStore = configureStore; module.exports.configureStore = configureStore;

Просмотреть файл

@ -2,7 +2,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ */ http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict"; "use strict";
const actions = require("devtools/client/webconsole/new-console-output/actions/filters"); const actions = require("devtools/client/webconsole/new-console-output/actions/index");
const { const {
FILTER_TEXT_SET, FILTER_TEXT_SET,
FILTER_TOGGLE, FILTER_TOGGLE,

Просмотреть файл

@ -26,16 +26,16 @@ describe("Message actions:", () => {
const store = mockStore({}); const store = mockStore({});
store.dispatch(actions.messageAdd(packet)); store.dispatch(actions.messageAdd(packet));
const expectedActions = store.getActions(); const actualActions = store.getActions();
expect(expectedActions.length).toEqual(1); expect(actualActions.length).toEqual(1);
const addAction = expectedActions[0]; const addAction = actualActions[0];
const {message} = addAction; const {message} = addAction;
const expected = { const expectedAction = {
type: constants.MESSAGE_ADD, type: constants.MESSAGE_ADD,
message: stubPreparedMessages.get("console.log('foobar', 'test')") message: stubPreparedMessages.get("console.log('foobar', 'test')")
}; };
expect(message.toJS()).toEqual(expected.message.toJS()); expect(message.toJS()).toEqual(expectedAction.message.toJS());
}); });
it("dispatches expected actions given a console.clear packet", () => { it("dispatches expected actions given a console.clear packet", () => {
@ -43,19 +43,19 @@ describe("Message actions:", () => {
const store = mockStore({}); const store = mockStore({});
store.dispatch(actions.messageAdd(packet)); store.dispatch(actions.messageAdd(packet));
const expectedActions = store.getActions(); const actualActions = store.getActions();
expect(expectedActions.length).toEqual(2); expect(actualActions.length).toEqual(1);
const [clearAction, addAction] = expectedActions; const [clearAction, addAction] = actualActions[0].actions;
expect(clearAction.type).toEqual(constants.MESSAGES_CLEAR); expect(clearAction.type).toEqual(constants.MESSAGES_CLEAR);
const {message} = addAction; const {message} = addAction;
const expected = { const expectedAction = {
type: constants.MESSAGE_ADD, type: constants.MESSAGE_ADD,
message: stubPreparedMessages.get("console.clear()") message: stubPreparedMessages.get("console.clear()")
}; };
expect(addAction.type).toEqual(constants.MESSAGE_ADD); expect(addAction.type).toEqual(constants.MESSAGE_ADD);
expect(message.toJS()).toEqual(expected.message.toJS()); expect(message.toJS()).toEqual(expectedAction.message.toJS());
}); });
}); });

Просмотреть файл

@ -2,7 +2,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ */ http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict"; "use strict";
const actions = require("devtools/client/webconsole/new-console-output/actions/ui"); const actions = require("devtools/client/webconsole/new-console-output/actions/index");
const { const {
FILTER_BAR_TOGGLE FILTER_BAR_TOGGLE
} = require("devtools/client/webconsole/new-console-output/constants"); } = require("devtools/client/webconsole/new-console-output/constants");

Просмотреть файл

@ -58,7 +58,7 @@ function timeit(cb) {
window.onload = Task.async(function* () { window.onload = Task.async(function* () {
const { configureStore } = browserRequire("devtools/client/webconsole/new-console-output/store"); const { configureStore } = browserRequire("devtools/client/webconsole/new-console-output/store");
const { filterTextSet, filtersClear } = browserRequire("devtools/client/webconsole/new-console-output/actions/filters"); const { filterTextSet, filtersClear } = browserRequire("devtools/client/webconsole/new-console-output/actions/index");
const NewConsoleOutputWrapper = browserRequire("devtools/client/webconsole/new-console-output/new-console-output-wrapper"); const NewConsoleOutputWrapper = browserRequire("devtools/client/webconsole/new-console-output/new-console-output-wrapper");
const wrapper = new NewConsoleOutputWrapper(document.querySelector("#output"), {}); const wrapper = new NewConsoleOutputWrapper(document.querySelector("#output"), {});

Просмотреть файл

@ -7,7 +7,7 @@ let ReactDOM = require("devtools/client/shared/vendor/react-dom");
let React = require("devtools/client/shared/vendor/react"); let React = require("devtools/client/shared/vendor/react");
var TestUtils = React.addons.TestUtils; var TestUtils = React.addons.TestUtils;
const actions = require("devtools/client/webconsole/new-console-output/actions/messages"); const actions = require("devtools/client/webconsole/new-console-output/actions/index");
const { configureStore } = require("devtools/client/webconsole/new-console-output/store"); const { configureStore } = require("devtools/client/webconsole/new-console-output/store");
const { IdGenerator } = require("devtools/client/webconsole/new-console-output/utils/id-generator"); const { IdGenerator } = require("devtools/client/webconsole/new-console-output/utils/id-generator");
const { stubPackets } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs/index"); const { stubPackets } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs/index");

Просмотреть файл

@ -5,8 +5,8 @@
const expect = require("expect"); const expect = require("expect");
const actions = require("devtools/client/webconsole/new-console-output/actions/filters"); const actions = require("devtools/client/webconsole/new-console-output/actions/index");
const { messageAdd } = require("devtools/client/webconsole/new-console-output/actions/messages"); const { messageAdd } = require("devtools/client/webconsole/new-console-output/actions/index");
const { ConsoleCommand } = require("devtools/client/webconsole/new-console-output/types"); const { ConsoleCommand } = require("devtools/client/webconsole/new-console-output/types");
const { getAllMessages } = require("devtools/client/webconsole/new-console-output/selectors/messages"); const { getAllMessages } = require("devtools/client/webconsole/new-console-output/selectors/messages");
const { getAllFilters } = require("devtools/client/webconsole/new-console-output/selectors/filters"); const { getAllFilters } = require("devtools/client/webconsole/new-console-output/selectors/filters");

Просмотреть файл

@ -3272,6 +3272,13 @@ WebConsoleConnectionProxy.prototype = {
}); });
}, },
/**
* Batched dispatch of messages.
*/
dispatchMessagesAdd: function(packets) {
this.webConsoleFrame.newConsoleOutput.dispatchMessagesAdd(packets);
},
/** /**
* The "cachedMessages" response handler. * The "cachedMessages" response handler.
* *
@ -3301,9 +3308,7 @@ WebConsoleConnectionProxy.prototype = {
// Filter out CSS page errors. // Filter out CSS page errors.
messages = messages.filter(message => !(message._type == "PageError" messages = messages.filter(message => !(message._type == "PageError"
&& Utils.categoryForScriptError(message) === CATEGORY_CSS)); && Utils.categoryForScriptError(message) === CATEGORY_CSS));
for (let packet of messages) { this.dispatchMessagesAdd(messages);
this.dispatchMessageAdd(packet);
}
} else { } else {
this.webConsoleFrame.displayCachedMessages(messages); this.webConsoleFrame.displayCachedMessages(messages);
if (!this._hasNativeConsoleAPI) { if (!this._hasNativeConsoleAPI) {