11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci// Flags: --expose-gc
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_ciconst common = require('../../common');
51cb0ef41Sopenharmony_ciconst assert = require('assert');
61cb0ef41Sopenharmony_ciconst theError = new Error('Some error');
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci// The test module throws an error during Init, but in order for its exports to
91cb0ef41Sopenharmony_ci// not be lost, it attaches them to the error's "bindings" property. This way,
101cb0ef41Sopenharmony_ci// we can make sure that exceptions thrown during the module initialization
111cb0ef41Sopenharmony_ci// phase are propagated through require() into JavaScript.
121cb0ef41Sopenharmony_ci// https://github.com/nodejs/node/issues/19437
131cb0ef41Sopenharmony_ciconst test_exception = (function() {
141cb0ef41Sopenharmony_ci  let resultingException;
151cb0ef41Sopenharmony_ci  try {
161cb0ef41Sopenharmony_ci    require(`./build/${common.buildType}/test_exception`);
171cb0ef41Sopenharmony_ci  } catch (anException) {
181cb0ef41Sopenharmony_ci    resultingException = anException;
191cb0ef41Sopenharmony_ci  }
201cb0ef41Sopenharmony_ci  assert.strictEqual(resultingException.message, 'Error during Init');
211cb0ef41Sopenharmony_ci  return resultingException.binding;
221cb0ef41Sopenharmony_ci})();
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci{
251cb0ef41Sopenharmony_ci  const throwTheError = () => { throw theError; };
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci  // Test that the native side successfully captures the exception
281cb0ef41Sopenharmony_ci  let returnedError = test_exception.returnException(throwTheError);
291cb0ef41Sopenharmony_ci  assert.strictEqual(returnedError, theError);
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci  // Test that the native side passes the exception through
321cb0ef41Sopenharmony_ci  assert.throws(
331cb0ef41Sopenharmony_ci    () => { test_exception.allowException(throwTheError); },
341cb0ef41Sopenharmony_ci    (err) => err === theError,
351cb0ef41Sopenharmony_ci  );
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci  // Test that the exception thrown above was marked as pending
381cb0ef41Sopenharmony_ci  // before it was handled on the JS side
391cb0ef41Sopenharmony_ci  const exception_pending = test_exception.wasPending();
401cb0ef41Sopenharmony_ci  assert.strictEqual(exception_pending, true,
411cb0ef41Sopenharmony_ci                     'Exception not pending as expected,' +
421cb0ef41Sopenharmony_ci                     ` .wasPending() returned ${exception_pending}`);
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci  // Test that the native side does not capture a non-existing exception
451cb0ef41Sopenharmony_ci  returnedError = test_exception.returnException(common.mustCall());
461cb0ef41Sopenharmony_ci  assert.strictEqual(returnedError, undefined,
471cb0ef41Sopenharmony_ci                     'Returned error should be undefined when no exception is' +
481cb0ef41Sopenharmony_ci                     ` thrown, but ${returnedError} was passed`);
491cb0ef41Sopenharmony_ci}
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci{
531cb0ef41Sopenharmony_ci  const throwTheError = class { constructor() { throw theError; } };
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci  // Test that the native side successfully captures the exception
561cb0ef41Sopenharmony_ci  let returnedError = test_exception.constructReturnException(throwTheError);
571cb0ef41Sopenharmony_ci  assert.strictEqual(returnedError, theError);
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  // Test that the native side passes the exception through
601cb0ef41Sopenharmony_ci  assert.throws(
611cb0ef41Sopenharmony_ci    () => { test_exception.constructAllowException(throwTheError); },
621cb0ef41Sopenharmony_ci    (err) => err === theError,
631cb0ef41Sopenharmony_ci  );
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci  // Test that the exception thrown above was marked as pending
661cb0ef41Sopenharmony_ci  // before it was handled on the JS side
671cb0ef41Sopenharmony_ci  const exception_pending = test_exception.wasPending();
681cb0ef41Sopenharmony_ci  assert.strictEqual(exception_pending, true,
691cb0ef41Sopenharmony_ci                     'Exception not pending as expected,' +
701cb0ef41Sopenharmony_ci                     ` .wasPending() returned ${exception_pending}`);
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci  // Test that the native side does not capture a non-existing exception
731cb0ef41Sopenharmony_ci  returnedError = test_exception.constructReturnException(common.mustCall());
741cb0ef41Sopenharmony_ci  assert.strictEqual(returnedError, undefined,
751cb0ef41Sopenharmony_ci                     'Returned error should be undefined when no exception is' +
761cb0ef41Sopenharmony_ci                     ` thrown, but ${returnedError} was passed`);
771cb0ef41Sopenharmony_ci}
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci{
801cb0ef41Sopenharmony_ci  // Test that no exception appears that was not thrown by us
811cb0ef41Sopenharmony_ci  let caughtError;
821cb0ef41Sopenharmony_ci  try {
831cb0ef41Sopenharmony_ci    test_exception.allowException(common.mustCall());
841cb0ef41Sopenharmony_ci  } catch (anError) {
851cb0ef41Sopenharmony_ci    caughtError = anError;
861cb0ef41Sopenharmony_ci  }
871cb0ef41Sopenharmony_ci  assert.strictEqual(caughtError, undefined,
881cb0ef41Sopenharmony_ci                     'No exception originated on the native side, but' +
891cb0ef41Sopenharmony_ci                     ` ${caughtError} was passed`);
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  // Test that the exception state remains clear when no exception is thrown
921cb0ef41Sopenharmony_ci  const exception_pending = test_exception.wasPending();
931cb0ef41Sopenharmony_ci  assert.strictEqual(exception_pending, false,
941cb0ef41Sopenharmony_ci                     'Exception state did not remain clear as expected,' +
951cb0ef41Sopenharmony_ci                     ` .wasPending() returned ${exception_pending}`);
961cb0ef41Sopenharmony_ci}
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci{
991cb0ef41Sopenharmony_ci  // Test that no exception appears that was not thrown by us
1001cb0ef41Sopenharmony_ci  let caughtError;
1011cb0ef41Sopenharmony_ci  try {
1021cb0ef41Sopenharmony_ci    test_exception.constructAllowException(common.mustCall());
1031cb0ef41Sopenharmony_ci  } catch (anError) {
1041cb0ef41Sopenharmony_ci    caughtError = anError;
1051cb0ef41Sopenharmony_ci  }
1061cb0ef41Sopenharmony_ci  assert.strictEqual(caughtError, undefined,
1071cb0ef41Sopenharmony_ci                     'No exception originated on the native side, but' +
1081cb0ef41Sopenharmony_ci                     ` ${caughtError} was passed`);
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci  // Test that the exception state remains clear when no exception is thrown
1111cb0ef41Sopenharmony_ci  const exception_pending = test_exception.wasPending();
1121cb0ef41Sopenharmony_ci  assert.strictEqual(exception_pending, false,
1131cb0ef41Sopenharmony_ci                     'Exception state did not remain clear as expected,' +
1141cb0ef41Sopenharmony_ci                     ` .wasPending() returned ${exception_pending}`);
1151cb0ef41Sopenharmony_ci}
116