<!-- Thank you for contributing to Pyodide! All improvements are welcome,
     so don't be afraid to make a PR. -->

<!-- [IMPORTANT] Note on CI failures:
     Currently, we are having issues with selenium-based tests.
     Don't panic if the CI fails on your PR because of timeouts.
     It's probably not your fault. We will investigate :) -->

### Description

<!-- Please explain what your PR is about:
     - reasoning for the change
     - some details of updated code
     - any noteworthy choices to be aware of
	Please refer to any related issues by #<issue_id> -->

Bumping MPL version - it turns out that Hist (which uses boost-histogram) depends on mplhep, which in turn requires matplotlib 3.4+. So I migrated the patches and bumped MPL.

I noticed micropip doesn't seem to respect extras, that is, `await micropip.install("hist[plot]")` doesn't seem to work. (will investigate later)

* Updated matplotlib to 3.5
    * Added fonttools
* Updated yt to 4
    * Added `cmyt` and `unyt`, which I am pretty sure are yt specific. At least by looking at the name. 😆 
    * Also `colorspacious`
    * Also `tdqm`
    * Also `tomli` and `tomli-w` (backported from the next yt release to avoid adding a dead dependency `toml`)

Closes #2088 too. Also 3.5 was the first version to officially support 3.10, I think.
chore: matplotlib 3.5.1, yt 4. <!-- Thank you for contributing to Pyodide! All improvements are welcome,
     so don't be afraid to make a PR. -->

<!-- [IMPORTANT] Note on CI failures:
     Currently, we are having issues with selenium-based tests.
     Don't panic if the CI fails on your PR because of timeouts.
     It's probably not your fault. We will investigate :) -->

### Description

<!-- Please explain what your PR is about:
     - reasoning for the change
     - some details of updated code
     - any noteworthy choices to be aware of
	Please refer to any related issues by #<issue_id> -->

Bumping MPL version - it turns out that Hist (which uses boost-histogram) depends on mplhep, which in turn requires matplotlib 3.4+. So I migrated the patches and bumped MPL.

I noticed micropip doesn't seem to respect extras, that is, `await micropip.install("hist[plot]")` doesn't seem to work. (will investigate later)

* Updated matplotlib to 3.5
    * Added fonttools
* Updated yt to 4
    * Added `cmyt` and `unyt`, which I am pretty sure are yt specific. At least by looking at the name. 😆 
    * Also `colorspacious`
    * Also `tdqm`
    * Also `tomli` and `tomli-w` (backported from the next yt release to avoid adding a dead dependency `toml`)

Closes #2088 too. Also 3.5 was the first version to officially support 3.10, I think.
from pyodide_build.testing import PYVERSION


def test_uncaught_cpp_exceptions(selenium):
    assert (
        selenium.run_js(
            f"""
            await pyodide.loadPackage("cpp-exceptions-test");
            const Tests = pyodide._api.tests;
            const idx = pyodide._module.LDSO.loadedLibNames["/lib/{PYVERSION}/site-packages/cpp-exceptions-test-throw.so"]
            const throwlib = pyodide._module.LDSO.loadedLibs[idx].module;
            """
            """\
            function t(x){
                try {
                    throwlib.throw_exc(x);
                } catch(e){
                    let errString = Tests.convertCppException(e).toString();
                    errString = errString.replace(/[0-9]+/, "xxx");
                    return errString;
                }
            }
            return [t(1), t(2), t(3), t(4), t(5)];
            """
        )
        == [
            "CppException int: The exception is an object of type int at address xxx "
            "which does not inherit from std::exception",
            "CppException char: The exception is an object of type char at address xxx "
            "which does not inherit from std::exception",
            "CppException std::runtime_error: abc",
            "CppException myexception: My exception happened",
            "CppException char const*: The exception is an object of type char const* at "
            "address xxx which does not inherit from std::exception",
        ]
    )


def test_cpp_exception_catching(selenium):
    assert (
        selenium.run_js(
            f"""
            await pyodide.loadPackage("cpp-exceptions-test");
            const Module = pyodide._module;
            const idx = Module.LDSO.loadedLibNames["/lib/{PYVERSION}/site-packages/cpp-exceptions-test-catch.so"]
            const catchlib = Module.LDSO.loadedLibs[idx].module;
            """
            """\
            function t(x){
                const ptr = catchlib.catch_exc(x);
                const res = Module.UTF8ToString(ptr);
                Module._free(ptr);
                return res;
            }

            return [t(1), t(2), t(3), t(5)];
            """
        )
        == [
            "caught int 1000",
            "caught char 99",
            "caught runtime_error abc",
            "caught ????",
        ]
    )

from pyodide_build.testing import PYVERSION


def test_uncaught_cpp_exceptions(selenium):
    assert (
        selenium.run_js(
            f"""
            await pyodide.loadPackage("cpp-exceptions-test");
            const Tests = pyodide._api.tests;
            const idx = pyodide._module.LDSO.loadedLibNames["/lib/{PYVERSION}/site-packages/cpp-exceptions-test-throw.so"]
            const throwlib = pyodide._module.LDSO.loadedLibs[idx].module;
            """
            """\
            function t(x){
                try {
                    throwlib.throw_exc(x);
                } catch(e){
                    let errString = Tests.convertCppException(e).toString();
                    errString = errString.replace(/[0-9]+/, "xxx");
                    return errString;
                }
            }
            return [t(1), t(2), t(3), t(4), t(5)];
            """
        )
        == [
            "CppException int: The exception is an object of type int at address xxx "
            "which does not inherit from std::exception",
            "CppException char: The exception is an object of type char at address xxx "
            "which does not inherit from std::exception",
            "CppException std::runtime_error: abc",
            "CppException myexception: My exception happened",
            "CppException char const*: The exception is an object of type char const* at "
            "address xxx which does not inherit from std::exception",
        ]
    )


def test_cpp_exception_catching(selenium):
    assert (
        selenium.run_js(
            f"""
            await pyodide.loadPackage("cpp-exceptions-test");
            const Module = pyodide._module;
            const idx = Module.LDSO.loadedLibNames["/lib/{PYVERSION}/site-packages/cpp-exceptions-test-catch.so"]
            const catchlib = Module.LDSO.loadedLibs[idx].module;
            """
            """\
            function t(x){
                const ptr = catchlib.catch_exc(x);
                const res = Module.UTF8ToString(ptr);
                Module._free(ptr);
                return res;
            }

            return [t(1), t(2), t(3), t(5)];
            """
        )
        == [
            "caught int 1000",
            "caught char 99",
            "caught runtime_error abc",
            "caught ????",
        ]
    )
