| <!DOCTYPE html> |
| <html> |
| <head> |
| <script src="../../http/tests/inspector/resources/inspector-test.js"></script> |
| <script> |
| function typeError() { |
| let object = {}; |
| try { |
| object.propertyDoesnt.exist; |
| } catch (e) { |
| console.trace(); |
| return e.stack; |
| } |
| } |
| |
| function triggerTypeError() { |
| return typeError(); |
| } |
| |
| function triggerTypeErrorWithNativeCallInBetween() { |
| return [42].map(typeError)[0]; |
| } |
| |
| let _anonymousFunctionError = null; |
| |
| (function() { |
| let object = {}; |
| try { |
| object.methodDoesntExist(); |
| } catch (e) { |
| _anonymousFunctionError = e.stack; |
| } |
| })(); |
| |
| function getAnonymousFunctionError() { |
| return _anonymousFunctionError; |
| } |
| |
| function* generator1() { |
| yield* generator2(); |
| } |
| |
| function* generator2() { |
| yield typeError(); |
| } |
| |
| function triggerGeneratorError() { |
| return generator1().next().value; |
| } |
| |
| function test() |
| { |
| function stripFilePaths(stackTrace) { |
| for (let frame of stackTrace) { |
| if (typeof frame.url === "string") |
| frame.url = frame.url.replace(/^.+?LayoutTests/, ""); |
| } |
| return stackTrace; |
| } |
| |
| function stripCallFramesAfterEval(stackTrace) { |
| for (let i = 0; i < stackTrace.length; ++i) { |
| let frame = stackTrace[i]; |
| if (frame.programCode) |
| return stackTrace.slice(0, i + 1); |
| } |
| return stackTrace; |
| } |
| |
| function stripPayloadAfterGlobalCode(stackTrace) { |
| for (let i = 0; i < stackTrace.length; ++i) { |
| let frame = stackTrace[i]; |
| if (frame.functionName === "global code") |
| return stackTrace.slice(0, i + 1); |
| } |
| return stackTrace; |
| } |
| |
| WI.consoleManager.addEventListener(WI.ConsoleManager.Event.MessageAdded, (event) => { |
| InspectorTest.log("\nconsole.trace():"); |
| |
| let stackTrace = []; |
| let callFramesBeforeEval = stripCallFramesAfterEval(event.data.message.stackTrace.callFrames); |
| for (let callFrame of callFramesBeforeEval) { |
| let lineNumber = callFrame.sourceCodeLocation ? callFrame.sourceCodeLocation.lineNumber : null; |
| let columnNumber = callFrame.sourceCodeLocation ? callFrame.sourceCodeLocation.columnNumber : null; |
| stackTrace.push({ |
| lineNumber: lineNumber, |
| columnNumber: columnNumber, |
| functionName: callFrame.functionName, |
| nativeCode: callFrame.nativeCode, |
| programCode: callFrame.programCode, |
| }); |
| } |
| |
| InspectorTest.log(JSON.stringify(stackTrace, null, 4)); |
| }); |
| |
| |
| let suite = InspectorTest.createAsyncSuite("ConsoleTraceAndJavaScriptStackTrace"); |
| |
| function addTestCase({name, expression}) { |
| suite.addTestCase({ |
| name, |
| test(resolve, reject) { |
| InspectorTest.evaluateInPage(expression, (error, result) => { |
| InspectorTest.assert(!error, error); |
| InspectorTest.log("\nError object:"); |
| let stackTrace = stripFilePaths(stripPayloadAfterGlobalCode(WI.StackTrace._parseStackTrace(result))); |
| InspectorTest.log(JSON.stringify(stackTrace, null, 4)); |
| resolve(); |
| }); |
| } |
| }); |
| } |
| |
| addTestCase({ |
| name: "ConsoleTraceAndJavaScriptStackTrace.BasicError", |
| expression: "triggerTypeError()", |
| }); |
| |
| addTestCase({ |
| name: "ConsoleTraceAndJavaScriptStackTrace.ErrorInNativeCall", |
| expression: "triggerTypeErrorWithNativeCallInBetween()", |
| }); |
| |
| addTestCase({ |
| name: "ConsoleTraceAndJavaScriptStackTrace.ErrorInAnonymousFunction", |
| expression: "getAnonymousFunctionError()", |
| }); |
| |
| addTestCase({ |
| name: "ConsoleTraceAndJavaScriptStackTrace.ErrorInGenerator", |
| expression: "triggerGeneratorError()", |
| }); |
| |
| suite.runTestCasesAndFinish(); |
| } |
| </script> |
| </head> |
| <body onload="runTest()"> |
| <p>Tests that we can parse the stack trace format used by JavaScriptCore and the contents of Error / console.trace stack traces.</p> |
| </body> |
| </html> |