1283712 - Add a mechanism to add notes for an error message.

This commit is contained in:
Fedor 2019-09-05 20:06:06 +03:00
parent 8a0e23aadb
commit 0e2b6e8609
36 changed files with 1482 additions and 443 deletions

View File

@ -34,6 +34,7 @@ function EvaluationResult(props) {
id: messageId,
exceptionDocURL,
frame,
notes,
} = message;
let messageBody;
@ -57,6 +58,7 @@ function EvaluationResult(props) {
serviceContainer,
exceptionDocURL,
frame,
notes,
};
return Message(childProps);
}

View File

@ -44,6 +44,7 @@ function PageError(props) {
stacktrace,
frame,
exceptionDocURL,
notes,
} = message;
const childProps = {
@ -62,6 +63,7 @@ function PageError(props) {
stacktrace,
serviceContainer,
exceptionDocURL,
notes,
};
return Message(childProps);
}

View File

@ -47,6 +47,10 @@ const Message = createClass({
onViewSourceInDebugger: PropTypes.func.isRequired,
sourceMapService: PropTypes.any,
}),
notes: PropTypes.arrayOf(PropTypes.shape({
messageBody: PropTypes.string.isRequired,
frame: PropTypes.any,
})),
},
getDefaultProps: function () {
@ -90,6 +94,7 @@ const Message = createClass({
serviceContainer,
dispatch,
exceptionDocURL,
notes,
} = this.props;
topLevelClasses.push("message", source, type, level);
@ -127,6 +132,29 @@ const Message = createClass({
});
}
let notesNodes;
if (notes) {
notesNodes = notes.map(note => dom.span(
{ className: "message-flex-body error-note" },
dom.span({ className: "message-body devtools-monospace" },
"note: " + note.messageBody
),
dom.span({ className: "message-location devtools-monospace" },
note.frame ? FrameView({
frame: note.frame,
onClick: serviceContainer
? serviceContainer.onViewSourceInDebugger
: undefined,
showEmptyPathAsHost: true,
sourceMapService: serviceContainer
? serviceContainer.sourceMapService
: undefined
}) : null
)));
} else {
notesNodes = [];
}
const repeat = this.props.repeat ? MessageRepeat({repeat: this.props.repeat}) : null;
// Configure the location.
@ -167,7 +195,8 @@ const Message = createClass({
repeat,
location
),
attachment
attachment,
...notesNodes
)
);
}

View File

@ -126,6 +126,15 @@ function matchSearchFilters(message, filters) {
|| (message.parameters !== null
&& message.parameters.join("").toLocaleLowerCase()
.includes(text.toLocaleLowerCase()))
// Look for a match in notes.
|| (Array.isArray(message.notes) && message.notes.some(note =>
// Look for a match in location.
isTextInFrame(text, note.frame)
// Look for a match in messageBody.
|| (note.messageBody !== null
&& note.messageBody.toLocaleLowerCase()
.includes(text.toLocaleLowerCase()))
))
);
}

View File

@ -123,4 +123,100 @@ describe("PageError component:", () => {
wrapper = render(PageError({ message, serviceContainer}));
expect(wrapper.find(".indent").prop("style").width).toBe(`0`);
});
it("has empty error notes", () => {
const message = stubPreparedMessages.get("ReferenceError: asdf is not defined");
let wrapper = render(PageError({ message, serviceContainer }));
const notes = wrapper.find(".error-note");
expect(notes.length).toBe(0);
});
it("can show an error note", () => {
const origMessage = stubPreparedMessages.get("ReferenceError: asdf is not defined");
const message = origMessage.set("notes", [
{
"messageBody": "test note",
"frame": {
"source": "http://example.com/test.js",
"line": 2,
"column": 6
}
}
]);
let wrapper = render(PageError({ message, serviceContainer }));
const notes = wrapper.find(".error-note");
expect(notes.length).toBe(1);
const note = notes.eq(0);
expect(note.find(".message-body").text())
.toBe("note: test note");
// There should be the location.
const locationLink = note.find(`.message-location`);
expect(locationLink.length).toBe(1);
expect(locationLink.text()).toBe("test.js:2:6");
});
it("can show multiple error notes", () => {
const origMessage = stubPreparedMessages.get("ReferenceError: asdf is not defined");
const message = origMessage.set("notes", [
{
"messageBody": "test note 1",
"frame": {
"source": "http://example.com/test1.js",
"line": 2,
"column": 6
}
},
{
"messageBody": "test note 2",
"frame": {
"source": "http://example.com/test2.js",
"line": 10,
"column": 18
}
},
{
"messageBody": "test note 3",
"frame": {
"source": "http://example.com/test3.js",
"line": 9,
"column": 4
}
}
]);
let wrapper = render(PageError({ message, serviceContainer }));
const notes = wrapper.find(".error-note");
expect(notes.length).toBe(3);
const note1 = notes.eq(0);
expect(note1.find(".message-body").text())
.toBe("note: test note 1");
const locationLink1 = note1.find(`.message-location`);
expect(locationLink1.length).toBe(1);
expect(locationLink1.text()).toBe("test1.js:2:6");
const note2 = notes.eq(1);
expect(note2.find(".message-body").text())
.toBe("note: test note 2");
const locationLink2 = note2.find(`.message-location`);
expect(locationLink2.length).toBe(1);
expect(locationLink2.text()).toBe("test2.js:10:18");
const note3 = notes.eq(2);
expect(note3.find(".message-body").text())
.toBe("note: test note 3");
const locationLink3 = note3.find(`.message-location`);
expect(locationLink3.length).toBe(1);
expect(locationLink3.text()).toBe("test3.js:9:4");
});
});

View File

