Cheerp supports C++ exceptions, enabled when passing ‘-fexceptions’ to the compiler.

Small clarification to start, there is the logic encoded in the C++ side (than will then be codegenerated as a mix of JavaScript and WebAssembly) and ‘external’ logic, either as external JavaScript libraries or anyhow included browser side (= not compiled in the same Cheerp project).

‘Internal’ exception catched by C++ code

#include <iostream>
using namespace std;

int main () {
  try
  {
    throw 20;
  }
  catch (int e)
  {
    cout << "An exception occurred. Exception Nr. " << e << '\n';
  }
  return 0;
}

This works the same regardless of whether code will be codegenerated as JavaScript or WebAssembly, as long as both sides are present on the C++ side it will follow the ‘regular’ rules for C++ exceptions, (eg. catch(…) included). This is the simpler case, you basically do as you would do while compilign natively, and any exceptions-enabled code should work out of the box.

‘External’ exception catched by C++ code

#include <iostream>
#include <cheerp/jsexception.h>
#include <cheerp/clientlib.h>
using namespace std;

namespace client{
    void someUndefinedExternalFunc();
}

int main () {
  try
  {
          client::someUndefinedExternalFunc();
  }
  catch (cheerp::JSException& ex)
  {
          client::Error* error = (client::Error*)ex.get();
          client::console.log(error->get_name());
          client::console.log(error->get_stack());
          client::console.log(error->get_message());
  }
  return 0;
}

Here say that we don’t implement someUndefinedExternalFunc, then executing it will throw a (JavaScript) Error, that can be catched using the cheerp-specific syntax:

catch (cheerp::JSException& ex)

Note that using the throw value requires: calling get() + casting to the appropriate value. Here we casted to a pointer to client::Error), but see for example here: cheerp-utils/tests for catching an integer value.

‘Internal’ (C++) exception catched by external JavaScript code

If your code (eg. a jsexported function) let a C++ exception bubble up, you can still catch it on the JavaScript side by wrapping the call of the relevant jsexported-method in a try {} catch {} statement. This is ‘just’ regular JavaScript.

[[cheerp::jsexport]]
void throwIfOdd(int n)
{
  if (n % 1)
    throw n;
}
try{
  throwIfOdd(3);
}
catch(e){
  console.log("Catched C++ exception ", e);
}

This is expecially useful during development.

Throw builtin

Also possibly useful for testing (and for internal usage) there is a __builtin_cheerp_throw( someObj ) that codegen to the equivalent JavaScript throw.

#include <cheerpintrin.h>
client::Object* obj = new client::Object();

__builtin_cheerp_throw(obj);

Throws via the builtin behave exactly as the object was thrown via the JavaScript throw mechanism (so it will be considered as ‘external’ by the Cheerp compiler).

__asm__ sections can’t throw

This is the very last ‘catch’, there can’t be throws (either directly or indirectly) in __asm__ sections (see asm sections).