Skip to content

Embind + MEMORY64: Cannot convert Promise to a BigInt #25468

@poretga99

Description

@poretga99

Embind Promise in combination with MEMORY64 fails to correctly bind Promise types.

Uncaught (in promise) SyntaxError: Cannot convert [object Promise] to a BigInt

Version of emscripten/emsdk:
emscripten 4.0.15
Chrome Canary Version 143.0.7447.0

Failing command line in full:
main.cpp

// cat main.cpp
#include <iostream>
#include <functional>
#include <emscripten/bind.h>

class ITestAsync {
public:
    virtual ~ITestAsync() = default;
    virtual void PrintValue() = 0;
};

class ITestAsyncWrapper : public emscripten::wrapper<ITestAsync> {
public:
    EMSCRIPTEN_WRAPPER(ITestAsyncWrapper);
    ~ITestAsyncWrapper() override = default;
    void PrintValue() override {
        std::cout << "PrintValue resolving" << std::endl;
        call<emscripten::val>("PrintValue").await().as<void>();
        std::cout << "PrintValue resolved" << std::endl;
    }
};

class TestAsyncFactory {
public:
    void SetFactory(emscripten::val factory) {
        mFactory = [factory]() -> std::unique_ptr<ITestAsync> { return factory().as<std::unique_ptr<ITestAsync>>(); };
    };

    void Execute() {
        if (mFactory)
            mFactory()->PrintValue();
    };

private:
    std::function<std::unique_ptr<ITestAsync>()> mFactory;
};

EMSCRIPTEN_BINDINGS(AsyncWrapper) {
    using namespace emscripten;
    class_<ITestAsync>("ITestAsync")
        .function("PrintValue", &ITestAsync::PrintValue, pure_virtual(), async())
        .allow_subclass<ITestAsyncWrapper>("ITestAsyncWrapper");

    class_<TestAsyncFactory>("TestAsyncFactory")
        .constructor()
        .function("SetFactory", &TestAsyncFactory::SetFactory)
        .function("Execute", &TestAsyncFactory::Execute, async());
}

main.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Minimal HTML</title>
</head>
<body>
<script lang="ts" src="AsyncFactory.js"></script>
<script>
    async function main() {
        Module = await Module();
        console.log("AsyncFactory loaded",Module)

        const TestAsyncClass = Module.ITestAsync.extend("ITestAsync", {
            PrintValue() {
                return new Promise((resolve) => {
                    setTimeout(() => {
                        console.log('TestAsyncClass PrintValue executed');
                        resolve();
                    }, 10);
                });
            },

        });

        const factory = new Module.TestAsyncFactory();
        factory.SetFactory(() => new TestAsyncClass());
        await factory.Execute();
        factory.delete();


    }
    main();

</script>
</body>
</html>

Build command:

 emcc main.cpp -o AsyncFactory.js -fPIC -sMODULARIZE=1 -lembind -sJSPI -sMEMORY64=1
Image

If -sMEMORY64=1 flag is omitted, the above example works just fine.

 emcc main.cpp -o AsyncFactory.js -fPIC -sMODULARIZE=1 -lembind -sJSPI
Image

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions