summaryrefslogtreecommitdiffstats
path: root/dom/promise/tests/unit/test_promise_unhandled_rejection.js
blob: 68471569ec438a69a9870a0b14542c4641be94b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
"use strict";

// Tests that unhandled promise rejections generate the appropriate
// console messages.

const { AddonTestUtils } = ChromeUtils.importESModule(
  "resource://testing-common/AddonTestUtils.sys.mjs"
);
const { PromiseTestUtils } = ChromeUtils.importESModule(
  "resource://testing-common/PromiseTestUtils.sys.mjs"
);

PromiseTestUtils.expectUncaughtRejection(/could not be cloned/);
PromiseTestUtils.expectUncaughtRejection(/An exception was thrown/);
PromiseTestUtils.expectUncaughtRejection(/Bleah/);

const filename = "resource://foo/Bar.jsm";

async function getSandboxMessages(sandbox, code) {
  let { messages } = await AddonTestUtils.promiseConsoleOutput(async () => {
    Cu.evalInSandbox(code, sandbox, null, filename, 1);

    // We need two trips through the event loop for this error to be reported.
    await new Promise(executeSoon);
    await new Promise(executeSoon);
  });

  // xpcshell tests on OS-X sometimes include an extra warning, which we
  // unfortunately need to ignore:
  return messages.filter(
    msg =>
      !msg.message.includes(
        "No chrome package registered for chrome://branding/locale/brand.properties"
      )
  );
}

add_task(async function test_unhandled_dom_exception() {
  let sandbox = Cu.Sandbox(Services.scriptSecurityManager.getSystemPrincipal());
  sandbox.StructuredCloneHolder = StructuredCloneHolder;

  let messages = await getSandboxMessages(
    sandbox,
    `new Promise(() => {
      new StructuredCloneHolder("", "", () => {});
    });`
  );

  equal(messages.length, 1, "Got one console message");

  let [msg] = messages;
  ok(msg instanceof Ci.nsIScriptError, "Message is a script error");
  equal(msg.sourceName, filename, "Got expected filename");
  equal(msg.lineNumber, 2, "Got expected line number");
  equal(
    msg.errorMessage,
    "DataCloneError: Function object could not be cloned.",
    "Got expected error message"
  );
});

add_task(async function test_unhandled_dom_exception_wrapped() {
  let sandbox = Cu.Sandbox(
    Services.scriptSecurityManager.createContentPrincipalFromOrigin(
      "http://example.com/"
    )
  );
  Cu.exportFunction(
    function frick() {
      throw new Components.Exception(
        "Bleah.",
        Cr.NS_ERROR_FAILURE,
        Components.stack.caller
      );
    },
    sandbox,
    { defineAs: "frick" }
  );

  let messages = await getSandboxMessages(
    sandbox,
    `new Promise(() => {
      frick();
    });`
  );

  equal(messages.length, 2, "Got two console messages");

  let [msg1, msg2] = messages;
  ok(msg1 instanceof Ci.nsIScriptError, "Message is a script error");
  equal(msg1.sourceName, filename, "Got expected filename");
  equal(msg1.lineNumber, 2, "Got expected line number");
  equal(
    msg1.errorMessage,
    "NS_ERROR_FAILURE: Bleah.",
    "Got expected error message"
  );

  ok(msg2 instanceof Ci.nsIScriptError, "Message is a script error");
  equal(msg2.sourceName, filename, "Got expected filename");
  equal(msg2.lineNumber, 2, "Got expected line number");
  equal(
    msg2.errorMessage,
    "InvalidStateError: An exception was thrown",
    "Got expected error message"
  );
});

add_task(async function test_unhandled_dom_exception_from_sandbox() {
  let sandbox = Cu.Sandbox(
    Services.scriptSecurityManager.createContentPrincipalFromOrigin(
      "http://example.com/"
    ),
    { wantGlobalProperties: ["DOMException"] }
  );
  let ctor = Cu.evalInSandbox("DOMException", sandbox);
  Cu.exportFunction(
    function frick() {
      throw new ctor("Bleah.");
    },
    sandbox,
    { defineAs: "frick" }
  );

  let messages = await getSandboxMessages(
    sandbox,
    `new Promise(() => {
      frick();
    });`
  );

  equal(messages.length, 1, "Got one console messages");

  let [msg] = messages;
  ok(msg instanceof Ci.nsIScriptError, "Message is a script error");
  equal(msg.sourceName, filename, "Got expected filename");
  equal(msg.lineNumber, 2, "Got expected line number");
  equal(msg.errorMessage, "Error: Bleah.", "Got expected error message");
});