mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 09:45:41 +00:00
Bug 1514815 - Keep console scrolled to bottom when rendering SmartTrace; r=bgrins.
Depends on D14999 Differential Revision: https://phabricator.services.mozilla.com/D15010 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
e753e09155
commit
ece2924f8d
@ -67,6 +67,7 @@ class ConsoleOutput extends Component {
|
|||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.onContextMenu = this.onContextMenu.bind(this);
|
this.onContextMenu = this.onContextMenu.bind(this);
|
||||||
|
this.maybeScrollToBottom = this.maybeScrollToBottom.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -125,6 +126,10 @@ class ConsoleOutput extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
|
this.maybeScrollToBottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
maybeScrollToBottom() {
|
||||||
if (this.shouldScrollBottom) {
|
if (this.shouldScrollBottom) {
|
||||||
scrollToBottom(this.outputNode);
|
scrollToBottom(this.outputNode);
|
||||||
}
|
}
|
||||||
@ -177,6 +182,7 @@ class ConsoleOutput extends Component {
|
|||||||
pausedExecutionPoint,
|
pausedExecutionPoint,
|
||||||
getMessage: () => messages.get(messageId),
|
getMessage: () => messages.get(messageId),
|
||||||
isPaused: pausedMessage && pausedMessage.id == messageId,
|
isPaused: pausedMessage && pausedMessage.id == messageId,
|
||||||
|
maybeScrollToBottom: this.maybeScrollToBottom,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -36,6 +36,7 @@ GripMessageBody.propTypes = {
|
|||||||
escapeWhitespace: PropTypes.bool,
|
escapeWhitespace: PropTypes.bool,
|
||||||
type: PropTypes.string,
|
type: PropTypes.string,
|
||||||
helperType: PropTypes.string,
|
helperType: PropTypes.string,
|
||||||
|
maybeScrollToBottom: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
GripMessageBody.defaultProps = {
|
GripMessageBody.defaultProps = {
|
||||||
@ -51,6 +52,7 @@ function GripMessageBody(props) {
|
|||||||
escapeWhitespace,
|
escapeWhitespace,
|
||||||
mode = MODE.LONG,
|
mode = MODE.LONG,
|
||||||
dispatch,
|
dispatch,
|
||||||
|
maybeScrollToBottom,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
let styleObject;
|
let styleObject;
|
||||||
@ -61,6 +63,7 @@ function GripMessageBody(props) {
|
|||||||
const objectInspectorProps = {
|
const objectInspectorProps = {
|
||||||
autoExpandDepth: shouldAutoExpandObjectInspector(props) ? 1 : 0,
|
autoExpandDepth: shouldAutoExpandObjectInspector(props) ? 1 : 0,
|
||||||
mode,
|
mode,
|
||||||
|
maybeScrollToBottom,
|
||||||
// TODO: we disable focus since the tabbing trail is a bit weird in the output (e.g.
|
// TODO: we disable focus since the tabbing trail is a bit weird in the output (e.g.
|
||||||
// location links are not focused). Let's remove the property below when we found and
|
// location links are not focused). Let's remove the property below when we found and
|
||||||
// fixed the issue (See Bug 1456060).
|
// fixed the issue (See Bug 1456060).
|
||||||
|
@ -70,6 +70,7 @@ class Message extends Component {
|
|||||||
frame: PropTypes.any,
|
frame: PropTypes.any,
|
||||||
})),
|
})),
|
||||||
isPaused: PropTypes.bool,
|
isPaused: PropTypes.bool,
|
||||||
|
maybeScrollToBottom: PropTypes.func,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,6 +211,7 @@ class Message extends Component {
|
|||||||
onViewSourceInScratchpad: serviceContainer.onViewSourceInScratchpad
|
onViewSourceInScratchpad: serviceContainer.onViewSourceInScratchpad
|
||||||
|| serviceContainer.onViewSource,
|
|| serviceContainer.onViewSource,
|
||||||
onViewSource: serviceContainer.onViewSource,
|
onViewSource: serviceContainer.onViewSource,
|
||||||
|
onReady: this.props.maybeScrollToBottom,
|
||||||
sourceMapService: serviceContainer.sourceMapService,
|
sourceMapService: serviceContainer.sourceMapService,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@ -24,6 +24,7 @@ ConsoleApiCall.propTypes = {
|
|||||||
open: PropTypes.bool,
|
open: PropTypes.bool,
|
||||||
serviceContainer: PropTypes.object.isRequired,
|
serviceContainer: PropTypes.object.isRequired,
|
||||||
timestampsVisible: PropTypes.bool.isRequired,
|
timestampsVisible: PropTypes.bool.isRequired,
|
||||||
|
maybeScrollToBottom: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
ConsoleApiCall.defaultProps = {
|
ConsoleApiCall.defaultProps = {
|
||||||
@ -41,6 +42,7 @@ function ConsoleApiCall(props) {
|
|||||||
repeat,
|
repeat,
|
||||||
pausedExecutionPoint,
|
pausedExecutionPoint,
|
||||||
isPaused,
|
isPaused,
|
||||||
|
maybeScrollToBottom,
|
||||||
} = props;
|
} = props;
|
||||||
const {
|
const {
|
||||||
id: messageId,
|
id: messageId,
|
||||||
@ -66,6 +68,7 @@ function ConsoleApiCall(props) {
|
|||||||
userProvidedStyles,
|
userProvidedStyles,
|
||||||
serviceContainer,
|
serviceContainer,
|
||||||
type,
|
type,
|
||||||
|
maybeScrollToBottom,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (type === "trace") {
|
if (type === "trace") {
|
||||||
@ -137,6 +140,7 @@ function ConsoleApiCall(props) {
|
|||||||
timeStamp,
|
timeStamp,
|
||||||
timestampsVisible,
|
timestampsVisible,
|
||||||
parameters,
|
parameters,
|
||||||
|
maybeScrollToBottom,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,6 +154,7 @@ function formatReps(options = {}) {
|
|||||||
serviceContainer,
|
serviceContainer,
|
||||||
userProvidedStyles,
|
userProvidedStyles,
|
||||||
type,
|
type,
|
||||||
|
maybeScrollToBottom,
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -166,6 +171,7 @@ function formatReps(options = {}) {
|
|||||||
loadedObjectProperties,
|
loadedObjectProperties,
|
||||||
loadedObjectEntries,
|
loadedObjectEntries,
|
||||||
type,
|
type,
|
||||||
|
maybeScrollToBottom,
|
||||||
}))
|
}))
|
||||||
// Interleave spaces.
|
// Interleave spaces.
|
||||||
.reduce((arr, v, i) => {
|
.reduce((arr, v, i) => {
|
||||||
|
@ -17,6 +17,7 @@ ConsoleCommand.propTypes = {
|
|||||||
message: PropTypes.object.isRequired,
|
message: PropTypes.object.isRequired,
|
||||||
timestampsVisible: PropTypes.bool.isRequired,
|
timestampsVisible: PropTypes.bool.isRequired,
|
||||||
serviceContainer: PropTypes.object,
|
serviceContainer: PropTypes.object,
|
||||||
|
maybeScrollToBottom: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,6 +28,7 @@ function ConsoleCommand(props) {
|
|||||||
message,
|
message,
|
||||||
timestampsVisible,
|
timestampsVisible,
|
||||||
serviceContainer,
|
serviceContainer,
|
||||||
|
maybeScrollToBottom,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -51,6 +53,7 @@ function ConsoleCommand(props) {
|
|||||||
indent,
|
indent,
|
||||||
timeStamp,
|
timeStamp,
|
||||||
timestampsVisible,
|
timestampsVisible,
|
||||||
|
maybeScrollToBottom,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ EvaluationResult.propTypes = {
|
|||||||
message: PropTypes.object.isRequired,
|
message: PropTypes.object.isRequired,
|
||||||
timestampsVisible: PropTypes.bool.isRequired,
|
timestampsVisible: PropTypes.bool.isRequired,
|
||||||
serviceContainer: PropTypes.object,
|
serviceContainer: PropTypes.object,
|
||||||
|
maybeScrollToBottom: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
function EvaluationResult(props) {
|
function EvaluationResult(props) {
|
||||||
@ -27,6 +28,7 @@ function EvaluationResult(props) {
|
|||||||
message,
|
message,
|
||||||
serviceContainer,
|
serviceContainer,
|
||||||
timestampsVisible,
|
timestampsVisible,
|
||||||
|
maybeScrollToBottom,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -63,6 +65,7 @@ function EvaluationResult(props) {
|
|||||||
escapeWhitespace: false,
|
escapeWhitespace: false,
|
||||||
type,
|
type,
|
||||||
helperType,
|
helperType,
|
||||||
|
maybeScrollToBottom,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,6 +86,7 @@ function EvaluationResult(props) {
|
|||||||
parameters,
|
parameters,
|
||||||
notes,
|
notes,
|
||||||
timestampsVisible,
|
timestampsVisible,
|
||||||
|
maybeScrollToBottom,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ PageError.propTypes = {
|
|||||||
open: PropTypes.bool,
|
open: PropTypes.bool,
|
||||||
timestampsVisible: PropTypes.bool.isRequired,
|
timestampsVisible: PropTypes.bool.isRequired,
|
||||||
serviceContainer: PropTypes.object,
|
serviceContainer: PropTypes.object,
|
||||||
|
maybeScrollToBottom: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
PageError.defaultProps = {
|
PageError.defaultProps = {
|
||||||
@ -33,6 +34,7 @@ function PageError(props) {
|
|||||||
serviceContainer,
|
serviceContainer,
|
||||||
timestampsVisible,
|
timestampsVisible,
|
||||||
isPaused,
|
isPaused,
|
||||||
|
maybeScrollToBottom,
|
||||||
} = props;
|
} = props;
|
||||||
const {
|
const {
|
||||||
id: messageId,
|
id: messageId,
|
||||||
@ -77,6 +79,7 @@ function PageError(props) {
|
|||||||
timeStamp,
|
timeStamp,
|
||||||
notes,
|
notes,
|
||||||
timestampsVisible,
|
timestampsVisible,
|
||||||
|
maybeScrollToBottom,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,9 +8,16 @@
|
|||||||
const TEST_URI =
|
const TEST_URI =
|
||||||
`data:text/html;charset=utf-8,<p>Web Console test for scroll.</p>
|
`data:text/html;charset=utf-8,<p>Web Console test for scroll.</p>
|
||||||
<script>
|
<script>
|
||||||
for (let i = 0; i < 100; i++) {
|
var a = () => b();
|
||||||
console.log("init-" + i);
|
var b = () => c();
|
||||||
}
|
var c = () => console.trace("trace in C");
|
||||||
|
|
||||||
|
for (let i = 0; i < 100; i++) {
|
||||||
|
if (i % 10 === 0) {
|
||||||
|
c();
|
||||||
|
}
|
||||||
|
console.log("init-" + i);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
`;
|
`;
|
||||||
add_task(async function() {
|
add_task(async function() {
|
||||||
@ -23,6 +30,10 @@ add_task(async function() {
|
|||||||
ok(hasVerticalOverflow(outputContainer), "There is a vertical overflow");
|
ok(hasVerticalOverflow(outputContainer), "There is a vertical overflow");
|
||||||
ok(isScrolledToBottom(outputContainer), "The console is scrolled to the bottom");
|
ok(isScrolledToBottom(outputContainer), "The console is scrolled to the bottom");
|
||||||
|
|
||||||
|
info("Wait until all stacktraces are rendered");
|
||||||
|
await waitFor(() => outputContainer.querySelectorAll(".frames").length === 10);
|
||||||
|
ok(isScrolledToBottom(outputContainer), "The console is scrolled to the bottom");
|
||||||
|
|
||||||
await refreshTab();
|
await refreshTab();
|
||||||
|
|
||||||
info("Console should be scrolled to bottom after refresh from page logs");
|
info("Console should be scrolled to bottom after refresh from page logs");
|
||||||
@ -30,39 +41,68 @@ add_task(async function() {
|
|||||||
ok(hasVerticalOverflow(outputContainer), "There is a vertical overflow");
|
ok(hasVerticalOverflow(outputContainer), "There is a vertical overflow");
|
||||||
ok(isScrolledToBottom(outputContainer), "The console is scrolled to the bottom");
|
ok(isScrolledToBottom(outputContainer), "The console is scrolled to the bottom");
|
||||||
|
|
||||||
|
info("Wait until all stacktraces are rendered");
|
||||||
|
await waitFor(() => outputContainer.querySelectorAll(".frames").length === 10);
|
||||||
|
ok(isScrolledToBottom(outputContainer), "The console is scrolled to the bottom");
|
||||||
|
|
||||||
info("Scroll up");
|
info("Scroll up");
|
||||||
outputContainer.scrollTop = 0;
|
outputContainer.scrollTop = 0;
|
||||||
|
|
||||||
info("Add a message to check that the scroll isn't impacted");
|
info("Add a console.trace message to check that the scroll isn't impacted");
|
||||||
let receievedMessages = waitForMessages({hud, messages: [{
|
let onMessage = waitForMessage(hud, "trace in C");
|
||||||
text: "stay",
|
|
||||||
}]});
|
|
||||||
ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
|
ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
|
||||||
content.wrappedJSObject.console.log("stay");
|
content.wrappedJSObject.c();
|
||||||
});
|
});
|
||||||
await receievedMessages;
|
let message = await onMessage;
|
||||||
ok(hasVerticalOverflow(outputContainer), "There is a vertical overflow");
|
ok(hasVerticalOverflow(outputContainer), "There is a vertical overflow");
|
||||||
is(outputContainer.scrollTop, 0, "The console stayed scrolled to the top");
|
is(outputContainer.scrollTop, 0, "The console stayed scrolled to the top");
|
||||||
|
|
||||||
|
info("Wait until the stacktrace is rendered");
|
||||||
|
await waitFor(() => message.node.querySelector(".frame"));
|
||||||
|
is(outputContainer.scrollTop, 0, "The console stayed scrolled to the top");
|
||||||
|
|
||||||
info("Evaluate a command to check that the console scrolls to the bottom");
|
info("Evaluate a command to check that the console scrolls to the bottom");
|
||||||
receievedMessages = waitForMessages({hud, messages: [{
|
onMessage = waitForMessage(hud, "42");
|
||||||
text: "42",
|
|
||||||
}]});
|
|
||||||
ui.jsterm.execute("21 + 21");
|
ui.jsterm.execute("21 + 21");
|
||||||
await receievedMessages;
|
await onMessage;
|
||||||
ok(hasVerticalOverflow(outputContainer), "There is a vertical overflow");
|
ok(hasVerticalOverflow(outputContainer), "There is a vertical overflow");
|
||||||
ok(isScrolledToBottom(outputContainer), "The console is scrolled to the bottom");
|
ok(isScrolledToBottom(outputContainer), "The console is scrolled to the bottom");
|
||||||
|
|
||||||
info("Add a message to check that the console do scroll since we're at the bottom");
|
info("Add a message to check that the console do scroll since we're at the bottom");
|
||||||
receievedMessages = waitForMessages({hud, messages: [{
|
onMessage = waitForMessage(hud, "scroll");
|
||||||
text: "scroll",
|
|
||||||
}]});
|
|
||||||
ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
|
ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
|
||||||
content.wrappedJSObject.console.log("scroll");
|
content.wrappedJSObject.console.log("scroll");
|
||||||
});
|
});
|
||||||
await receievedMessages;
|
await onMessage;
|
||||||
ok(hasVerticalOverflow(outputContainer), "There is a vertical overflow");
|
ok(hasVerticalOverflow(outputContainer), "There is a vertical overflow");
|
||||||
ok(isScrolledToBottom(outputContainer), "The console is scrolled to the bottom");
|
ok(isScrolledToBottom(outputContainer), "The console is scrolled to the bottom");
|
||||||
|
|
||||||
|
info("Evaluate an Error object to check that the console scrolls to the bottom");
|
||||||
|
onMessage = waitForMessage(hud, "myErrorObject", ".message.result");
|
||||||
|
ui.jsterm.execute(`
|
||||||
|
x = new Error("myErrorObject");
|
||||||
|
x.stack = "a@b/c.js:1:2\\nd@e/f.js:3:4";
|
||||||
|
x;`
|
||||||
|
);
|
||||||
|
message = await onMessage;
|
||||||
|
ok(isScrolledToBottom(outputContainer), "The console is scrolled to the bottom");
|
||||||
|
|
||||||
|
info("Wait until the stacktrace is rendered and check the console is scrolled");
|
||||||
|
await waitFor(() => message.node.querySelector(".objectBox-stackTrace .frame"));
|
||||||
|
ok(isScrolledToBottom(outputContainer), "The console is scrolled to the bottom");
|
||||||
|
|
||||||
|
info("Add a console.trace message to check that the console stays scrolled to bottom");
|
||||||
|
onMessage = waitForMessage(hud, "trace in C");
|
||||||
|
ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
|
||||||
|
content.wrappedJSObject.c();
|
||||||
|
});
|
||||||
|
message = await onMessage;
|
||||||
|
ok(hasVerticalOverflow(outputContainer), "There is a vertical overflow");
|
||||||
|
ok(isScrolledToBottom(outputContainer), "The console is scrolled to the bottom");
|
||||||
|
|
||||||
|
info("Wait until the stacktrace is rendered");
|
||||||
|
await waitFor(() => message.node.querySelector(".frame"));
|
||||||
|
ok(isScrolledToBottom(outputContainer), "The console is scrolled to the bottom");
|
||||||
});
|
});
|
||||||
|
|
||||||
function hasVerticalOverflow(container) {
|
function hasVerticalOverflow(container) {
|
||||||
|
@ -62,6 +62,7 @@ function getObjectInspector(grip, serviceContainer, override = {}) {
|
|||||||
? serviceContainer.onViewSourceInScratchpad || serviceContainer.onViewSource
|
? serviceContainer.onViewSourceInScratchpad || serviceContainer.onViewSource
|
||||||
: null,
|
: null,
|
||||||
onViewSource: serviceContainer.onViewSource,
|
onViewSource: serviceContainer.onViewSource,
|
||||||
|
onReady: override.maybeScrollToBottom,
|
||||||
sourceMapService: serviceContainer ? serviceContainer.sourceMapService : null,
|
sourceMapService: serviceContainer ? serviceContainer.sourceMapService : null,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user