async-debug-caught-exception-cases.js 5.2 KB
Newer Older
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
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

Debug = debug.Debug

let events = 0;

function listener(event, exec_state, event_data, data) {
  if (event != Debug.DebugEvent.Exception) return;
  events++;
}

async function thrower() {
  throw "a";  // Exception a
}

var reject = () => Promise.reject("b");  // Exception b

async function awaitReturn() { await 1; return; }

async function scalar() { return 1; }

function nothing() { return 1; }

function rejectConstructor() {
  return new Promise((resolve, reject) => reject("c"));  // Exception c
}

async function argThrower(x = (() => { throw "d"; })()) { }  // Exception d

32 33 34 35 36 37 38 39 40 41 42 43 44
async function awaitThrow() {
  await undefined;
  throw "e";  // Exception e
}

function constructorThrow() {
  return new Promise((resolve, reject) =>
    Promise.resolve().then(() =>
      reject("f")  // Exception f
    )
  );
}

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
function suppressThrow() {
  return thrower();
}

async function caught(producer) {
  try {
    await producer();
  } catch (e) {
  }
}

async function uncaught(producer) {
  await producer();
}

async function indirectUncaught(producer) {
  await uncaught(producer);
}

async function indirectCaught(producer) {
  try {
    await uncaught(producer);
  } catch (e) {
  }
}

function dotCatch(producer) {
  Promise.resolve(producer()).catch(() => {});
}

function indirectReturnDotCatch(producer) {
  (async() => producer())().catch(() => {});
}

function indirectAwaitDotCatch(producer) {
  (async() => await producer())().catch(() => {});
}

function nestedDotCatch(producer) {
  Promise.resolve(producer()).then().catch(() => {});
}

async function indirectAwaitCatch(producer) {
  try {
    await (() => producer())();
  } catch (e) {
  }
}

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
function switchCatch(producer) {
  let resolve;
  let promise = new Promise(r => resolve = r);
  async function localCaught() {
    try {
      await promise;  // force switching to localUncaught and back
      await producer();
    } catch (e) { }
  }
  async function localUncaught() {
    await undefined;
    resolve();
  }
  localCaught();
  localUncaught();
}

function switchDotCatch(producer) {
  let resolve;
  let promise = new Promise(r => resolve = r);
  async function localCaught() {
    await promise;  // force switching to localUncaught and back
    await producer();
  }
  async function localUncaught() {
    await undefined;
    resolve();
  }
  localCaught().catch(() => {});
  localUncaught();
}

let catches = [caught,
               indirectCaught,
               indirectAwaitCatch,
               switchCatch,
               switchDotCatch];
131 132 133 134 135 136 137 138
let noncatches = [uncaught, indirectUncaught];
let lateCatches = [dotCatch,
                   indirectReturnDotCatch,
                   indirectAwaitDotCatch,
                   nestedDotCatch];

let throws = [thrower, reject, argThrower, suppressThrow];
let nonthrows = [awaitReturn, scalar, nothing];
139
let lateThrows = [awaitThrow, constructorThrow];
140 141 142 143
let uncatchable = [rejectConstructor];

let cases = [];

144
for (let producer of throws.concat(lateThrows)) {
145 146 147 148 149 150
  for (let consumer of catches) {
    cases.push({ producer, consumer, expectedEvents: 1, caught: true });
    cases.push({ producer, consumer, expectedEvents: 0, caught: false });
  }
}

151
for (let producer of throws.concat(lateThrows)) {
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
  for (let consumer of noncatches) {
    cases.push({ producer, consumer, expectedEvents: 1, caught: true });
    cases.push({ producer, consumer, expectedEvents: 1, caught: false });
  }
}

for (let producer of nonthrows) {
  for (let consumer of catches.concat(noncatches, lateCatches)) {
    cases.push({ producer, consumer, expectedEvents: 0, caught: true });
    cases.push({ producer, consumer, expectedEvents: 0, caught: false });
  }
}

for (let producer of uncatchable) {
  for (let consumer of catches.concat(noncatches, lateCatches)) {
    cases.push({ producer, consumer, expectedEvents: 1, caught: true });
    cases.push({ producer, consumer, expectedEvents: 1, caught: false });
  }
}

172
for (let producer of lateThrows) {
173 174
  for (let consumer of lateCatches) {
    cases.push({ producer, consumer, expectedEvents: 1, caught: true });
175
    cases.push({ producer, consumer, expectedEvents: 0, caught: false });
176 177 178
  }
}

179 180 181 182
for (let producer of throws) {
  for (let consumer of lateCatches) {
    cases.push({ producer, consumer, expectedEvents: 1, caught: true });
    cases.push({ producer, consumer, expectedEvents: 1, caught: false });
183
  }
184
}
185 186


187 188 189 190 191 192 193 194 195 196 197 198 199
function runPart(n) {
  let subcases = cases.slice(n * cases.length / 4,
                             ((n + 1) * cases.length) / 4);
  for (let {producer, consumer, expectedEvents, caught} of subcases) {
    Debug.setListener(listener);
    if (caught) {
      Debug.setBreakOnException();
    } else {
      Debug.setBreakOnUncaughtException();
    }

    events = 0;
    consumer(producer);
200
    %PerformMicrotaskCheckpoint();
201 202 203 204 205 206 207 208

    Debug.setListener(null);
    if (caught) {
      Debug.clearBreakOnException();
    } else {
      Debug.clearBreakOnUncaughtException();
    }
    if (expectedEvents != events) {
209 210
      %AbortJS(`producer ${producer} consumer ${consumer} expectedEvents ` +
               `${expectedEvents} caught ${caught} events ${events}`);
211
    }
212 213
  }
}