@ -11,8 +11,6 @@ const { ConsoleMessage, NetworkEventMessage } = require("devtools/client/webcons
let stubPreparedMessages = new Map();
let stubPackets = new Map();
stubPreparedMessages.set("console.log('foobar', 'test')", new ConsoleMessage({
"id": "1",
"allowRepeating": true,
@ -34,7 +32,8 @@ stubPreparedMessages.set("console.log('foobar', 'test')", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.log(undefined)", new ConsoleMessage({
@ -50,7 +49,7 @@ stubPreparedMessages.set("console.log(undefined)", new ConsoleMessage({
}
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"undefined\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(undefined)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"undefined\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(undefined)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(undefined)",
@ -59,7 +58,8 @@ stubPreparedMessages.set("console.log(undefined)", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.warn('danger, will robinson!')", new ConsoleMessage({
@ -73,7 +73,7 @@ stubPreparedMessages.set("console.warn('danger, will robinson!')", new ConsoleMe
"danger, will robinson!"
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"warn\",\"level\":\"warn\",\"messageText\":null,\"parameters\":[\"danger, will robinson!\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.warn(%27danger%2C%20will%20robinson!%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"warn\",\"level\":\"warn\",\"messageText\":null,\"parameters\":[\"danger, will robinson!\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.warn(%27danger%2C%20will%20robinson!%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.warn(%27danger%2C%20will%20robinson!%27)",
@ -82,7 +82,8 @@ stubPreparedMessages.set("console.warn('danger, will robinson!')", new ConsoleMe
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.log(NaN)", new ConsoleMessage({
@ -98,7 +99,7 @@ stubPreparedMessages.set("console.log(NaN)", new ConsoleMessage({
}
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"NaN\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(NaN)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"NaN\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(NaN)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(NaN)",
@ -107,7 +108,8 @@ stubPreparedMessages.set("console.log(NaN)", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.log(null)", new ConsoleMessage({
@ -123,7 +125,7 @@ stubPreparedMessages.set("console.log(null)", new ConsoleMessage({
}
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"null\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(null)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"null\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(null)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(null)",
@ -132,7 +134,8 @@ stubPreparedMessages.set("console.log(null)", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.log('鼬')", new ConsoleMessage({
@ -146,7 +149,7 @@ stubPreparedMessages.set("console.log('鼬')", new ConsoleMessage({
"鼬"
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"鼬\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%E9%BC%AC%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"鼬\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%E9%BC%AC%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%E9%BC%AC%27)",
@ -155,7 +158,8 @@ stubPreparedMessages.set("console.log('鼬')", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.clear()", new ConsoleMessage({
@ -169,8 +173,7 @@ stubPreparedMessages.set("console.clear()", new ConsoleMessage({
"Console was cleared."
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"clear\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"Console was cleared.\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.clear()\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"stacktrace": null,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"clear\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"Console was cleared.\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.clear()\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.clear()",
"line": 1,
@ -178,7 +181,8 @@ stubPreparedMessages.set("console.clear()", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.count('bar')", new ConsoleMessage({
@ -190,7 +194,7 @@ stubPreparedMessages.set("console.count('bar')", new ConsoleMessage({
"messageText": "bar: 1",
"parameters": null,
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"debug\",\"messageText\":\"bar: 1\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.count(%27bar%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"debug\",\"messageText\":\"bar: 1\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.count(%27bar%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.count(%27bar%27)",
@ -199,7 +203,8 @@ stubPreparedMessages.set("console.count('bar')", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.assert(false, {message: 'foobar'})", new ConsoleMessage({
@ -234,7 +239,7 @@ stubPreparedMessages.set("console.assert(false, {message: 'foobar'})", new Conso
}
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"assert\",\"level\":\"error\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn8.child1/obj31\",\"class\":\"Object\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":1,\"preview\":{\"kind\":\"Object\",\"ownProperties\":{\"message\":{\"configurable\":true,\"enumerable\":true,\"writable\":true,\"value\":\"foobar\"}},\"ownPropertiesLength\":1,\"safeGetterValues\":{}}}],\"repeatId\":null,\"stacktrace\":[{\"columnNumber\":27,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)\",\"functionName\":\"triggerPacket\",\"language\":2,\"lineNumber\":1}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"assert\",\"level\":\"error\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn8.child1/obj31\",\"class\":\"Object\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":1,\"preview\":{\"kind\":\"Object\",\"ownProperties\":{\"message\":{\"configurable\":true,\"enumerable\":true,\"writable\":true,\"value\":\"foobar\"}},\"ownPropertiesLength\":1,\"safeGetterValues\":{}}}],\"repeatId\":null,\"stacktrace\":[{\"columnNumber\":27,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)\",\"functionName\":\"triggerPacket\",\"language\":2,\"lineNumber\":1}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": [
{
"columnNumber": 27,
@ -251,7 +256,8 @@ stubPreparedMessages.set("console.assert(false, {message: 'foobar'})", new Conso
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.log('hello \nfrom \rthe \"string world!')", new ConsoleMessage({
@ -265,7 +271,7 @@ stubPreparedMessages.set("console.log('hello \nfrom \rthe \"string world!')", ne
"hello \nfrom \rthe \"string world!"
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"hello \\nfrom \\rthe \\\"string world!\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27hello%20%5Cnfrom%20%5Crthe%20%5C%22string%20world!%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"hello \\nfrom \\rthe \\\"string world!\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27hello%20%5Cnfrom%20%5Crthe%20%5C%22string%20world!%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27hello%20%5Cnfrom%20%5Crthe%20%5C%22string%20world!%27)",
@ -274,7 +280,8 @@ stubPreparedMessages.set("console.log('hello \nfrom \rthe \"string world!')", ne
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.log('úṇĩçödê țĕșť')", new ConsoleMessage({
@ -288,7 +295,7 @@ stubPreparedMessages.set("console.log('úṇĩçödê țĕșť')", new ConsoleMe
"úṇĩçödê țĕșť"
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"úṇĩçödê țĕșť\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%C3%BA%E1%B9%87%C4%A9%C3%A7%C3%B6d%C3%AA%20%C8%9B%C4%95%C8%99%C5%A5%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"úṇĩçödê țĕșť\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%C3%BA%E1%B9%87%C4%A9%C3%A7%C3%B6d%C3%AA%20%C8%9B%C4%95%C8%99%C5%A5%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%C3%BA%E1%B9%87%C4%A9%C3%A7%C3%B6d%C3%AA%20%C8%9B%C4%95%C8%99%C5%A5%27)",
@ -297,7 +304,8 @@ stubPreparedMessages.set("console.log('úṇĩçödê țĕșť')", new ConsoleMe
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.dirxml(window)", new ConsoleMessage({
@ -315,7 +323,7 @@ stubPreparedMessages.set("console.dirxml(window)", new ConsoleMessage({
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 804,
"ownPropertyLength": 815,
"preview": {
"kind": "ObjectWithURL",
"url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html"
@ -323,7 +331,7 @@ stubPreparedMessages.set("console.dirxml(window)", new ConsoleMessage({
}
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn11.child1/obj31\",\"class\":\"Window\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":804,\"preview\":{\"kind\":\"ObjectWithURL\",\"url\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html\"}}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.dirxml(window)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn11.child1/obj31\",\"class\":\"Window\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":804,\"preview\":{\"kind\":\"ObjectWithURL\",\"url\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html\"}}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.dirxml(window)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.dirxml(window)",
@ -332,7 +340,8 @@ stubPreparedMessages.set("console.dirxml(window)", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.trace()", new ConsoleMessage({
@ -344,7 +353,7 @@ stubPreparedMessages.set("console.trace()", new ConsoleMessage({
"messageText": null,
"parameters": [],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"trace\",\"level\":\"log\",\"messageText\":null,\"parameters\":[],\"repeatId\":null,\"stacktrace\":[{\"columnNumber\":3,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"testStacktraceFiltering\",\"language\":2,\"lineNumber\":3},{\"columnNumber\":3,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"foo\",\"language\":2,\"lineNumber\":6},{\"columnNumber\":1,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"triggerPacket\",\"language\":2,\"lineNumber\":9}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"line\":3,\"column\":3},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"trace\",\"level\":\"log\",\"messageText\":null,\"parameters\":[],\"repeatId\":null,\"stacktrace\":[{\"columnNumber\":3,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"testStacktraceFiltering\",\"language\":2,\"lineNumber\":3},{\"columnNumber\":3,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"foo\",\"language\":2,\"lineNumber\":6},{\"columnNumber\":1,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"triggerPacket\",\"language\":2,\"lineNumber\":9}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"line\":3,\"column\":3},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": [
{
"columnNumber": 3,
@ -375,7 +384,8 @@ stubPreparedMessages.set("console.trace()", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.time('bar')", new ConsoleMessage({
@ -387,7 +397,7 @@ stubPreparedMessages.set("console.time('bar')", new ConsoleMessage({
"messageText": null,
"parameters": null,
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"nullMessage\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"nullMessage\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)",
@ -396,7 +406,8 @@ stubPreparedMessages.set("console.time('bar')", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.timeEnd('bar')", new ConsoleMessage({
@ -408,7 +419,7 @@ stubPreparedMessages.set("console.timeEnd('bar')", new ConsoleMessage({
"messageText": "bar: 1.36ms",
"parameters": null,
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"timeEnd\",\"level\":\"log\",\"messageText\":\"bar: 1.36ms\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"timeEnd\",\"level\":\"log\",\"messageText\":\"bar: 1.36ms\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)",
@ -417,7 +428,8 @@ stubPreparedMessages.set("console.timeEnd('bar')", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.table('bar')", new ConsoleMessage({
@ -431,7 +443,7 @@ stubPreparedMessages.set("console.table('bar')", new ConsoleMessage({
"bar"
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"bar\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"bar\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%27bar%27)",
@ -440,7 +452,8 @@ stubPreparedMessages.set("console.table('bar')", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.table(['a', 'b', 'c'])", new ConsoleMessage({
@ -471,7 +484,7 @@ stubPreparedMessages.set("console.table(['a', 'b', 'c'])", new ConsoleMessage({
}
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"table\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn15.child1/obj31\",\"class\":\"Array\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":4,\"preview\":{\"kind\":\"ArrayLike\",\"length\":3,\"items\":[\"a\",\"b\",\"c\"]}}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%5B%27a%27%2C%20%27b%27%2C%20%27c%27%5D)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"table\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn15.child1/obj31\",\"class\":\"Array\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":4,\"preview\":{\"kind\":\"ArrayLike\",\"length\":3,\"items\":[\"a\",\"b\",\"c\"]}}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%5B%27a%27%2C%20%27b%27%2C%20%27c%27%5D)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%5B%27a%27%2C%20%27b%27%2C%20%27c%27%5D)",
@ -480,7 +493,8 @@ stubPreparedMessages.set("console.table(['a', 'b', 'c'])", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.group('bar')", new ConsoleMessage({
@ -492,7 +506,7 @@ stubPreparedMessages.set("console.group('bar')", new ConsoleMessage({
"messageText": "bar",
"parameters": null,
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"startGroup\",\"level\":\"log\",\"messageText\":\"bar\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"startGroup\",\"level\":\"log\",\"messageText\":\"bar\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)",
@ -501,7 +515,8 @@ stubPreparedMessages.set("console.group('bar')", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.groupEnd('bar')", new ConsoleMessage({
@ -513,7 +528,7 @@ stubPreparedMessages.set("console.groupEnd('bar')", new ConsoleMessage({
"messageText": null,
"parameters": null,
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)",
@ -522,7 +537,8 @@ stubPreparedMessages.set("console.groupEnd('bar')", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.groupCollapsed('foo')", new ConsoleMessage({
@ -534,7 +550,7 @@ stubPreparedMessages.set("console.groupCollapsed('foo')", new ConsoleMessage({
"messageText": "foo",
"parameters": null,
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"startGroupCollapsed\",\"level\":\"log\",\"messageText\":\"foo\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"startGroupCollapsed\",\"level\":\"log\",\"messageText\":\"foo\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)",
@ -543,7 +559,8 @@ stubPreparedMessages.set("console.groupCollapsed('foo')", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.groupEnd('foo')", new ConsoleMessage({
@ -555,7 +572,7 @@ stubPreparedMessages.set("console.groupEnd('foo')", new ConsoleMessage({
"messageText": null,
"parameters": null,
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)",
@ -564,7 +581,8 @@ stubPreparedMessages.set("console.groupEnd('foo')", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.group()", new ConsoleMessage({
@ -576,7 +594,7 @@ stubPreparedMessages.set("console.group()", new ConsoleMessage({
"messageText": "<no group label>",
"parameters": null,
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"startGroup\",\"level\":\"log\",\"messageText\":\"<no group label>\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"startGroup\",\"level\":\"log\",\"messageText\":\"<no group label>\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()",
@ -585,7 +603,8 @@ stubPreparedMessages.set("console.group()", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.groupEnd()", new ConsoleMessage({
@ -597,7 +616,7 @@ stubPreparedMessages.set("console.groupEnd()", new ConsoleMessage({
"messageText": null,
"parameters": null,
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()",
@ -606,7 +625,8 @@ stubPreparedMessages.set("console.groupEnd()", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": []
"userProvidedStyles": [],
"notes": null
}));
stubPreparedMessages.set("console.log(%cfoobar)", new ConsoleMessage({
@ -621,7 +641,7 @@ stubPreparedMessages.set("console.log(%cfoobar)", new ConsoleMessage({
"bar"
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"foo\",\"bar\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%25cfoobar)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[\"color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px\",\"color:red;background:url('http://example.com/test')\"]}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"foo\",\"bar\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%25cfoobar)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[\"color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px\",\"color:red;background:url('http://example.com/test')\"],\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%25cfoobar)",
@ -633,10 +653,10 @@ stubPreparedMessages.set("console.log(%cfoobar)", new ConsoleMessage({
"userProvidedStyles": [
"color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px",
"color:red;background:url('http://example.com/test')"
]
],
"notes": null
}));
stubPackets.set("console.log('foobar', 'test')", {
"from": "server1.conn0.child1/consoleActor2",
"type": "consoleAPICall",
@ -1017,7 +1037,7 @@ stubPackets.set("console.dirxml(window)", {
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 804,
"ownPropertyLength": 815,
"preview": {
"kind": "ObjectWithURL",
"url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html"
@ -1451,8 +1471,7 @@ stubPackets.set("console.log(%cfoobar)", {
}
});
module.exports = {
stubPreparedMessages,
stubPackets,
}
};

View File

@ -11,8 +11,6 @@ const { ConsoleMessage, NetworkEventMessage } = require("devtools/client/webcons
let stubPreparedMessages = new Map();
let stubPackets = new Map();
stubPreparedMessages.set("new Date(0)", new ConsoleMessage({
"id": "1",
"allowRepeating": true,
@ -32,11 +30,12 @@ stubPreparedMessages.set("new Date(0)", new ConsoleMessage({
}
},
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"type\":\"result\",\"level\":\"log\",\"parameters\":{\"type\":\"object\",\"actor\":\"server1.conn0.child1/obj30\",\"class\":\"Date\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":0,\"preview\":{\"timestamp\":0}},\"repeatId\":null,\"stacktrace\":null,\"frame\":null,\"groupId\":null,\"userProvidedStyles\":null}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"type\":\"result\",\"level\":\"log\",\"parameters\":{\"type\":\"object\",\"actor\":\"server1.conn0.child1/obj30\",\"class\":\"Date\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":0,\"preview\":{\"timestamp\":0}},\"repeatId\":null,\"stacktrace\":null,\"frame\":null,\"groupId\":null,\"userProvidedStyles\":null,\"notes\":null}",
"stacktrace": null,
"frame": null,
"groupId": null,
"userProvidedStyles": null
"userProvidedStyles": null,
"notes": null
}));
stubPreparedMessages.set("asdf()", new ConsoleMessage({
@ -50,7 +49,7 @@ stubPreparedMessages.set("asdf()", new ConsoleMessage({
"type": "undefined"
},
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"type\":\"result\",\"level\":\"error\",\"messageText\":\"ReferenceError: asdf is not defined\",\"parameters\":{\"type\":\"undefined\"},\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"debugger eval code\",\"line\":1,\"column\":1},\"groupId\":null,\"exceptionDocURL\":\"https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default\",\"userProvidedStyles\":null}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"type\":\"result\",\"level\":\"error\",\"messageText\":\"ReferenceError: asdf is not defined\",\"parameters\":{\"type\":\"undefined\"},\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"debugger eval code\",\"line\":1,\"column\":1},\"groupId\":null,\"exceptionDocURL\":\"https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default\",\"userProvidedStyles\":null,\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "debugger eval code",
@ -59,7 +58,8 @@ stubPreparedMessages.set("asdf()", new ConsoleMessage({
},
"groupId": null,
"exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default",
"userProvidedStyles": null
"userProvidedStyles": null,
"notes": null
}));
stubPreparedMessages.set("1 + @", new ConsoleMessage({
@ -73,7 +73,7 @@ stubPreparedMessages.set("1 + @", new ConsoleMessage({
"type": "undefined"
},
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"type\":\"result\",\"level\":\"error\",\"messageText\":\"SyntaxError: illegal character\",\"parameters\":{\"type\":\"undefined\"},\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"debugger eval code\",\"line\":1,\"column\":4},\"groupId\":null,\"userProvidedStyles\":null}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"type\":\"result\",\"level\":\"error\",\"messageText\":\"SyntaxError: illegal character\",\"parameters\":{\"type\":\"undefined\"},\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"debugger eval code\",\"line\":1,\"column\":4},\"groupId\":null,\"userProvidedStyles\":null,\"notes\":null}",
"stacktrace": null,
"frame": {
"source": "debugger eval code",
@ -81,10 +81,10 @@ stubPreparedMessages.set("1 + @", new ConsoleMessage({
"column": 4
},
"groupId": null,
"userProvidedStyles": null
"userProvidedStyles": null,
"notes": null
}));
stubPackets.set("new Date(0)", {
"from": "server1.conn0.child1/consoleActor2",
"input": "new Date(0)",
@ -103,7 +103,8 @@ stubPackets.set("new Date(0)", {
"timestamp": 1476573073424,
"exception": null,
"frame": null,
"helperResult": null
"helperResult": null,
"notes": null
});
stubPackets.set("asdf()", {
@ -138,7 +139,8 @@ stubPackets.set("asdf()", {
"line": 1,
"column": 1
},
"helperResult": null
"helperResult": null,
"notes": null
});
stubPackets.set("1 + @", {
@ -172,11 +174,11 @@ stubPackets.set("1 + @", {
"line": 1,
"column": 4
},
"helperResult": null
"helperResult": null,
"notes": null
});
module.exports = {
stubPreparedMessages,
stubPackets,
}
};

View File

@ -11,8 +11,6 @@ const { ConsoleMessage, NetworkEventMessage } = require("devtools/client/webcons
let stubPreparedMessages = new Map();
let stubPackets = new Map();
stubPreparedMessages.set("ReferenceError: asdf is not defined", new ConsoleMessage({
"id": "1",
"allowRepeating": true,
@ -22,7 +20,7 @@ stubPreparedMessages.set("ReferenceError: asdf is not defined", new ConsoleMessa
"messageText": "ReferenceError: asdf is not defined",
"parameters": null,
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"type\":\"log\",\"level\":\"error\",\"messageText\":\"ReferenceError: asdf is not defined\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":[{\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"lineNumber\":3,\"columnNumber\":5,\"functionName\":\"bar\"},{\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"lineNumber\":6,\"columnNumber\":5,\"functionName\":\"foo\"},{\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"lineNumber\":9,\"columnNumber\":3,\"functionName\":null}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"line\":3,\"column\":5},\"groupId\":null,\"exceptionDocURL\":\"https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default\"}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"type\":\"log\",\"level\":\"error\",\"messageText\":\"ReferenceError: asdf is not defined\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":[{\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"lineNumber\":3,\"columnNumber\":5,\"functionName\":\"bar\"},{\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"lineNumber\":6,\"columnNumber\":5,\"functionName\":\"foo\"},{\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"lineNumber\":9,\"columnNumber\":3,\"functionName\":null}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"line\":3,\"column\":5},\"groupId\":null,\"exceptionDocURL\":\"https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default\",\"userProvidedStyles\":null,\"notes\":null}",
"stacktrace": [
{
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error",
@ -49,10 +47,11 @@ stubPreparedMessages.set("ReferenceError: asdf is not defined", new ConsoleMessa
"column": 5
},
"groupId": null,
"exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default"
"exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default",
"userProvidedStyles": null,
"notes": null
}));
stubPackets.set("ReferenceError: asdf is not defined", {
"from": "server1.conn0.child1/consoleActor2",
"type": "pageError",
@ -91,12 +90,12 @@ stubPackets.set("ReferenceError: asdf is not defined", {
"columnNumber": 3,
"functionName": null
}
]
],
"notes": null
}
});
module.exports = {
stubPreparedMessages,
stubPackets,
}
};

View File

@ -38,6 +38,7 @@ exports.ConsoleMessage = Immutable.Record({
groupId: null,
exceptionDocURL: null,
userProvidedStyles: null,
notes: null,
});
exports.NetworkEventMessage = Immutable.Record({

View File

@ -165,6 +165,7 @@ function transformPacket(packet) {
stacktrace: pageError.stacktrace ? pageError.stacktrace : null,
frame,
exceptionDocURL: pageError.exceptionDocURL,
notes: pageError.notes,
});
}
@ -185,7 +186,8 @@ function transformPacket(packet) {
exceptionMessage: messageText,
exceptionDocURL,
frame,
result: parameters
result: parameters,
notes,
} = packet;
const level = messageText ? MESSAGE_LEVEL.ERROR : MESSAGE_LEVEL.LOG;
@ -197,6 +199,7 @@ function transformPacket(packet) {
parameters,
exceptionDocURL,
frame,
notes,
});
}
}

View File

@ -888,7 +888,8 @@ WebConsoleActor.prototype =
let evalResult = evalInfo.result;
let helperResult = evalInfo.helperResult;
let result, errorDocURL, errorMessage, errorGrip = null, frame = null;
let result, errorDocURL, errorMessage, errorNotes = null, errorGrip = null,
frame = null;
if (evalResult) {
if ("return" in evalResult) {
result = evalResult.return;
@ -943,6 +944,23 @@ WebConsoleActor.prototype =
};
}
} catch (ex) {}
try {
let notes = error.errorNotes;
if (notes && notes.length) {
errorNotes = [];
for (let note of notes) {
errorNotes.push({
messageBody: this._createStringGrip(note.message),
frame: {
source: note.fileName,
line: note.lineNumber,
column: note.columnNumber,
}
});
}
}
} catch (ex) {}
}
}
@ -967,6 +985,7 @@ WebConsoleActor.prototype =
exceptionDocURL: errorDocURL,
frame,
helperResult: helperResult,
notes: errorNotes,
};
},
@ -1500,6 +1519,23 @@ WebConsoleActor.prototype =
lineText = lineText.substr(0, DebuggerServer.LONG_STRING_INITIAL_LENGTH);
}
let notesArray = null;
let notes = aPageError.notes;
if (notes && notes.length) {
notesArray = [];
for (let i = 0, len = notes.length; i < len; i++) {
let note = notes.queryElementAt(i, Ci.nsIScriptErrorNote);
notesArray.push({
messageBody: this._createStringGrip(note.errorMessage),
frame: {
source: note.sourceName,
line: note.lineNumber,
column: note.columnNumber,
}
});
}
}
return {
errorMessage: this._createStringGrip(aPageError.errorMessage),
errorMessageName: aPageError.errorMessageName,
@ -1516,7 +1552,8 @@ WebConsoleActor.prototype =
strict: !!(aPageError.flags & aPageError.strictFlag),
info: !!(aPageError.flags & aPageError.infoFlag),
private: aPageError.isFromPrivateWindow,
stacktrace: stack
stacktrace: stack,
notes: notesArray,
};
},

View File

@ -9,13 +9,25 @@
#include "nsISupports.idl"
#include "nsIArray.idl"
#include "nsIConsoleMessage.idl"
%{C++
#include "nsStringGlue.h" // for nsDependentCString
%}
[scriptable, uuid(361be358-76f0-47aa-b37b-6ad833599e8d)]
[scriptable, uuid(e8933fc9-c302-4e12-a55b-4f88611d9c6c)]
interface nsIScriptErrorNote : nsISupports
{
readonly attribute AString errorMessage;
readonly attribute AString sourceName;
readonly attribute uint32_t lineNumber;
readonly attribute uint32_t columnNumber;
AUTF8String toString();
};
[scriptable, uuid(63eb4d3e-7d99-4150-b4f3-11314f9d82a9)]
interface nsIScriptError : nsIConsoleMessage
{
/** pseudo-flag for default case */
@ -74,6 +86,7 @@ interface nsIScriptError : nsIConsoleMessage
*/
attribute AString errorMessageName;
readonly attribute nsIArray notes;
void init(in AString message,
in AString sourceName,

View File

@ -17,6 +17,7 @@
#include "nsPIDOMWindow.h"
#include "nsILoadContext.h"
#include "nsIDocShell.h"
#include "nsIMutableArray.h"
#include "nsIScriptError.h"
#include "nsISensitiveInfoHiddenURI.h"
@ -46,6 +47,12 @@ nsScriptErrorBase::nsScriptErrorBase()
nsScriptErrorBase::~nsScriptErrorBase() {}
void
nsScriptErrorBase::AddNote(nsIScriptErrorNote* note)
{
mNotes.AppendObject(note);
}
void
nsScriptErrorBase::InitializeOnMainThread()
{
@ -189,6 +196,28 @@ nsScriptErrorBase::Init(const nsAString& message,
0);
}
static void
AssignSourceNameHelper(nsString& aSourceNameDest, const nsAString& aSourceNameSrc)
{
if (aSourceNameSrc.IsEmpty())
return;
aSourceNameDest.Assign(aSourceNameSrc);
nsCOMPtr<nsIURI> uri;
nsAutoCString pass;
if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), aSourceNameSrc)) &&
NS_SUCCEEDED(uri->GetPassword(pass)) &&
!pass.IsEmpty())
{
nsCOMPtr<nsISensitiveInfoHiddenURI> safeUri = do_QueryInterface(uri);
nsAutoCString loc;
if (safeUri && NS_SUCCEEDED(safeUri->GetSensitiveInfoHiddenSpec(loc)))
aSourceNameDest.Assign(NS_ConvertUTF8toUTF16(loc));
}
}
NS_IMETHODIMP
nsScriptErrorBase::InitWithWindowID(const nsAString& message,
const nsAString& sourceName,
@ -200,26 +229,7 @@ nsScriptErrorBase::InitWithWindowID(const nsAString& message,
uint64_t aInnerWindowID)
{
mMessage.Assign(message);
if (!sourceName.IsEmpty()) {
mSourceName.Assign(sourceName);
nsCOMPtr<nsIURI> uri;
nsAutoCString pass;
if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), sourceName)) &&
NS_SUCCEEDED(uri->GetPassword(pass)) &&
!pass.IsEmpty()) {
nsCOMPtr<nsISensitiveInfoHiddenURI> safeUri =
do_QueryInterface(uri);
nsAutoCString loc;
if (safeUri &&
NS_SUCCEEDED(safeUri->GetSensitiveInfoHiddenSpec(loc))) {
mSourceName.Assign(NS_ConvertUTF8toUTF16(loc));
}
}
}
AssignSourceNameHelper(mSourceName, sourceName);
mLineNumber = lineNumber;
mSourceLine.Assign(sourceLine);
mColumnNumber = columnNumber;
@ -235,8 +245,11 @@ nsScriptErrorBase::InitWithWindowID(const nsAString& message,
return NS_OK;
}
NS_IMETHODIMP
nsScriptErrorBase::ToString(nsACString& /*UTF8*/ aResult)
static nsresult
ToStringHelper(const char* aSeverity, const nsString& aMessage,
const nsString& aSourceName, const nsString* aSourceLine,
uint32_t aLineNumber, uint32_t aColumnNumber,
nsACString& /*UTF8*/ aResult)
{
static const char format0[] =
"[%s: \"%s\" {file: \"%s\" line: %d column: %d source: \"%s\"}]";
@ -245,43 +258,39 @@ nsScriptErrorBase::ToString(nsACString& /*UTF8*/ aResult)
static const char format2[] =
"[%s: \"%s\"]";
static const char error[] = "JavaScript Error";
static const char warning[] = "JavaScript Warning";
const char* severity = !(mFlags & JSREPORT_WARNING) ? error : warning;
char* temp;
char* tempMessage = nullptr;
char* tempSourceName = nullptr;
char* tempSourceLine = nullptr;
if (!mMessage.IsEmpty())
tempMessage = ToNewUTF8String(mMessage);
if (!mSourceName.IsEmpty())
if (!aMessage.IsEmpty())
tempMessage = ToNewUTF8String(aMessage);
if (!aSourceName.IsEmpty())
// Use at most 512 characters from mSourceName.
tempSourceName = ToNewUTF8String(StringHead(mSourceName, 512));
if (!mSourceLine.IsEmpty())
tempSourceName = ToNewUTF8String(StringHead(aSourceName, 512));
if (aSourceLine && !aSourceLine->IsEmpty())
// Use at most 512 characters from mSourceLine.
tempSourceLine = ToNewUTF8String(StringHead(mSourceLine, 512));
tempSourceLine = ToNewUTF8String(StringHead(*aSourceLine, 512));
if (nullptr != tempSourceName && nullptr != tempSourceLine)
if (nullptr != tempSourceName && nullptr != tempSourceLine) {
temp = JS_smprintf(format0,
severity,
aSeverity,
tempMessage,
tempSourceName,
mLineNumber,
mColumnNumber,
aLineNumber,
aColumnNumber,
tempSourceLine);
else if (!mSourceName.IsEmpty())
} else if (!aSourceName.IsEmpty()) {
temp = JS_smprintf(format1,
severity,
aSeverity,
tempMessage,
tempSourceName,
mLineNumber);
else
aLineNumber);
} else {
temp = JS_smprintf(format2,
severity,
aSeverity,
tempMessage);
}
if (nullptr != tempMessage)
free(tempMessage);
@ -298,6 +307,18 @@ nsScriptErrorBase::ToString(nsACString& /*UTF8*/ aResult)
return NS_OK;
}
NS_IMETHODIMP
nsScriptErrorBase::ToString(nsACString& /*UTF8*/ aResult)
{
static const char error[] = "JavaScript Error";
static const char warning[] = "JavaScript Warning";
const char* severity = !(mFlags & JSREPORT_WARNING) ? error : warning;
return ToStringHelper(severity, mMessage, mSourceName, &mSourceLine,
mLineNumber, mColumnNumber, aResult);
}
NS_IMETHODIMP
nsScriptErrorBase::GetOuterWindowID(uint64_t* aOuterWindowID)
{
@ -342,4 +363,76 @@ nsScriptErrorBase::GetIsFromPrivateWindow(bool* aIsFromPrivateWindow)
return NS_OK;
}
NS_IMETHODIMP
nsScriptErrorBase::GetNotes(nsIArray** aNotes)
{
nsresult rv = NS_OK;
nsCOMPtr<nsIMutableArray> array =
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
uint32_t len = mNotes.Length();
for (uint32_t i = 0; i < len; i++)
array->AppendElement(mNotes[i], false);
array.forget(aNotes);
return NS_OK;
}
NS_IMPL_ISUPPORTS(nsScriptError, nsIConsoleMessage, nsIScriptError)
nsScriptErrorNote::nsScriptErrorNote()
: mMessage(),
mSourceName(),
mLineNumber(0),
mColumnNumber(0)
{
}
nsScriptErrorNote::~nsScriptErrorNote() {}
void
nsScriptErrorNote::Init(const nsAString& message,
const nsAString& sourceName,
uint32_t lineNumber,
uint32_t columnNumber)
{
mMessage.Assign(message);
AssignSourceNameHelper(mSourceName, sourceName);
mLineNumber = lineNumber;
mColumnNumber = columnNumber;
}
// nsIScriptErrorNote methods
NS_IMETHODIMP
nsScriptErrorNote::GetErrorMessage(nsAString& aResult) {
aResult.Assign(mMessage);
return NS_OK;
}
NS_IMETHODIMP
nsScriptErrorNote::GetSourceName(nsAString& aResult) {
aResult.Assign(mSourceName);
return NS_OK;
}
NS_IMETHODIMP
nsScriptErrorNote::GetLineNumber(uint32_t* result) {
*result = mLineNumber;
return NS_OK;
}
NS_IMETHODIMP
nsScriptErrorNote::GetColumnNumber(uint32_t* result) {
*result = mColumnNumber;
return NS_OK;
}
NS_IMETHODIMP
nsScriptErrorNote::ToString(nsACString& /*UTF8*/ aResult)
{
return ToStringHelper("JavaScript Note", mMessage, mSourceName, nullptr,
mLineNumber, mColumnNumber, aResult);
}
NS_IMPL_ISUPPORTS(nsScriptErrorNote, nsIScriptErrorNote)

View File

@ -17,6 +17,26 @@
#include "nsIScriptError.h"
#include "nsString.h"
class nsScriptErrorNote final : public nsIScriptErrorNote {
public:
nsScriptErrorNote();
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSISCRIPTERRORNOTE
void Init(const nsAString& message, const nsAString& sourceName,
uint32_t lineNumber, uint32_t columnNumber);
private:
virtual ~nsScriptErrorNote();
nsString mMessage;
nsString mSourceName;
nsString mSourceLine;
uint32_t mLineNumber;
uint32_t mColumnNumber;
};
// Definition of nsScriptError..
class nsScriptErrorBase : public nsIScriptError {
public:
@ -25,12 +45,15 @@ public:
NS_DECL_NSICONSOLEMESSAGE
NS_DECL_NSISCRIPTERROR
void AddNote(nsIScriptErrorNote* note);
protected:
virtual ~nsScriptErrorBase();
void
InitializeOnMainThread();
nsCOMArray<nsIScriptErrorNote> mNotes;
nsString mMessage;
nsString mMessageName;
nsString mSourceName;

View File

@ -87,6 +87,7 @@
#include "nsProxyRelease.h"
#include "nsQueryObject.h"
#include "nsSandboxFlags.h"
#include "nsScriptError.h"
#include "nsUTF8Utils.h"
#include "prthread.h"
#include "xpcpublic.h"
@ -281,27 +282,34 @@ struct WindowAction
};
void
LogErrorToConsole(const nsAString& aMessage,
const nsAString& aFilename,
const nsAString& aLine,
uint32_t aLineNumber,
uint32_t aColumnNumber,
uint32_t aFlags,
uint64_t aInnerWindowId)
LogErrorToConsole(const WorkerErrorReport& aReport, uint64_t aInnerWindowId)
{
AssertIsOnMainThread();
nsCOMPtr<nsIScriptError> scriptError =
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
RefPtr<nsScriptErrorBase> scriptError = new nsScriptError();
NS_WARNING_ASSERTION(scriptError, "Failed to create script error!");
if (scriptError) {
if (NS_FAILED(scriptError->InitWithWindowID(aMessage, aFilename, aLine,
aLineNumber, aColumnNumber,
aFlags, "Web Worker",
nsAutoCString category("Web Worker");
if (NS_FAILED(scriptError->InitWithWindowID(aReport.mMessage,
aReport.mFilename,
aReport.mLine,
aReport.mLineNumber,
aReport.mColumnNumber,
aReport.mFlags,
category,
aInnerWindowId))) {
NS_WARNING("Failed to init script error!");
scriptError = nullptr;
for (size_t i = 0, len = aReport.mNotes.Length(); i < len; i++) {
const WorkerErrorNote& note = aReport.mNotes.ElementAt(i);
nsScriptErrorNote* noteObject = new nsScriptErrorNote();
noteObject->Init(note.mMessage, note.mFilename,
note.mLineNumber, note.mColumnNumber);
scriptError->AddNote(noteObject);
}
}
}
@ -316,23 +324,23 @@ LogErrorToConsole(const nsAString& aMessage,
}
NS_WARNING("LogMessage failed!");
} else if (NS_SUCCEEDED(consoleService->LogStringMessage(
aMessage.BeginReading()))) {
aReport.mMessage.BeginReading()))) {
return;
}
NS_WARNING("LogStringMessage failed!");
}
NS_ConvertUTF16toUTF8 msg(aMessage);
NS_ConvertUTF16toUTF8 filename(aFilename);
NS_ConvertUTF16toUTF8 msg(aReport.mMessage);
NS_ConvertUTF16toUTF8 filename(aReport.mFilename);
static const char kErrorString[] = "JS error in Web Worker: %s [%s:%u]";
#ifdef ANDROID
__android_log_print(ANDROID_LOG_INFO, "Gecko", kErrorString, msg.get(),
filename.get(), aLineNumber);
filename.get(), aReport.mLineNumber);
#endif
fprintf(stderr, kErrorString, msg.get(), filename.get(), aLineNumber);
fprintf(stderr, kErrorString, msg.get(), filename.get(), aReport.mLineNumber);
fflush(stderr);
}
@ -536,10 +544,7 @@ private:
}
if (aWorkerPrivate->IsSharedWorker()) {
aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, EmptyString(),
EmptyString(),
EmptyString(), 0, 0,
JSREPORT_ERROR,
aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, nullptr,
/* isErrorEvent */ false);
return true;
}
@ -1060,15 +1065,7 @@ private:
class ReportErrorRunnable final : public WorkerRunnable
{
nsString mMessage;
nsString mFilename;
nsString mLine;
uint32_t mLineNumber;
uint32_t mColumnNumber;
uint32_t mFlags;
uint32_t mErrorNumber;
JSExnType mExnType;
bool mMutedError;
WorkerErrorReport mReport;
public:
// aWorkerPrivate is the worker thread we're on (or the main thread, if null)
@ -1077,11 +1074,7 @@ public:
static void
ReportError(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
bool aFireAtScope, WorkerPrivate* aTarget,
const nsString& aMessage, const nsString& aFilename,
const nsString& aLine, uint32_t aLineNumber,
uint32_t aColumnNumber, uint32_t aFlags,
uint32_t aErrorNumber, JSExnType aExnType,
bool aMutedError, uint64_t aInnerWindowId,
const WorkerErrorReport& aReport, uint64_t aInnerWindowId,
JS::Handle<JS::Value> aException = JS::NullHandleValue)
{
if (aWorkerPrivate) {
@ -1092,16 +1085,16 @@ public:
// We should not fire error events for warnings but instead make sure that
// they show up in the error console.
if (!JSREPORT_IS_WARNING(aFlags)) {
if (!JSREPORT_IS_WARNING(aReport.mFlags)) {
// First fire an ErrorEvent at the worker.
RootedDictionary<ErrorEventInit> init(aCx);
if (aMutedError) {
if (aReport.mMutedError) {
init.mMessage.AssignLiteral("Script error.");
} else {
init.mMessage = aMessage;
init.mFilename = aFilename;
init.mLineno = aLineNumber;
init.mMessage = aReport.mMessage;
init.mFilename = aReport.mFilename;
init.mLineno = aReport.mLineNumber;
init.mError = aException;
}
@ -1128,7 +1121,8 @@ public:
// into an error event on our parent worker!
// https://bugzilla.mozilla.org/show_bug.cgi?id=1271441 tracks making this
// better.
if (aFireAtScope && (aTarget || aErrorNumber != JSMSG_OVER_RECURSED)) {
if (aFireAtScope &&
(aTarget || aReport.mErrorNumber != JSMSG_OVER_RECURSED)) {
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
NS_ASSERTION(global, "This should never be null!");
@ -1145,8 +1139,8 @@ public:
MOZ_ASSERT_IF(globalScope, globalScope->GetWrapperPreserveColor() == global);
if (globalScope || IsDebuggerSandbox(global)) {
aWorkerPrivate->ReportErrorToDebugger(aFilename, aLineNumber,
aMessage);
aWorkerPrivate->ReportErrorToDebugger(aReport.mFilename, aReport.mLineNumber,
aReport.mMessage);
return;
}
@ -1193,28 +1187,20 @@ public:
// Now fire a runnable to do the same on the parent's thread if we can.
if (aWorkerPrivate) {
RefPtr<ReportErrorRunnable> runnable =
new ReportErrorRunnable(aWorkerPrivate, aMessage, aFilename, aLine,
aLineNumber, aColumnNumber, aFlags,
aErrorNumber, aExnType, aMutedError);
new ReportErrorRunnable(aWorkerPrivate, aReport);
runnable->Dispatch();
return;
}
// Otherwise log an error to the error console.
LogErrorToConsole(aMessage, aFilename, aLine, aLineNumber, aColumnNumber,
aFlags, aInnerWindowId);
LogErrorToConsole(aReport, aInnerWindowId);
}
private:
ReportErrorRunnable(WorkerPrivate* aWorkerPrivate, const nsString& aMessage,
const nsString& aFilename, const nsString& aLine,
uint32_t aLineNumber, uint32_t aColumnNumber,
uint32_t aFlags, uint32_t aErrorNumber,
JSExnType aExnType, bool aMutedError)
ReportErrorRunnable(WorkerPrivate* aWorkerPrivate,
const WorkerErrorReport& aReport)
: WorkerRunnable(aWorkerPrivate, ParentThreadUnchangedBusyCount),
mMessage(aMessage), mFilename(aFilename), mLine(aLine),
mLineNumber(aLineNumber), mColumnNumber(aColumnNumber), mFlags(aFlags),
mErrorNumber(aErrorNumber), mExnType(aExnType), mMutedError(aMutedError)
mReport(aReport)
{ }
virtual void
@ -1251,9 +1237,7 @@ private:
}
if (aWorkerPrivate->IsSharedWorker()) {
aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, mMessage, mFilename,
mLine, mLineNumber,
mColumnNumber, mFlags,
aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, &mReport,
/* isErrorEvent */ true);
return true;
}
@ -1267,9 +1251,10 @@ private:
swm->HandleError(aCx, aWorkerPrivate->GetPrincipal(),
aWorkerPrivate->WorkerName(),
aWorkerPrivate->ScriptURL(),
mMessage,
mFilename, mLine, mLineNumber,
mColumnNumber, mFlags, mExnType);
mReport.mMessage,
mReport.mFilename, mReport.mLine, mReport.mLineNumber,
mReport.mColumnNumber, mReport.mFlags,
mReport.mExnType);
}
return true;
}
@ -1289,9 +1274,8 @@ private:
return true;
}
ReportError(aCx, parent, fireAtScope, aWorkerPrivate, mMessage,
mFilename, mLine, mLineNumber, mColumnNumber, mFlags,
mErrorNumber, mExnType, mMutedError, innerWindowId);
ReportError(aCx, parent, fireAtScope, aWorkerPrivate, mReport,
innerWindowId);
return true;
}
};
@ -3314,21 +3298,16 @@ template <class Derived>
void
WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
JSContext* aCx,
const nsAString& aMessage,
const nsAString& aFilename,
const nsAString& aLine,
uint32_t aLineNumber,
uint32_t aColumnNumber,
uint32_t aFlags,
const WorkerErrorReport* aReport,
bool aIsErrorEvent)
{
AssertIsOnMainThread();
if (JSREPORT_IS_WARNING(aFlags)) {
if (aIsErrorEvent && JSREPORT_IS_WARNING(aReport->mFlags)) {
// Don't fire any events anywhere. Just log to console.
// XXXbz should we log to all the consoles of all the relevant windows?
LogErrorToConsole(aMessage, aFilename, aLine, aLineNumber, aColumnNumber,
aFlags, 0);
MOZ_ASSERT(aReport);
LogErrorToConsole(*aReport, 0);
return;
}
@ -3357,10 +3336,10 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
RootedDictionary<ErrorEventInit> errorInit(aCx);
errorInit.mBubbles = false;
errorInit.mCancelable = true;
errorInit.mMessage = aMessage;
errorInit.mFilename = aFilename;
errorInit.mLineno = aLineNumber;
errorInit.mColno = aColumnNumber;
errorInit.mMessage = aReport->mMessage;
errorInit.mFilename = aReport->mFilename;
errorInit.mLineno = aReport->mLineNumber;
errorInit.mColno = aReport->mColumnNumber;
event = ErrorEvent::Constructor(sharedWorker, NS_LITERAL_STRING("error"),
errorInit);
@ -3426,9 +3405,9 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
MOZ_ASSERT(NS_IsMainThread());
RootedDictionary<ErrorEventInit> init(aCx);
init.mLineno = aLineNumber;
init.mFilename = aFilename;
init.mMessage = aMessage;
init.mLineno = aReport->mLineNumber;
init.mFilename = aReport->mFilename;
init.mMessage = aReport->mMessage;
init.mCancelable = true;
init.mBubbles = true;
@ -3446,8 +3425,8 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
// Finally log a warning in the console if no window tried to prevent it.
if (shouldLogErrorToConsole) {
LogErrorToConsole(aMessage, aFilename, aLine, aLineNumber, aColumnNumber,
aFlags, 0);
MOZ_ASSERT(aReport);
LogErrorToConsole(*aReport, 0);
}
}
@ -4120,7 +4099,10 @@ WorkerDebugger::ReportErrorToDebuggerOnMainThread(const nsAString& aFilename,
listeners[index]->OnError(aFilename, aLineno, aMessage);
}
LogErrorToConsole(aMessage, aFilename, nsString(), aLineno, 0, 0, 0);
WorkerErrorReport report;
report.mMessage = aMessage;
report.mFilename = aFilename;
LogErrorToConsole(report, 0);
}
WorkerPrivate::WorkerPrivate(WorkerPrivate* aParent,
@ -5925,6 +5907,47 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus)
return false;
}
void
WorkerErrorBase::AssignErrorBase(JSErrorBase* aReport)
{
mFilename = NS_ConvertUTF8toUTF16(aReport->filename);
mLineNumber = aReport->lineno;
mColumnNumber = aReport->column;
mErrorNumber = aReport->errorNumber;
}
void
WorkerErrorNote::AssignErrorNote(JSErrorNotes::Note* aNote)
{
WorkerErrorBase::AssignErrorBase(aNote);
xpc::ErrorNote::ErrorNoteToMessageString(aNote, mMessage);
}
void
WorkerErrorReport::AssignErrorReport(JSErrorReport* aReport)
{
WorkerErrorBase::AssignErrorBase(aReport);
xpc::ErrorReport::ErrorReportToMessageString(aReport, mMessage);
mLine.Assign(aReport->linebuf(), aReport->linebufLength());
mFlags = aReport->flags;
MOZ_ASSERT(aReport->exnType >= JSEXN_FIRST && aReport->exnType < JSEXN_LIMIT);
mExnType = JSExnType(aReport->exnType);
mMutedError = aReport->isMuted;
if (aReport->notes) {
if (!mNotes.SetLength(aReport->notes->length(), fallible)) {
return;
}
size_t i = 0;
for (auto&& note : *aReport->notes) {
mNotes.ElementAt(i).AssignErrorNote(note.get());
i++;
}
}
}
void
WorkerPrivate::ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
JSErrorReport* aReport)
@ -5947,32 +5970,17 @@ WorkerPrivate::ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
}
JS_ClearPendingException(aCx);
nsString message, filename, line;
uint32_t lineNumber, columnNumber, flags, errorNumber;
JSExnType exnType = JSEXN_ERR;
bool mutedError = aReport && aReport->isMuted;
WorkerErrorReport report;
if (aReport) {
// We want the same behavior here as xpc::ErrorReport::init here.
xpc::ErrorReport::ErrorReportToMessageString(aReport, message);
filename = NS_ConvertUTF8toUTF16(aReport->filename);
line.Assign(aReport->linebuf(), aReport->linebufLength());
lineNumber = aReport->lineno;
columnNumber = aReport->tokenOffset();
flags = aReport->flags;
errorNumber = aReport->errorNumber;
MOZ_ASSERT(aReport->exnType >= JSEXN_FIRST && aReport->exnType < JSEXN_LIMIT);
exnType = JSExnType(aReport->exnType);
report.AssignErrorReport(aReport);
}
else {
lineNumber = columnNumber = errorNumber = 0;
flags = nsIScriptError::errorFlag | nsIScriptError::exceptionFlag;
report.mFlags = nsIScriptError::errorFlag | nsIScriptError::exceptionFlag;
}
if (message.IsEmpty() && aToStringResult) {
if (report.mMessage.IsEmpty() && aToStringResult) {
nsDependentCString toStringResult(aToStringResult.c_str());
if (!AppendUTF8toUTF16(toStringResult, message, mozilla::fallible)) {
if (!AppendUTF8toUTF16(toStringResult, report.mMessage, mozilla::fallible)) {
// Try again, with only a 1 KB string. Do this infallibly this time.
// If the user doesn't have 1 KB to spare we're done anyways.
uint32_t index = std::min(uint32_t(1024), toStringResult.Length());
@ -5982,7 +5990,7 @@ WorkerPrivate::ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
nsDependentCString truncatedToStringResult(aToStringResult.c_str(),
index);
AppendUTF8toUTF16(truncatedToStringResult, message);
AppendUTF8toUTF16(truncatedToStringResult, report.mMessage);
}
}
@ -5991,13 +5999,11 @@ WorkerPrivate::ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
// Don't want to run the scope's error handler if this is a recursive error or
// if we ran out of memory.
bool fireAtScope = mErrorHandlerRecursionCount == 1 &&
errorNumber != JSMSG_OUT_OF_MEMORY &&
report.mErrorNumber != JSMSG_OUT_OF_MEMORY &&
JS::CurrentGlobalOrNull(aCx);
ReportErrorRunnable::ReportError(aCx, this, fireAtScope, nullptr, message,
filename, line, lineNumber,
columnNumber, flags, errorNumber, exnType,
mutedError, 0, exn);
ReportErrorRunnable::ReportError(aCx, this, fireAtScope, nullptr, report, 0,
exn);
mErrorHandlerRecursionCount--;
}

View File

@ -140,6 +140,45 @@ public:
}
};
class WorkerErrorBase {
public:
nsString mMessage;
nsString mFilename;
uint32_t mLineNumber;
uint32_t mColumnNumber;
uint32_t mErrorNumber;
WorkerErrorBase()
: mLineNumber(0),
mColumnNumber(0),
mErrorNumber(0)
{ }
void AssignErrorBase(JSErrorBase* aReport);
};
class WorkerErrorNote : public WorkerErrorBase {
public:
void AssignErrorNote(JSErrorNotes::Note* aNote);
};
class WorkerErrorReport : public WorkerErrorBase {
public:
nsString mLine;
uint32_t mFlags;
JSExnType mExnType;
bool mMutedError;
nsTArray<WorkerErrorNote> mNotes;
WorkerErrorReport()
: mFlags(0),
mExnType(JSEXN_ERR),
mMutedError(false)
{ }
void AssignErrorReport(JSErrorReport* aReport);
};
template <class Derived>
class WorkerPrivateParent : public DOMEventTargetHelper
{
@ -401,12 +440,7 @@ public:
void
BroadcastErrorToSharedWorkers(JSContext* aCx,
const nsAString& aMessage,
const nsAString& aFilename,
const nsAString& aLine,
uint32_t aLineNumber,
uint32_t aColumnNumber,
uint32_t aFlags,
const WorkerErrorReport* aReport,
bool aIsErrorEvent);
void

View File

@ -94,6 +94,7 @@ LOCAL_INCLUDES += [
'../base',
'../system',
'/dom/base',
'/dom/bindings',
'/xpcom/build',
'/xpcom/threads',
]

View File

@ -23,7 +23,7 @@
const errorFilename = href.substring(0, href.lastIndexOf("/") + 1) +
filename;
const errorLine = 91;
const errorColumn = 0;
const errorColumn = 11;
var worker = new SharedWorker(filename);

View File

@ -4043,6 +4043,32 @@ IsConstructor(JSContext* cx, unsigned argc, Value* vp)
return true;
}
static bool
GetErrorNotes(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (!args.requireAtLeast(cx, "getErrorNotes", 1))
return false;
if (!args[0].isObject() || !args[0].toObject().is<ErrorObject>()) {
args.rval().setNull();
return true;
}
JSErrorReport* report = args[0].toObject().as<ErrorObject>().getErrorReport();
if (!report) {
args.rval().setNull();
return true;
}
RootedObject notesArray(cx, CreateErrorNotesArray(cx, report));
if (!notesArray)
return false;
args.rval().setObject(*notesArray);
return true;
}
static const JSFunctionSpecWithHelp TestingFunctions[] = {
JS_FN_HELP("gc", ::GC, 0, 0,
"gc([obj] | 'zone' [, 'shrinking'])",
@ -4577,6 +4603,10 @@ static const JSFunctionSpecWithHelp FuzzingUnsafeTestingFunctions[] = {
" Dumps RegExp bytecode."),
#endif
JS_FN_HELP("getErrorNotes", GetErrorNotes, 1, 0,
"getErrorNotes(error)",
" Returns an array of error notes."),
JS_FS_HELP_END
};

View File

@ -3604,7 +3604,7 @@ BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, ...)
va_list args;
va_start(args, errorNumber);
bool result = tokenStream()->reportCompileErrorNumberVA(pos.begin, JSREPORT_ERROR,
bool result = tokenStream()->reportCompileErrorNumberVA(nullptr, pos.begin, JSREPORT_ERROR,
errorNumber, args);
va_end(args);
return result;
@ -3617,7 +3617,8 @@ BytecodeEmitter::reportExtraWarning(ParseNode* pn, unsigned errorNumber, ...)
va_list args;
va_start(args, errorNumber);
bool result = tokenStream()->reportExtraWarningErrorNumberVA(pos.begin, errorNumber, args);
bool result = tokenStream()->reportExtraWarningErrorNumberVA(nullptr, pos.begin,
errorNumber, args);
va_end(args);
return result;
}
@ -3629,7 +3630,7 @@ BytecodeEmitter::reportStrictModeError(ParseNode* pn, unsigned errorNumber, ...)
va_list args;
va_start(args, errorNumber);
bool result = tokenStream()->reportStrictModeErrorNumberVA(pos.begin, sc->strict(),
bool result = tokenStream()->reportStrictModeErrorNumberVA(nullptr, pos.begin, sc->strict(),
errorNumber, args);
va_end(args);
return result;

View File

@ -579,7 +579,22 @@ ParserBase::error(unsigned errorNumber, ...)
#ifdef DEBUG
bool result =
#endif
tokenStream.reportCompileErrorNumberVA(pos().begin, JSREPORT_ERROR, errorNumber, args);
tokenStream.reportCompileErrorNumberVA(nullptr, pos().begin, JSREPORT_ERROR,
errorNumber, args);
MOZ_ASSERT(!result, "reporting an error returned true?");
va_end(args);
}
void
ParserBase::errorWithNotes(UniquePtr<JSErrorNotes> notes, unsigned errorNumber, ...)
{
va_list args;
va_start(args, errorNumber);
#ifdef DEBUG
bool result =
#endif
tokenStream.reportCompileErrorNumberVA(Move(notes), pos().begin, JSREPORT_ERROR,
errorNumber, args);
MOZ_ASSERT(!result, "reporting an error returned true?");
va_end(args);
}
@ -592,7 +607,22 @@ ParserBase::errorAt(uint32_t offset, unsigned errorNumber, ...)
#ifdef DEBUG
bool result =
#endif
tokenStream.reportCompileErrorNumberVA(offset, JSREPORT_ERROR, errorNumber, args);
tokenStream.reportCompileErrorNumberVA(nullptr, offset, JSREPORT_ERROR, errorNumber, args);
MOZ_ASSERT(!result, "reporting an error returned true?");
va_end(args);
}
void
ParserBase::errorWithNotesAt(UniquePtr<JSErrorNotes> notes, uint32_t offset,
unsigned errorNumber, ...)
{
va_list args;
va_start(args, errorNumber);
#ifdef DEBUG
bool result =
#endif
tokenStream.reportCompileErrorNumberVA(Move(notes), offset, JSREPORT_ERROR,
errorNumber, args);
MOZ_ASSERT(!result, "reporting an error returned true?");
va_end(args);
}
@ -603,7 +633,8 @@ ParserBase::warning(unsigned errorNumber, ...)
va_list args;
va_start(args, errorNumber);
bool result =
tokenStream.reportCompileErrorNumberVA(pos().begin, JSREPORT_WARNING, errorNumber, args);
tokenStream.reportCompileErrorNumberVA(nullptr, pos().begin, JSREPORT_WARNING,
errorNumber, args);
va_end(args);
return result;
}
@ -614,7 +645,8 @@ ParserBase::warningAt(uint32_t offset, unsigned errorNumber, ...)
va_list args;
va_start(args, errorNumber);
bool result =
tokenStream.reportCompileErrorNumberVA(offset, JSREPORT_WARNING, errorNumber, args);
tokenStream.reportCompileErrorNumberVA(nullptr, offset, JSREPORT_WARNING,
errorNumber, args);
va_end(args);
return result;
}
@ -624,7 +656,8 @@ ParserBase::extraWarning(unsigned errorNumber, ...)
{
va_list args;
va_start(args, errorNumber);
bool result = tokenStream.reportExtraWarningErrorNumberVA(pos().begin, errorNumber, args);
bool result = tokenStream.reportExtraWarningErrorNumberVA(nullptr, pos().begin,
errorNumber, args);
va_end(args);
return result;
}
@ -635,7 +668,7 @@ ParserBase::strictModeError(unsigned errorNumber, ...)
va_list args;
va_start(args, errorNumber);
bool res =
tokenStream.reportStrictModeErrorNumberVA(pos().begin, pc->sc()->strict(),
tokenStream.reportStrictModeErrorNumberVA(nullptr, pos().begin, pc->sc()->strict(),
errorNumber, args);
va_end(args);
return res;
@ -647,7 +680,8 @@ ParserBase::strictModeErrorAt(uint32_t offset, unsigned errorNumber, ...)
va_list args;
va_start(args, errorNumber);
bool res =
tokenStream.reportStrictModeErrorNumberVA(offset, pc->sc()->strict(), errorNumber, args);
tokenStream.reportStrictModeErrorNumberVA(nullptr, offset, pc->sc()->strict(),
errorNumber, args);
va_end(args);
return res;
}
@ -661,17 +695,21 @@ ParserBase::reportNoOffset(ParseReportKind kind, bool strict, unsigned errorNumb
uint32_t offset = TokenStream::NoOffset;
switch (kind) {
case ParseError:
result = tokenStream.reportCompileErrorNumberVA(offset, JSREPORT_ERROR, errorNumber, args);
result = tokenStream.reportCompileErrorNumberVA(nullptr, offset, JSREPORT_ERROR,
errorNumber, args);
break;
case ParseWarning:
result =
tokenStream.reportCompileErrorNumberVA(offset, JSREPORT_WARNING, errorNumber, args);
tokenStream.reportCompileErrorNumberVA(nullptr, offset, JSREPORT_WARNING,
errorNumber, args);
break;
case ParseExtraWarning:
result = tokenStream.reportExtraWarningErrorNumberVA(offset, errorNumber, args);
result = tokenStream.reportExtraWarningErrorNumberVA(nullptr, offset,
errorNumber, args);
break;
case ParseStrictError:
result = tokenStream.reportStrictModeErrorNumberVA(offset, strict, errorNumber, args);
result = tokenStream.reportStrictModeErrorNumberVA(nullptr, offset, strict,
errorNumber, args);
break;
}
va_end(args);

View File

@ -824,9 +824,12 @@ class ParserBase : public StrictModeGetter
/* Report the given error at the current offset. */
void error(unsigned errorNumber, ...);
void errorWithNotes(UniquePtr<JSErrorNotes> notes, unsigned errorNumber, ...);
/* Report the given error at the given offset. */
void errorAt(uint32_t offset, unsigned errorNumber, ...);
void errorWithNotesAt(UniquePtr<JSErrorNotes> notes, uint32_t offset,
unsigned errorNumber, ...);
/*
* Handle a strict mode error at the current offset. Report an error if in

View File

@ -607,8 +607,8 @@ TokenStream::seek(const Position& pos, const TokenStream& other)
}
bool
TokenStream::reportStrictModeErrorNumberVA(uint32_t offset, bool strictMode, unsigned errorNumber,
va_list args)
TokenStream::reportStrictModeErrorNumberVA(UniquePtr<JSErrorNotes> notes, uint32_t offset,
bool strictMode, unsigned errorNumber, va_list args)
{
// In strict mode code, this is an error, not merely a warning.
unsigned flags;
@ -619,7 +619,7 @@ TokenStream::reportStrictModeErrorNumberVA(uint32_t offset, bool strictMode, uns
else
return true;
return reportCompileErrorNumberVA(offset, flags, errorNumber, args);
return reportCompileErrorNumberVA(Move(notes), offset, flags, errorNumber, args);
}
void
@ -645,8 +645,8 @@ CompileError::throwError(JSContext* cx)
}
bool
TokenStream::reportCompileErrorNumberVA(uint32_t offset, unsigned flags, unsigned errorNumber,
va_list args)
TokenStream::reportCompileErrorNumberVA(UniquePtr<JSErrorNotes> notes, uint32_t offset,
unsigned flags, unsigned errorNumber, va_list args)
{
bool warning = JSREPORT_IS_WARNING(flags);
@ -663,6 +663,7 @@ TokenStream::reportCompileErrorNumberVA(uint32_t offset, unsigned flags, unsigne
return false;
CompileError& err = *tempErrPtr;
err.notes = Move(notes);
err.flags = flags;
err.errorNumber = errorNumber;
err.filename = filename;
@ -754,7 +755,7 @@ TokenStream::reportStrictModeError(unsigned errorNumber, ...)
{
va_list args;
va_start(args, errorNumber);
bool result = reportStrictModeErrorNumberVA(currentToken().pos.begin, strictMode(),
bool result = reportStrictModeErrorNumberVA(nullptr, currentToken().pos.begin, strictMode(),
errorNumber, args);
va_end(args);
return result;
@ -765,8 +766,8 @@ TokenStream::reportError(unsigned errorNumber, ...)
{
va_list args;
va_start(args, errorNumber);
bool result = reportCompileErrorNumberVA(currentToken().pos.begin, JSREPORT_ERROR, errorNumber,
args);
bool result = reportCompileErrorNumberVA(nullptr, currentToken().pos.begin, JSREPORT_ERROR,
errorNumber, args);
va_end(args);
return result;
}
@ -776,8 +777,8 @@ TokenStream::reportErrorNoOffset(unsigned errorNumber, ...)
{
va_list args;
va_start(args, errorNumber);
bool result = reportCompileErrorNumberVA(NoOffset, JSREPORT_ERROR, errorNumber,
args);
bool result = reportCompileErrorNumberVA(nullptr, NoOffset, JSREPORT_ERROR,
errorNumber, args);
va_end(args);
return result;
}
@ -787,19 +788,21 @@ TokenStream::warning(unsigned errorNumber, ...)
{
va_list args;
va_start(args, errorNumber);
bool result = reportCompileErrorNumberVA(currentToken().pos.begin, JSREPORT_WARNING,
bool result = reportCompileErrorNumberVA(nullptr, currentToken().pos.begin, JSREPORT_WARNING,
errorNumber, args);
va_end(args);
return result;
}
bool
TokenStream::reportExtraWarningErrorNumberVA(uint32_t offset, unsigned errorNumber, va_list args)
TokenStream::reportExtraWarningErrorNumberVA(UniquePtr<JSErrorNotes> notes, uint32_t offset,
unsigned errorNumber, va_list args)
{
if (!options().extraWarningsOption)
return true;
return reportCompileErrorNumberVA(offset, JSREPORT_STRICT|JSREPORT_WARNING, errorNumber, args);
return reportCompileErrorNumberVA(Move(notes), offset, JSREPORT_STRICT|JSREPORT_WARNING,
errorNumber, args);
}
void
@ -810,7 +813,7 @@ TokenStream::reportAsmJSError(uint32_t offset, unsigned errorNumber, ...)
unsigned flags = options().throwOnAsmJSValidationFailureOption
? JSREPORT_ERROR
: JSREPORT_WARNING;
reportCompileErrorNumberVA(offset, flags, errorNumber, args);
reportCompileErrorNumberVA(nullptr, offset, flags, errorNumber, args);
va_end(args);
}
@ -822,7 +825,8 @@ TokenStream::error(unsigned errorNumber, ...)
#ifdef DEBUG
bool result =
#endif
reportCompileErrorNumberVA(currentToken().pos.begin, JSREPORT_ERROR, errorNumber, args);
reportCompileErrorNumberVA(nullptr, currentToken().pos.begin, JSREPORT_ERROR,
errorNumber, args);
MOZ_ASSERT(!result, "reporting an error returned true?");
va_end(args);
}
@ -835,7 +839,7 @@ TokenStream::errorAt(uint32_t offset, unsigned errorNumber, ...)
#ifdef DEBUG
bool result =
#endif
reportCompileErrorNumberVA(offset, JSREPORT_ERROR, errorNumber, args);
reportCompileErrorNumberVA(nullptr, offset, JSREPORT_ERROR, errorNumber, args);
MOZ_ASSERT(!result, "reporting an error returned true?");
va_end(args);
}

View File

@ -410,11 +410,12 @@ class MOZ_STACK_CLASS TokenStream
// General-purpose error reporters. You should avoid calling these
// directly, and instead use the more succinct alternatives (error(),
// warning(), &c.) in TokenStream, Parser, and BytecodeEmitter.
bool reportCompileErrorNumberVA(uint32_t offset, unsigned flags, unsigned errorNumber,
va_list args);
bool reportStrictModeErrorNumberVA(uint32_t offset, bool strictMode, unsigned errorNumber,
va_list args);
bool reportExtraWarningErrorNumberVA(uint32_t offset, unsigned errorNumber, va_list args);
bool reportCompileErrorNumberVA(UniquePtr<JSErrorNotes> notes, uint32_t offset, unsigned flags,
unsigned errorNumber, va_list args);
bool reportStrictModeErrorNumberVA(UniquePtr<JSErrorNotes> notes, uint32_t offset,
bool strictMode, unsigned errorNumber, va_list args);
bool reportExtraWarningErrorNumberVA(UniquePtr<JSErrorNotes> notes, uint32_t offset,
unsigned errorNumber, va_list args);
// asm.js reporter
void reportAsmJSError(uint32_t offset, unsigned errorNumber, ...);

View File

@ -69,7 +69,6 @@
#include "js/Proxy.h"
#include "js/SliceBudget.h"
#include "js/StructuredClone.h"
#include "js/UniquePtr.h"
#include "js/Utility.h"
#include "vm/AsyncFunction.h"
#include "vm/DateObject.h"
@ -6300,7 +6299,7 @@ JSErrorReport::freeLinebuf()
}
JSString*
JSErrorReport::newMessageString(JSContext* cx)
JSErrorBase::newMessageString(JSContext* cx)
{
if (!message_)
return cx->runtime()->emptyString;
@ -6309,7 +6308,7 @@ JSErrorReport::newMessageString(JSContext* cx)
}
void
JSErrorReport::freeMessage()
JSErrorBase::freeMessage()
{
if (ownsMessage_) {
js_free((void*)message_.get());
@ -6318,6 +6317,132 @@ JSErrorReport::freeMessage()
message_ = JS::ConstUTF8CharsZ();
}
JSErrorNotes::JSErrorNotes()
: notes_()
{}
JSErrorNotes::~JSErrorNotes()
{
}
static UniquePtr<JSErrorNotes::Note>
CreateErrorNoteVA(ExclusiveContext* cx,
const char* filename, unsigned lineno, unsigned column,
JSErrorCallback errorCallback, void* userRef,
const unsigned errorNumber,
ErrorArgumentsType argumentsType, va_list ap)
{
auto note = MakeUnique<JSErrorNotes::Note>();
if (!note)
return nullptr;
note->errorNumber = errorNumber;
note->filename = filename;
note->lineno = lineno;
note->column = column;
if (!ExpandErrorArgumentsVA(cx, errorCallback, userRef, errorNumber,
nullptr, argumentsType, note.get(), ap)) {
return nullptr;
}
return note;
}
bool
JSErrorNotes::addNoteASCII(JSContext* cx,
const char* filename, unsigned lineno, unsigned column,
JSErrorCallback errorCallback, void* userRef,
const unsigned errorNumber, ...)
{
va_list ap;
va_start(ap, errorNumber);
auto note = CreateErrorNoteVA(cx, filename, lineno, column, errorCallback, userRef,
errorNumber, ArgumentsAreASCII, ap);
va_end(ap);
if (!note)
return false;
if (!notes_.append(Move(note)))
return false;
return true;
}
bool
JSErrorNotes::addNoteLatin1(JSContext* cx,
const char* filename, unsigned lineno, unsigned column,
JSErrorCallback errorCallback, void* userRef,
const unsigned errorNumber, ...)
{
va_list ap;
va_start(ap, errorNumber);
auto note = CreateErrorNoteVA(cx, filename, lineno, column, errorCallback, userRef,
errorNumber, ArgumentsAreLatin1, ap);
va_end(ap);
if (!note)
return false;
if (!notes_.append(Move(note)))
return false;
return true;
}
bool
JSErrorNotes::addNoteUTF8(JSContext* cx,
const char* filename, unsigned lineno, unsigned column,
JSErrorCallback errorCallback, void* userRef,
const unsigned errorNumber, ...)
{
va_list ap;
va_start(ap, errorNumber);
auto note = CreateErrorNoteVA(cx, filename, lineno, column, errorCallback, userRef,
errorNumber, ArgumentsAreUTF8, ap);
va_end(ap);
if (!note)
return false;
if (!notes_.append(Move(note)))
return false;
return true;
}
size_t
JSErrorNotes::length()
{
return notes_.length();
}
UniquePtr<JSErrorNotes>
JSErrorNotes::copy(JSContext* cx)
{
auto copiedNotes = MakeUnique<JSErrorNotes>();
if (!copiedNotes)
return nullptr;
for (auto&& note : *this) {
js::UniquePtr<JSErrorNotes::Note> copied(CopyErrorNote(cx, note.get()));
if (!copied)
return nullptr;
if (!copiedNotes->notes_.append(Move(copied)))
return nullptr;
}
return copiedNotes;
}
JSErrorNotes::iterator
JSErrorNotes::begin()
{
return iterator(notes_.begin());
}
JSErrorNotes::iterator
JSErrorNotes::end()
{
return iterator(notes_.end());
}
JS_PUBLIC_API(bool)
JS_ThrowStopIteration(JSContext* cx)
{

View File

@ -18,6 +18,7 @@
#include "mozilla/RefPtr.h"
#include "mozilla/Variant.h"
#include <iterator>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
@ -36,6 +37,7 @@
#include "js/Realm.h"
#include "js/RootingAPI.h"
#include "js/TracingAPI.h"
#include "js/UniquePtr.h"
#include "js/Utility.h"
#include "js/Value.h"
#include "js/Vector.h"
@ -652,6 +654,7 @@ typedef enum JSExnType {
JSEXN_WASMRUNTIMEERROR,
JSEXN_ERROR_LIMIT,
JSEXN_WARN = JSEXN_ERROR_LIMIT,
JSEXN_NOTE,
JSEXN_LIMIT
} JSExnType;
@ -5362,65 +5365,43 @@ JS_ReportOutOfMemory(JSContext* cx);
extern JS_PUBLIC_API(void)
JS_ReportAllocationOverflow(JSContext* cx);
class JSErrorReport
/**
* Base class that implements parts shared by JSErrorReport and
* JSErrorNotes::Note.
*/
class JSErrorBase
{
// The (default) error message.
// If ownsMessage_ is true, the it is freed in destructor.
JS::ConstUTF8CharsZ message_;
// Offending source line without final '\n'.
// If ownsLinebuf__ is true, the buffer is freed in destructor.
const char16_t* linebuf_;
// Number of chars in linebuf_. Does not include trailing '\0'.
size_t linebufLength_;
// The 0-based offset of error token in linebuf_.
size_t tokenOffset_;
public:
JSErrorReport()
: linebuf_(nullptr), linebufLength_(0), tokenOffset_(0),
filename(nullptr), lineno(0), column(0),
flags(0), errorNumber(0),
exnType(0), isMuted(false),
ownsLinebuf_(false), ownsMessage_(false)
JSErrorBase()
: filename(nullptr), lineno(0), column(0),
errorNumber(0),
ownsMessage_(false)
{}
~JSErrorReport() {
freeLinebuf();
~JSErrorBase() {
freeMessage();
}
const char* filename; /* source file name, URL, etc., or null */
unsigned lineno; /* source line number */
unsigned column; /* zero-based column index in line */
unsigned flags; /* error/warning, etc. */
unsigned errorNumber; /* the error number, e.g. see js.msg */
int16_t exnType; /* One of the JSExnType constants */
bool isMuted : 1; /* See the comment in ReadOnlyCompileOptions. */
// Source file name, URL, etc., or null.
const char* filename;
// Source line number.
unsigned lineno;
// Zero-based column index in line.
unsigned column;
// the error number, e.g. see js.msg.
unsigned errorNumber;
private:
bool ownsLinebuf_ : 1;
bool ownsMessage_ : 1;
public:
const char16_t* linebuf() const {
return linebuf_;
}
size_t linebufLength() const {
return linebufLength_;
}
size_t tokenOffset() const {
return tokenOffset_;
}
void initOwnedLinebuf(const char16_t* linebufArg, size_t linebufLengthArg, size_t tokenOffsetArg) {
initBorrowedLinebuf(linebufArg, linebufLengthArg, tokenOffsetArg);
ownsLinebuf_ = true;
}
void initBorrowedLinebuf(const char16_t* linebufArg, size_t linebufLengthArg, size_t tokenOffsetArg);
void freeLinebuf();
const JS::ConstUTF8CharsZ message() const {
return message_;
}
@ -5436,9 +5417,135 @@ class JSErrorReport
JSString* newMessageString(JSContext* cx);
private:
void freeMessage();
};
/**
* Notes associated with JSErrorReport.
*/
class JSErrorNotes
{
public:
class Note : public JSErrorBase
{};
private:
// Stores pointers to each note.
js::Vector<js::UniquePtr<Note>, 1, js::SystemAllocPolicy> notes_;
public:
JSErrorNotes();
~JSErrorNotes();
// Add an note to the given position.
bool addNoteASCII(JSContext* cx,
const char* filename, unsigned lineno, unsigned column,
JSErrorCallback errorCallback, void* userRef,
const unsigned errorNumber, ...);
bool addNoteLatin1(JSContext* cx,
const char* filename, unsigned lineno, unsigned column,
JSErrorCallback errorCallback, void* userRef,
const unsigned errorNumber, ...);
bool addNoteUTF8(JSContext* cx,
const char* filename, unsigned lineno, unsigned column,
JSErrorCallback errorCallback, void* userRef,
const unsigned errorNumber, ...);
size_t length();
// Create a deep copy of notes.
js::UniquePtr<JSErrorNotes> copy(JSContext* cx);
class iterator : public std::iterator<std::input_iterator_tag, js::UniquePtr<Note>>
{
js::UniquePtr<Note>* note_;
public:
explicit iterator(js::UniquePtr<Note>* note = nullptr) : note_(note)
{}
bool operator==(iterator other) const {
return note_ == other.note_;
}
bool operator!=(iterator other) const {
return !(*this == other);
}
iterator& operator++() {
note_++;
return *this;
}
reference operator*() {
return *note_;
}
};
iterator begin();
iterator end();
};
/**
* Describes a single error or warning that occurs in the execution of script.
*/
class JSErrorReport : public JSErrorBase
{
// Offending source line without final '\n'.
// If ownsLinebuf_ is true, the buffer is freed in destructor.
const char16_t* linebuf_;
// Number of chars in linebuf_. Does not include trailing '\0'.
size_t linebufLength_;
// The 0-based offset of error token in linebuf_.
size_t tokenOffset_;
public:
JSErrorReport()
: linebuf_(nullptr), linebufLength_(0), tokenOffset_(0),
notes(nullptr),
flags(0), exnType(0), isMuted(false),
ownsLinebuf_(false)
{}
~JSErrorReport() {
freeLinebuf();
}
// Associated notes, or nullptr if there's no note.
js::UniquePtr<JSErrorNotes> notes;
// error/warning, etc.
unsigned flags;
// One of the JSExnType constants.
int16_t exnType;
// See the comment in ReadOnlyCompileOptions.
bool isMuted : 1;
private:
bool ownsLinebuf_ : 1;
public:
const char16_t* linebuf() const {
return linebuf_;
}
size_t linebufLength() const {
return linebufLength_;
}
size_t tokenOffset() const {
return tokenOffset_;
}
void initOwnedLinebuf(const char16_t* linebufArg, size_t linebufLengthArg,
size_t tokenOffsetArg) {
initBorrowedLinebuf(linebufArg, linebufLengthArg, tokenOffsetArg);
ownsLinebuf_ = true;
}
void initBorrowedLinebuf(const char16_t* linebufArg, size_t linebufLengthArg,
size_t tokenOffsetArg);
private:
void freeLinebuf();
};
/*
* JSErrorReport flag values. These may be freely composed.
*/

View File

@ -381,49 +381,16 @@ js::ReportUsageErrorASCII(JSContext* cx, HandleObject callee, const char* msg)
}
}
bool
js::PrintError(JSContext* cx, FILE* file, JS::ConstUTF8CharsZ toStringResult,
JSErrorReport* report, bool reportWarnings)
enum class PrintErrorKind {
Error,
Warning,
StrictWarning,
Note
};
static void
PrintErrorLine(JSContext* cx, FILE* file, const char* prefix, JSErrorReport* report)
{
MOZ_ASSERT(report);
/* Conditionally ignore reported warnings. */
if (JSREPORT_IS_WARNING(report->flags) && !reportWarnings)
return false;
char* prefix = nullptr;
if (report->filename)
prefix = JS_smprintf("%s:", report->filename);
if (report->lineno) {
char* tmp = prefix;
prefix = JS_smprintf("%s%u:%u ", tmp ? tmp : "", report->lineno, report->column);
JS_free(cx, tmp);
}
if (JSREPORT_IS_WARNING(report->flags)) {
char* tmp = prefix;
prefix = JS_smprintf("%s%swarning: ",
tmp ? tmp : "",
JSREPORT_IS_STRICT(report->flags) ? "strict " : "");
JS_free(cx, tmp);
}
const char* message = toStringResult ? toStringResult.c_str() : report->message().c_str();
/* embedded newlines -- argh! */
const char* ctmp;
while ((ctmp = strchr(message, '\n')) != 0) {
ctmp++;
if (prefix)
fputs(prefix, file);
fwrite(message, 1, ctmp - message, file);
message = ctmp;
}
/* If there were no filename or lineno, the prefix might be empty */
if (prefix)
fputs(prefix, file);
fputs(message, file);
if (const char16_t* linebuf = report->linebuf()) {
size_t n = report->linebufLength();
@ -453,9 +420,96 @@ js::PrintError(JSContext* cx, FILE* file, JS::ConstUTF8CharsZ toStringResult,
}
fputc('^', file);
}
}
static void
PrintErrorLine(JSContext* cx, FILE* file, const char* prefix, JSErrorNotes::Note* note)
{
}
template <typename T>
static bool
PrintSingleError(JSContext* cx, FILE* file, JS::ConstUTF8CharsZ toStringResult,
T* report, PrintErrorKind kind)
{
UniquePtr<char> prefix;
if (report->filename)
prefix.reset(JS_smprintf("%s:", report->filename));
if (report->lineno) {
UniquePtr<char> tmp(JS_smprintf("%s%u:%u ", prefix ? prefix.get() : "", report->lineno,
report->column));
prefix = Move(tmp);
}
if (kind != PrintErrorKind::Error) {
const char* kindPrefix = nullptr;
switch (kind) {
case PrintErrorKind::Error:
break;
case PrintErrorKind::Warning:
kindPrefix = "warning";
break;
case PrintErrorKind::StrictWarning:
kindPrefix = "strict warning";
break;
case PrintErrorKind::Note:
kindPrefix = "note";
break;
}
UniquePtr<char> tmp(JS_smprintf("%s%s: ", prefix ? prefix.get() : "", kindPrefix));
prefix = Move(tmp);
}
const char* message = toStringResult ? toStringResult.c_str() : report->message().c_str();
/* embedded newlines -- argh! */
const char* ctmp;
while ((ctmp = strchr(message, '\n')) != 0) {
ctmp++;
if (prefix)
fputs(prefix.get(), file);
fwrite(message, 1, ctmp - message, file);
message = ctmp;
}
/* If there were no filename or lineno, the prefix might be empty */
if (prefix)
fputs(prefix.get(), file);
fputs(message, file);
PrintErrorLine(cx, file, prefix.get(), report);
fputc('\n', file);
fflush(file);
JS_free(cx, prefix);
return true;
}
bool
js::PrintError(JSContext* cx, FILE* file, JS::ConstUTF8CharsZ toStringResult,
JSErrorReport* report, bool reportWarnings)
{
MOZ_ASSERT(report);
/* Conditionally ignore reported warnings. */
if (JSREPORT_IS_WARNING(report->flags) && !reportWarnings)
return false;
PrintErrorKind kind = PrintErrorKind::Error;
if (JSREPORT_IS_WARNING(report->flags)) {
if (JSREPORT_IS_STRICT(report->flags))
kind = PrintErrorKind::StrictWarning;
else
kind = PrintErrorKind::Warning;
}
PrintSingleError(cx, file, toStringResult, report, kind);
if (report->notes) {
for (auto&& note : *report->notes)
PrintSingleError(cx, file, JS::ConstUTF8CharsZ(), note.get(), PrintErrorKind::Note);
}
return true;
}
@ -557,6 +611,18 @@ class MOZ_RAII AutoMessageArgs
}
};
static void
SetExnType(JSErrorReport* reportp, int16_t exnType)
{
reportp->exnType = exnType;
}
static void
SetExnType(JSErrorNotes::Note* notep, int16_t exnType)
{
// Do nothing for JSErrorNotes::Note.
}
/*
* The arguments from ap need to be packaged up into an array and stored
* into the report struct.
@ -568,12 +634,13 @@ class MOZ_RAII AutoMessageArgs
*
* Returns true if the expansion succeeds (can fail if out of memory).
*/
template <typename T>
bool
js::ExpandErrorArgumentsVA(ExclusiveContext* cx, JSErrorCallback callback,
ExpandErrorArgumentsHelper(ExclusiveContext* cx, JSErrorCallback callback,
void* userRef, const unsigned errorNumber,
const char16_t** messageArgs,
ErrorArgumentsType argumentsType,
JSErrorReport* reportp, va_list ap)
T* reportp, va_list ap)
{
const JSErrorFormatString* efs;
@ -586,7 +653,7 @@ js::ExpandErrorArgumentsVA(ExclusiveContext* cx, JSErrorCallback callback,
}
if (efs) {
reportp->exnType = efs->exnType;
SetExnType(reportp, efs->exnType);
MOZ_ASSERT_IF(argumentsType == ArgumentsAreASCII, JS::StringIsASCII(efs->format));
@ -669,6 +736,28 @@ js::ExpandErrorArgumentsVA(ExclusiveContext* cx, JSErrorCallback callback,
return true;
}
bool
js::ExpandErrorArgumentsVA(ExclusiveContext* cx, JSErrorCallback callback,
void* userRef, const unsigned errorNumber,
const char16_t** messageArgs,
ErrorArgumentsType argumentsType,
JSErrorReport* reportp, va_list ap)
{
return ExpandErrorArgumentsHelper(cx, callback, userRef, errorNumber,
messageArgs, argumentsType, reportp, ap);
}
bool
js::ExpandErrorArgumentsVA(ExclusiveContext* cx, JSErrorCallback callback,
void* userRef, const unsigned errorNumber,
const char16_t** messageArgs,
ErrorArgumentsType argumentsType,
JSErrorNotes::Note* notep, va_list ap)
{
return ExpandErrorArgumentsHelper(cx, callback, userRef, errorNumber,
messageArgs, argumentsType, notep, ap);
}
bool
js::ReportErrorNumberVA(JSContext* cx, unsigned flags, JSErrorCallback callback,
void* userRef, const unsigned errorNumber,
@ -832,6 +921,52 @@ js::ReportValueErrorFlags(JSContext* cx, unsigned flags, const unsigned errorNum
return ok;
}
JSObject*
js::CreateErrorNotesArray(JSContext* cx, JSErrorReport* report)
{
RootedArrayObject notesArray(cx, NewDenseEmptyArray(cx));
if (!notesArray)
return nullptr;
if (!report->notes)
return notesArray;
for (auto&& note : *report->notes) {
RootedPlainObject noteObj(cx, NewBuiltinClassInstance<PlainObject>(cx));
if (!noteObj)
return nullptr;
RootedString messageStr(cx, note->newMessageString(cx));
if (!messageStr)
return nullptr;
RootedValue messageVal(cx, StringValue(messageStr));
if (!DefineProperty(cx, noteObj, cx->names().message, messageVal))
return nullptr;
RootedValue filenameVal(cx);
if (note->filename) {
RootedString filenameStr(cx, NewStringCopyZ<CanGC>(cx, note->filename));
if (!filenameStr)
return nullptr;
filenameVal = StringValue(filenameStr);
}
if (!DefineProperty(cx, noteObj, cx->names().fileName, filenameVal))
return nullptr;
RootedValue linenoVal(cx, Int32Value(note->lineno));
if (!DefineProperty(cx, noteObj, cx->names().lineNumber, linenoVal))
return nullptr;
RootedValue columnVal(cx, Int32Value(note->column));
if (!DefineProperty(cx, noteObj, cx->names().columnNumber, columnVal))
return nullptr;
if (!NewbornArrayPush(cx, notesArray, ObjectValue(*noteObj)))
return nullptr;
}
return notesArray;
}
const JSErrorFormatString js_ErrorFormatString[JSErr_Limit] = {
#define MSG_DEF(name, count, exception, format) \
{ #name, format, count, exception } ,

View File

@ -621,6 +621,13 @@ ExpandErrorArgumentsVA(ExclusiveContext* cx, JSErrorCallback callback,
ErrorArgumentsType argumentsType,
JSErrorReport* reportp, va_list ap);
extern bool
ExpandErrorArgumentsVA(ExclusiveContext* cx, JSErrorCallback callback,
void* userRef, const unsigned errorNumber,
const char16_t** messageArgs,
ErrorArgumentsType argumentsType,
JSErrorNotes::Note* notep, va_list ap);
/* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */
extern void
ReportUsageErrorASCII(JSContext* cx, HandleObject callee, const char* msg);
@ -678,6 +685,9 @@ ReportValueErrorFlags(JSContext* cx, unsigned flags, const unsigned errorNumber,
((void)ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, \
spindex, v, fallback, arg1, arg2))
JSObject*
CreateErrorNotesArray(JSContext* cx, JSErrorReport* report);
} /* namespace js */
extern const JSErrorFormatString js_ErrorFormatString[JSErr_Limit];

View File

@ -201,28 +201,77 @@ ErrorObject::classes[JSEXN_ERROR_LIMIT] = {
IMPLEMENT_ERROR_CLASS(RuntimeError)
};
JSErrorReport*
js::CopyErrorReport(JSContext* cx, JSErrorReport* report)
size_t
ExtraMallocSize(JSErrorReport* report)
{
if (report->linebuf())
return (report->linebufLength() + 1) * sizeof(char16_t);
return 0;
}
size_t
ExtraMallocSize(JSErrorNotes::Note* note)
{
return 0;
}
bool
CopyExtraData(JSContext* cx, uint8_t** cursor, JSErrorReport* copy, JSErrorReport* report)
{
if (report->linebuf()) {
size_t linebufSize = (report->linebufLength() + 1) * sizeof(char16_t);
const char16_t* linebufCopy = (const char16_t*)(*cursor);
js_memcpy(*cursor, report->linebuf(), linebufSize);
*cursor += linebufSize;
copy->initBorrowedLinebuf(linebufCopy, report->linebufLength(), report->tokenOffset());
}
/* Copy non-pointer members. */
copy->isMuted = report->isMuted;
copy->exnType = report->exnType;
/* Note that this is before it gets flagged with JSREPORT_EXCEPTION */
copy->flags = report->flags;
/* Deep copy notes. */
if (report->notes) {
auto copiedNotes = report->notes->copy(cx);
if (!copiedNotes)
return false;
copy->notes = Move(copiedNotes);
} else {
copy->notes.reset(nullptr);
}
return true;
}
bool
CopyExtraData(JSContext* cx, uint8_t** cursor, JSErrorNotes::Note* copy, JSErrorNotes::Note* report)
{
return true;
}
template <typename T>
static T*
CopyErrorHelper(JSContext* cx, T* report)
{
/*
* We use a single malloc block to make a deep copy of JSErrorReport with
* We use a single malloc block to make a deep copy of JSErrorReport or
* JSErrorNotes::Note, except JSErrorNotes linked from JSErrorReport with
* the following layout:
* JSErrorReport
* JSErrorReport or JSErrorNotes::Note
* char array with characters for message_
* char16_t array with characters for linebuf
* char array with characters for filename
* char16_t array with characters for linebuf (only for JSErrorReport)
* Such layout together with the properties enforced by the following
* asserts does not need any extra alignment padding.
*/
JS_STATIC_ASSERT(sizeof(JSErrorReport) % sizeof(const char*) == 0);
JS_STATIC_ASSERT(sizeof(T) % sizeof(const char*) == 0);
JS_STATIC_ASSERT(sizeof(const char*) % sizeof(char16_t) == 0);
#define JS_CHARS_SIZE(chars) ((js_strlen(chars) + 1) * sizeof(char16_t))
size_t filenameSize = report->filename ? strlen(report->filename) + 1 : 0;
size_t linebufSize = 0;
if (report->linebuf())
linebufSize = (report->linebufLength() + 1) * sizeof(char16_t);
size_t messageSize = 0;
if (report->message())
messageSize = strlen(report->message().c_str()) + 1;
@ -231,13 +280,13 @@ js::CopyErrorReport(JSContext* cx, JSErrorReport* report)
* The mallocSize can not overflow since it represents the sum of the
* sizes of already allocated objects.
*/
size_t mallocSize = sizeof(JSErrorReport) + messageSize + linebufSize + filenameSize;
size_t mallocSize = sizeof(T) + messageSize + filenameSize + ExtraMallocSize(report);
uint8_t* cursor = cx->pod_calloc<uint8_t>(mallocSize);
if (!cursor)
return nullptr;
JSErrorReport* copy = (JSErrorReport*)cursor;
cursor += sizeof(JSErrorReport);
T* copy = new (cursor) T();
cursor += sizeof(T);
if (report->message()) {
copy->initBorrowedMessage((const char*)cursor);
@ -245,33 +294,40 @@ js::CopyErrorReport(JSContext* cx, JSErrorReport* report)
cursor += messageSize;
}
if (report->linebuf()) {
const char16_t* linebufCopy = (const char16_t*)cursor;
js_memcpy(cursor, report->linebuf(), linebufSize);
cursor += linebufSize;
copy->initBorrowedLinebuf(linebufCopy, report->linebufLength(), report->tokenOffset());
}
if (report->filename) {
copy->filename = (const char*)cursor;
js_memcpy(cursor, report->filename, filenameSize);
cursor += filenameSize;
}
MOZ_ASSERT(cursor + filenameSize == (uint8_t*)copy + mallocSize);
if (!CopyExtraData(cx, &cursor, copy, report)) {
/* js_delete calls destructor for T and js_free for pod_calloc. */
js_delete(copy);
return nullptr;
}
MOZ_ASSERT(cursor == (uint8_t*)copy + mallocSize);
/* Copy non-pointer members. */
copy->isMuted = report->isMuted;
copy->lineno = report->lineno;
copy->column = report->column;
copy->errorNumber = report->errorNumber;
copy->exnType = report->exnType;
/* Note that this is before it gets flagged with JSREPORT_EXCEPTION */
copy->flags = report->flags;
#undef JS_CHARS_SIZE
return copy;
}
JSErrorNotes::Note*
js::CopyErrorNote(JSContext* cx, JSErrorNotes::Note* note)
{
return CopyErrorHelper(cx, note);
}
JSErrorReport*
js::CopyErrorReport(JSContext* cx, JSErrorReport* report)
{
return CopyErrorHelper(cx, report);
}
struct SuppressErrorsGuard
{
JSContext* cx;
@ -322,7 +378,7 @@ exn_finalize(FreeOp* fop, JSObject* obj)
{
MOZ_ASSERT(fop->maybeOffMainThread());
if (JSErrorReport* report = obj->as<ErrorObject>().getErrorReport())
fop->free_(report);
fop->delete_(report);
}
JSErrorReport*
@ -589,6 +645,7 @@ js::ErrorToException(JSContext* cx, JSErrorReport* reportp,
const JSErrorFormatString* errorString = callback(userRef, errorNumber);
JSExnType exnType = errorString ? static_cast<JSExnType>(errorString->exnType) : JSEXN_ERR;
MOZ_ASSERT(exnType < JSEXN_LIMIT);
MOZ_ASSERT(exnType != JSEXN_NOTE);
if (exnType == JSEXN_WARN) {
// werror must be enabled, so we use JSEXN_ERR.
@ -672,7 +729,7 @@ ErrorReportToString(JSContext* cx, JSErrorReport* reportp)
*/
JSExnType type = static_cast<JSExnType>(reportp->exnType);
RootedString str(cx);
if (type != JSEXN_WARN)
if (type != JSEXN_WARN && type != JSEXN_NOTE)
str = ClassName(GetExceptionProtoKey(type), cx);
/*

View File

@ -18,6 +18,9 @@
namespace js {
class ErrorObject;
JSErrorNotes::Note*
CopyErrorNote(JSContext* cx, JSErrorNotes::Note* note);
JSErrorReport*
CopyErrorReport(JSContext* cx, JSErrorReport* report);
@ -67,7 +70,8 @@ static_assert(JSEXN_ERR == 0 &&
JSProto_Error + JSEXN_WASMCOMPILEERROR == JSProto_CompileError &&
JSProto_Error + JSEXN_WASMRUNTIMEERROR == JSProto_RuntimeError &&
JSEXN_WASMRUNTIMEERROR + 1 == JSEXN_WARN &&
JSEXN_WARN + 1 == JSEXN_LIMIT,
JSEXN_WARN + 1 == JSEXN_NOTE &&
JSEXN_NOTE + 1 == JSEXN_LIMIT,
"GetExceptionProtoKey and ExnTypeFromProtoKey require that "
"each corresponding JSExnType and JSProtoKey value be separated "
"by the same constant value");

View File

@ -6419,6 +6419,14 @@ CreateLastWarningObject(JSContext* cx, JSErrorReport* report)
if (!DefineProperty(cx, warningObj, cx->names().columnNumber, columnVal))
return false;
RootedObject notesArray(cx, CreateErrorNotesArray(cx, report));
if (!notesArray)
return false;
RootedValue notesArrayVal(cx, ObjectValue(*notesArray));
if (!DefineProperty(cx, warningObj, cx->names().notes, notesArrayVal))
return false;
GetShellContext(cx)->lastWarning.setObject(*warningObj);
return true;
}

View File

@ -217,6 +217,7 @@
macro(noFilename, noFilename, "noFilename") \
macro(nonincrementalReason, nonincrementalReason, "nonincrementalReason") \
macro(noStack, noStack, "noStack") \
macro(notes, notes, "notes") \
macro(NumberFormat, NumberFormat, "NumberFormat") \
macro(NumberFormatFormatGet, NumberFormatFormatGet, "Intl_NumberFormat_format_get") \
macro(numeric, numeric, "numeric") \

View File

@ -8665,6 +8665,14 @@ DebuggerObject::errorMessageNameGetter(JSContext *cx, unsigned argc, Value* vp)
return true;
}
/* static */ bool
DebuggerObject::errorNotesGetter(JSContext *cx, unsigned argc, Value* vp)
{
THIS_DEBUGOBJECT(cx, argc, vp, "get errorNotes", args, object)
return DebuggerObject::getErrorNotes(cx, object, args.rval());
}
/* static */ bool
DebuggerObject::errorLineNumberGetter(JSContext *cx, unsigned argc, Value* vp)
{
@ -9324,6 +9332,7 @@ const JSPropertySpec DebuggerObject::properties_[] = {
JS_PSG("global", DebuggerObject::globalGetter, 0),
JS_PSG("allocationSite", DebuggerObject::allocationSiteGetter, 0),
JS_PSG("errorMessageName", DebuggerObject::errorMessageNameGetter, 0),
JS_PSG("errorNotes", DebuggerObject::errorNotesGetter, 0),
JS_PSG("errorLineNumber", DebuggerObject::errorLineNumberGetter, 0),
JS_PSG("errorColumnNumber", DebuggerObject::errorColumnNumberGetter, 0),
JS_PSG("isProxy", DebuggerObject::isProxyGetter, 0),
@ -9694,6 +9703,30 @@ DebuggerObject::getErrorMessageName(JSContext* cx, HandleDebuggerObject object,
return true;
}
/* static */ bool
DebuggerObject::getErrorNotes(JSContext* cx, HandleDebuggerObject object,
MutableHandleValue result)
{
RootedObject referent(cx, object->referent());
JSErrorReport* report;
if (!getErrorReport(cx, referent, report))
return false;
if (!report) {
result.setUndefined();
return true;
}
RootedObject errorNotesArray(cx, CreateErrorNotesArray(cx, report));
if (!errorNotesArray)
return false;
if (!cx->compartment()->wrap(cx, &errorNotesArray))
return false;
result.setObject(*errorNotesArray);
return true;
}
/* static */ bool
DebuggerObject::getErrorLineNumber(JSContext* cx, HandleDebuggerObject object,
MutableHandleValue result)

View File

@ -1246,6 +1246,8 @@ class DebuggerObject : public NativeObject
MutableHandleObject result);
static MOZ_MUST_USE bool getErrorMessageName(JSContext* cx, HandleDebuggerObject object,
MutableHandleString result);
static MOZ_MUST_USE bool getErrorNotes(JSContext* cx, HandleDebuggerObject object,
MutableHandleValue result);
static MOZ_MUST_USE bool getErrorLineNumber(JSContext* cx, HandleDebuggerObject object,
MutableHandleValue result);
static MOZ_MUST_USE bool getErrorColumnNumber(JSContext* cx, HandleDebuggerObject object,
@ -1371,6 +1373,7 @@ class DebuggerObject : public NativeObject
static MOZ_MUST_USE bool globalGetter(JSContext* cx, unsigned argc, Value* vp);
static MOZ_MUST_USE bool allocationSiteGetter(JSContext* cx, unsigned argc, Value* vp);
static MOZ_MUST_USE bool errorMessageNameGetter(JSContext* cx, unsigned argc, Value* vp);
static MOZ_MUST_USE bool errorNotesGetter(JSContext* cx, unsigned argc, Value* vp);
static MOZ_MUST_USE bool errorLineNumberGetter(JSContext* cx, unsigned argc, Value* vp);
static MOZ_MUST_USE bool errorColumnNumberGetter(JSContext* cx, unsigned argc, Value* vp);
static MOZ_MUST_USE bool isProxyGetter(JSContext* cx, unsigned argc, Value* vp);

View File

@ -171,10 +171,32 @@ nsXPConnect::IsISupportsDescendant(nsIInterfaceInfo* info)
return found;
}
void
xpc::ErrorBase::Init(JSErrorBase* aReport)
{
if (!aReport->filename) {
mFileName.SetIsVoid(true);
} else {
mFileName.AssignWithConversion(aReport->filename);
}
mLineNumber = aReport->lineno;
mColumn = aReport->column;
}
void
xpc::ErrorNote::Init(JSErrorNotes::Note* aNote)
{
xpc::ErrorBase::Init(aNote);
ErrorNoteToMessageString(aNote, mErrorMsg);
}
void
xpc::ErrorReport::Init(JSErrorReport* aReport, const char* aToStringResult,
bool aIsChrome, uint64_t aWindowID)
{
xpc::ErrorBase::Init(aReport);
mCategory = aIsChrome ? NS_LITERAL_CSTRING("chrome javascript")
: NS_LITERAL_CSTRING("content javascript");
mWindowID = aWindowID;
@ -184,12 +206,6 @@ xpc::ErrorReport::Init(JSErrorReport* aReport, const char* aToStringResult,
AppendUTF8toUTF16(aToStringResult, mErrorMsg);
}
if (!aReport->filename) {
mFileName.SetIsVoid(true);
} else {
mFileName.AssignWithConversion(aReport->filename);
}
mSourceLine.Assign(aReport->linebuf(), aReport->linebufLength());
const JSErrorFormatString* efs = js::GetErrorMessage(nullptr, aReport->errorNumber);
@ -199,10 +215,20 @@ xpc::ErrorReport::Init(JSErrorReport* aReport, const char* aToStringResult,
mErrorMsgName.AssignASCII(efs->name);
}
mLineNumber = aReport->lineno;
mColumn = aReport->column;
mFlags = aReport->flags;
mIsMuted = aReport->isMuted;
if (aReport->notes) {
if (!mNotes.SetLength(aReport->notes->length(), fallible)) {
return;
}
size_t i = 0;
for (auto&& note : *aReport->notes) {
mNotes.ElementAt(i).Init(note.get());
i++;
}
}
}
void
@ -227,6 +253,59 @@ xpc::ErrorReport::Init(JSContext* aCx, mozilla::dom::Exception* aException,
static LazyLogModule gJSDiagnostics("JSDiagnostics");
void
xpc::ErrorBase::AppendErrorDetailsTo(nsCString& error)
{
error.Append(NS_LossyConvertUTF16toASCII(mFileName));
error.AppendLiteral(", line ");
error.AppendInt(mLineNumber, 10);
error.AppendLiteral(": ");
error.Append(NS_LossyConvertUTF16toASCII(mErrorMsg));
}
void
xpc::ErrorNote::LogToStderr()
{
if (!nsContentUtils::DOMWindowDumpEnabled()) {
return;
}
nsAutoCString error;
error.AssignLiteral("JavaScript note: ");
AppendErrorDetailsTo(error);
fprintf(stderr, "%s\n", error.get());
fflush(stderr);
}
void
xpc::ErrorReport::LogToStderr()
{
if (!nsContentUtils::DOMWindowDumpEnabled()) {
return;
}
nsAutoCString error;
error.AssignLiteral("JavaScript ");
if (JSREPORT_IS_STRICT(mFlags)) {
error.AppendLiteral("strict ");
}
if (JSREPORT_IS_WARNING(mFlags)) {
error.AppendLiteral("warning: ");
} else {
error.AppendLiteral("error: ");
}
AppendErrorDetailsTo(error);
fprintf(stderr, "%s\n", error.get());
fflush(stderr);
for (size_t i = 0, len = mNotes.Length(); i < len; i++) {
ErrorNote& note = mNotes[i];
note.LogToStderr();
}
}
void
xpc::ErrorReport::LogToConsole()
{
@ -235,25 +314,7 @@ xpc::ErrorReport::LogToConsole()
void
xpc::ErrorReport::LogToConsoleWithStack(JS::HandleObject aStack)
{
// Log to stdout.
if (nsContentUtils::DOMWindowDumpEnabled()) {
nsAutoCString error;
error.AssignLiteral("JavaScript ");
if (JSREPORT_IS_STRICT(mFlags))
error.AppendLiteral("strict ");
if (JSREPORT_IS_WARNING(mFlags))
error.AppendLiteral("warning: ");
else
error.AppendLiteral("error: ");
error.Append(NS_LossyConvertUTF16toASCII(mFileName));
error.AppendLiteral(", line ");
error.AppendInt(mLineNumber, 10);
error.AppendLiteral(": ");
error.Append(NS_LossyConvertUTF16toASCII(mErrorMsg));
fprintf(stderr, "%s\n", error.get());
fflush(stderr);
}
LogToStderr();
MOZ_LOG(gJSDiagnostics,
JSREPORT_IS_WARNING(mFlags) ? LogLevel::Warning : LogLevel::Error,
@ -265,8 +326,9 @@ xpc::ErrorReport::LogToConsoleWithStack(JS::HandleObject aStack)
// mechanisms.
nsCOMPtr<nsIConsoleService> consoleService =
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
NS_ENSURE_TRUE_VOID(consoleService);
nsCOMPtr<nsIScriptError> errorObject;
RefPtr<nsScriptErrorBase> errorObject;
if (mWindowID && aStack) {
// Only set stack on messages related to a document
// As we cache messages in the console service,
@ -277,16 +339,36 @@ xpc::ErrorReport::LogToConsoleWithStack(JS::HandleObject aStack)
errorObject = new nsScriptError();
}
errorObject->SetErrorMessageName(mErrorMsgName);
NS_ENSURE_TRUE_VOID(consoleService);
nsresult rv = errorObject->InitWithWindowID(mErrorMsg, mFileName, mSourceLine,
mLineNumber, mColumn, mFlags,
mCategory, mWindowID);
NS_ENSURE_SUCCESS_VOID(rv);
for (size_t i = 0, len = mNotes.Length(); i < len; i++) {
ErrorNote& note = mNotes[i];
nsScriptErrorNote* noteObject = new nsScriptErrorNote();
noteObject->Init(note.mErrorMsg, note.mFileName,
note.mLineNumber, note.mColumn);
errorObject->AddNote(noteObject);
}
consoleService->LogMessage(errorObject);
}
/* static */
void
xpc::ErrorNote::ErrorNoteToMessageString(JSErrorNotes::Note* aNote,
nsAString& aString)
{
aString.Truncate();
if (aNote->message()) {
aString.Append(NS_ConvertUTF8toUTF16(aNote->message().c_str()));
}
}
/* static */
void
xpc::ErrorReport::ErrorReportToMessageString(JSErrorReport* aReport,

View File

@ -515,13 +515,50 @@ AllowCPOWsInAddon(const nsACString& addonId, bool allow);
bool
ExtraWarningsForSystemJS();
class ErrorReport {
class ErrorBase {
public:
nsString mErrorMsg;
nsString mFileName;
uint32_t mLineNumber;
uint32_t mColumn;
ErrorBase() : mLineNumber(0)
, mColumn(0)
{}
void Init(JSErrorBase* aReport);
void AppendErrorDetailsTo(nsCString& error);
};
class ErrorNote : public ErrorBase {
public:
void Init(JSErrorNotes::Note* aNote);
// Produce an error event message string from the given JSErrorNotes::Note.
// This may produce an empty string if aNote doesn't have a message
// attached.
static void ErrorNoteToMessageString(JSErrorNotes::Note* aNote,
nsAString& aString);
// Log the error note to the stderr.
void LogToStderr();
};
class ErrorReport : public ErrorBase {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ErrorReport);
nsTArray<ErrorNote> mNotes;
nsCString mCategory;
nsString mSourceLine;
nsString mErrorMsgName;
uint64_t mWindowID;
uint32_t mFlags;
bool mIsMuted;
ErrorReport() : mWindowID(0)
, mLineNumber(0)
, mColumn(0)
, mFlags(0)
, mIsMuted(false)
{}
@ -530,6 +567,7 @@ class ErrorReport {
bool aIsChrome, uint64_t aWindowID);
void Init(JSContext* aCx, mozilla::dom::Exception* aException,
bool aIsChrome, uint64_t aWindowID);
// Log the error report to the console. Which console will depend on the
// window id it was initialized with.
void LogToConsole();
@ -544,18 +582,8 @@ class ErrorReport {
static void ErrorReportToMessageString(JSErrorReport* aReport,
nsAString& aString);
public:
nsCString mCategory;
nsString mErrorMsgName;
nsString mErrorMsg;
nsString mFileName;
nsString mSourceLine;
uint64_t mWindowID;
uint32_t mLineNumber;
uint32_t mColumn;
uint32_t mFlags;
bool mIsMuted;
// Log the error report to the stderr.
void LogToStderr();
private:
~ErrorReport() {}