test_getCallerLocation.js (2687B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 "use strict"; 5 6 Cu.importGlobalProperties(["ChromeUtils"]); 7 8 const {AddonTestUtils} = ChromeUtils.importESModule("resource://testing-common/AddonTestUtils.sys.mjs"); 9 10 add_task(async function() { 11 const sandbox = Cu.Sandbox("http://example.com/"); 12 13 function foo() { 14 return bar(); 15 } 16 17 function bar() { 18 return baz(); 19 } 20 21 function baz() { 22 return ChromeUtils.getCallerLocation(Cu.getObjectPrincipal(sandbox)); 23 } 24 25 Cu.evalInSandbox(` 26 function it() { 27 // Use map() to throw a self-hosted frame on the stack, which we 28 // should filter out. 29 return [0].map(foo)[0]; 30 } 31 function thing() { 32 return it(); 33 } 34 `, sandbox, undefined, "thing.js"); 35 36 Cu.exportFunction(foo, sandbox, {defineAs: "foo"}); 37 38 let frame = sandbox.thing(); 39 40 equal(frame.source, "thing.js", "Frame source"); 41 equal(frame.line, 5, "Frame line"); 42 equal(frame.column, 18, "Frame column"); 43 equal(frame.functionDisplayName, "it", "Frame function name"); 44 equal(frame.parent, null, "Frame parent"); 45 46 equal(String(frame), "it@thing.js:5:18\n", "Stringified frame"); 47 48 49 // reportError 50 51 let {messages} = await AddonTestUtils.promiseConsoleOutput(() => { 52 Cu.reportError("Meh", frame); 53 }); 54 55 let [msg] = messages.filter(m => m.message.includes("Meh")); 56 57 equal(msg.stack, frame, "reportError stack frame"); 58 equal(msg.message, '[JavaScript Error: "Meh" {file: "thing.js" line: 5}]\nit@thing.js:5:18\n'); 59 60 Assert.throws(() => { Cu.reportError("Meh", {}); }, 61 err => err.result == Cr.NS_ERROR_INVALID_ARG, 62 "reportError should throw when passed a non-SavedFrame object"); 63 64 65 // createError 66 67 Assert.throws(() => { ChromeUtils.createError("Meh", {}); }, 68 err => err.result == Cr.NS_ERROR_INVALID_ARG, 69 "createError should throw when passed a non-SavedFrame object"); 70 71 let cloned = Cu.cloneInto(frame, sandbox); 72 let error = ChromeUtils.createError("Meh", cloned); 73 74 equal(String(cloned), String(frame), 75 "Cloning a SavedStack preserves its stringification"); 76 77 equal(Cu.getGlobalForObject(error), sandbox, 78 "createError creates errors in the global of the SavedFrame"); 79 equal(error.stack, String(cloned), 80 "createError creates errors with the correct stack"); 81 82 equal(error.message, "Meh", "Error message"); 83 equal(error.fileName, "thing.js", "Error filename"); 84 equal(error.lineNumber, 5, "Error line"); 85 equal(error.columnNumber, 18, "Error column"); 86 });