diff --git a/.github/workflows/emscripten.yml b/.github/workflows/emscripten.yml new file mode 100644 index 0000000..d3f6665 --- /dev/null +++ b/.github/workflows/emscripten.yml @@ -0,0 +1,58 @@ +name: Emscripten + +on: + push: + branches: + - main + - development + pull_request: + branches: + - main + - development + +jobs: + test-emscripten: + strategy: + fail-fast: false + matrix: + emscripten: [ "3.1.44", "3.1.45", "3.1.46" ] + runs-on: "ubuntu-latest" + steps: + - uses: actions/checkout@v3 + - uses: mymindstorm/setup-emsdk@v11 + with: + version: ${{ matrix.emscripten }} + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: "1.21" + - name: Recompile examples + run: | + curdir=`pwd` + for example in $(find examples -mindepth 1 -maxdepth 1 -type d) + do + cd $curdir/$example/wasm + ./compile.sh + done + cd $curdir + - name: Test generation of examples + run: | + go generate ./... + - name: Run examples + run: | + curdir=`pwd` + for example in $(find examples -mindepth 1 -maxdepth 1 -type d) + do + cd $curdir/$example + go run main.go + done + cd $curdir + - name: Recompile testdata + run: | + curdir=`pwd` + cd testdata/wasm + ./compile.sh + cd $curdir + - name: Test all packages + run: | + go test -timeout 30m ./... -v \ No newline at end of file diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 6151c89..fa016fb 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -39,7 +39,7 @@ jobs: - name: Test implementation for coverage if: matrix.os == 'ubuntu-latest' && matrix.go == env.COVERAGE_GO_VERSION run: | - go test -timeout 30m `go list ./... | grep -v examples` -coverprofile=coverage.out -covermode=atomic -v + go test -timeout 30m `go list ./... | grep -v examples | grep -v generated` -coverpkg=-coverpkg=`go list ./... | grep -v examples | grep -v generated | tr '\n' ','` -coverprofile=coverage.out -covermode=atomic -v - name: Archive code coverage results if: matrix.os == 'ubuntu-latest' && matrix.go == env.COVERAGE_GO_VERSION uses: actions/upload-artifact@v3 diff --git a/.gitignore b/.gitignore index 485dee6..3ce5adb 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .idea +vendor diff --git a/README.md b/README.md index ad9c3ff..74ae835 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Go Reference](https://pkg.go.dev/badge/github.com/jerbob92/wazero-emscripten-embind.svg)](https://pkg.go.dev/github.com/jerbob92/wazero-emscripten-embind) [![Build Status][build-status]][build-url] - +[![codecov](https://codecov.io/gh/jerbob92/wazero-emscripten-embind/graph/badge.svg?token=4SC2SOJNZK)](https://codecov.io/gh/jerbob92/wazero-emscripten-embind) [build-status]:https://github.com/jerbob92/wazero-emscripten-embind/workflows/Go/badge.svg [build-url]:https://github.com/jerbob92/wazero-emscripten-embind/actions @@ -11,7 +11,7 @@ ## Features -* Support for all [Embind](https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html) features +* Support for almost all [Embind](https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html) features * Code generator for all Embind bindings: * [Functions](https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#a-quick-example) * [Classes](https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#classes) @@ -23,6 +23,14 @@ * Communicate between guest and host without worrying about data encoding/decoding * Direct access to memory through [memory views](https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#memory-views) +* Tested with custom test C++ and standard tests from Emscripten + +But not everything is supported: + +* ASYNCIFY: does not make a lot of sense in Go, might come later to allow Async C++ implementations to work +* EM_ASM/EM_JS (and related methods): naturally, you can't run JS in Go/Wazero. Since Go is not an interpreted language, + I don't see much sense to add support for Go code in it, as that would require a Go interpreter. +* Binding class method names to well-known symbols (which is something JS specific). ## What does Embind do? diff --git a/embind_test.go b/embind_test.go new file mode 100644 index 0000000..c41071e --- /dev/null +++ b/embind_test.go @@ -0,0 +1,1147 @@ +package embind_test + +import ( + "context" + "log" + "os" + "testing" + + embind_external "github.com/jerbob92/wazero-emscripten-embind" + "github.com/jerbob92/wazero-emscripten-embind/generator/generator" + embind "github.com/jerbob92/wazero-emscripten-embind/internal" + + "github.com/jerbob92/wazero-emscripten-embind/types" + "github.com/tetratelabs/wazero" + "github.com/tetratelabs/wazero/imports/emscripten" + "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1" + + "github.com/tetratelabs/wazero/api" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestEmbind(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Embind Suite") +} + +var ctx = context.Background() +var engine embind_external.Engine +var runtime wazero.Runtime +var mod api.Module +var wasmData []byte + +var _ = BeforeSuite(func() { + wasm, err := os.ReadFile("./testdata/wasm/tests.wasm") + if err != nil { + Expect(err).To(BeNil()) + return + } + + wasmData = wasm + + runtimeConfig := wazero.NewRuntimeConfig() + runtime = wazero.NewRuntimeWithConfig(ctx, runtimeConfig) + + if _, err := wasi_snapshot_preview1.Instantiate(ctx, runtime); err != nil { + Expect(err).To(BeNil()) + return + } + + compiledModule, err := runtime.CompileModule(ctx, wasm) + if err != nil { + log.Fatal(err) + } + + builder := runtime.NewHostModuleBuilder("env") + + emscriptenExporter, err := emscripten.NewFunctionExporterForModule(compiledModule) + if err != nil { + Expect(err).To(BeNil()) + return + } + + emscriptenExporter.ExportFunctions(builder) + + engine = embind_external.CreateEngine(embind_external.NewConfig()) + + embindExporter := engine.NewFunctionExporterForModule(compiledModule) + err = embindExporter.ExportFunctions(builder) + if err != nil { + Expect(err).To(BeNil()) + return + } + + _, err = builder.Instantiate(ctx) + if err != nil { + Expect(err).To(BeNil()) + return + } + + moduleConfig := wazero.NewModuleConfig(). + WithStartFunctions("_initialize"). + WithStdout(os.Stdout). + WithStderr(os.Stderr). + WithName("") + + ctx = engine.Attach(ctx) + mod, err = runtime.InstantiateModule(ctx, compiledModule, moduleConfig) + if err != nil { + Expect(err).To(BeNil()) + return + } +}) + +var _ = AfterSuite(func() { + runtime.Close(ctx) +}) + +var _ = Describe("Calling embind functions", Label("library"), func() { + When("the function is being called", func() { + It("gives an error on an invalid argument count", func() { + res, err := engine.CallPublicSymbol(ctx, "bool_return_bool", 1, 2) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("function bool_return_bool called with 2 argument(s), expected 1 arg(s)")) + } + Expect(res).To(BeNil()) + }) + Context("the return type is bool", func() { + It("has the correct return values", func() { + res, err := engine.CallPublicSymbol(ctx, "bool_return_true") + Expect(err).To(BeNil()) + Expect(res).To(BeTrue()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_false") + Expect(err).To(BeNil()) + Expect(res).To(BeFalse()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", false) + Expect(err).To(BeNil()) + Expect(res).To(BeFalse()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", true) + Expect(err).To(BeNil()) + Expect(res).To(BeTrue()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", int(0)) + Expect(err).To(BeNil()) + Expect(res).To(BeFalse()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", int(1)) + Expect(err).To(BeNil()) + Expect(res).To(BeTrue()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", uint(0)) + Expect(err).To(BeNil()) + Expect(res).To(BeFalse()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", uint(1)) + Expect(err).To(BeNil()) + Expect(res).To(BeTrue()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", int8(0)) + Expect(err).To(BeNil()) + Expect(res).To(BeFalse()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", int8(1)) + Expect(err).To(BeNil()) + Expect(res).To(BeTrue()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", uint8(0)) + Expect(err).To(BeNil()) + Expect(res).To(BeFalse()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", uint8(1)) + Expect(err).To(BeNil()) + Expect(res).To(BeTrue()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", int16(0)) + Expect(err).To(BeNil()) + Expect(res).To(BeFalse()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", int16(1)) + Expect(err).To(BeNil()) + Expect(res).To(BeTrue()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", uint16(0)) + Expect(err).To(BeNil()) + Expect(res).To(BeFalse()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", uint16(1)) + Expect(err).To(BeNil()) + Expect(res).To(BeTrue()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", int32(0)) + Expect(err).To(BeNil()) + Expect(res).To(BeFalse()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", int32(1)) + Expect(err).To(BeNil()) + Expect(res).To(BeTrue()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", uint32(0)) + Expect(err).To(BeNil()) + Expect(res).To(BeFalse()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", uint32(1)) + Expect(err).To(BeNil()) + Expect(res).To(BeTrue()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", uint16(1)) + Expect(err).To(BeNil()) + Expect(res).To(BeTrue()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", int64(0)) + Expect(err).To(BeNil()) + Expect(res).To(BeFalse()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", int64(1)) + Expect(err).To(BeNil()) + Expect(res).To(BeTrue()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", uint64(0)) + Expect(err).To(BeNil()) + Expect(res).To(BeFalse()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", uint64(1)) + Expect(err).To(BeNil()) + Expect(res).To(BeTrue()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", float32(0)) + Expect(err).To(BeNil()) + Expect(res).To(BeFalse()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", float32(1)) + Expect(err).To(BeNil()) + Expect(res).To(BeTrue()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", float64(0)) + Expect(err).To(BeNil()) + Expect(res).To(BeFalse()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", float64(1)) + Expect(err).To(BeNil()) + Expect(res).To(BeTrue()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", "") + Expect(err).To(BeNil()) + Expect(res).To(BeFalse()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", "123") + Expect(err).To(BeNil()) + Expect(res).To(BeTrue()) + + res, err = engine.CallPublicSymbol(ctx, "bool_return_bool", struct { + }{}) + Expect(err).To(BeNil()) + Expect(res).To(BeTrue()) + }) + }) + + Context("the return type is void", func() { + It("has the correct return type", func() { + res, err := engine.CallPublicSymbol(ctx, "float_return_void", float32(123)) + Expect(err).To(BeNil()) + Expect(res).To(BeNil()) + }) + }) + + Context("the return type is float", func() { + It("gives an error on an invalid input", func() { + res, err := engine.CallPublicSymbol(ctx, "float_return_float", 1) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not get wire type of argument 0 (float): value must be of type float32")) + } + Expect(res).To(BeNil()) + }) + It("has the correct return values", func() { + res, err := engine.CallPublicSymbol(ctx, "float_return_float", float32(3)) + Expect(err).To(BeNil()) + Expect(res).To(Equal(float32(9))) + }) + }) + + Context("the return type is double", func() { + It("gives an error on an invalid input", func() { + res, err := engine.CallPublicSymbol(ctx, "double_return_double", 1) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not get wire type of argument 0 (double): value must be of type float64")) + } + Expect(res).To(BeNil()) + }) + It("has the correct return values", func() { + res, err := engine.CallPublicSymbol(ctx, "double_return_double", float64(3)) + Expect(err).To(BeNil()) + Expect(res).To(Equal(float64(9))) + }) + }) + + Context("the return type is int", func() { + It("gives an error on an invalid input", func() { + res, err := engine.CallPublicSymbol(ctx, "int_return_int", 1) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not get wire type of argument 0 (int): value must be of type int32")) + } + Expect(res).To(BeNil()) + }) + It("has the correct return values", func() { + res, err := engine.CallPublicSymbol(ctx, "int_return_int", int32(3)) + Expect(err).To(BeNil()) + Expect(res).To(Equal(int32(9))) + }) + }) + + Context("the return type is char", func() { + It("gives an error on an invalid input", func() { + res, err := engine.CallPublicSymbol(ctx, "char_return_char", 1) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not get wire type of argument 0 (char): value must be of type int8, is int")) + } + Expect(res).To(BeNil()) + }) + It("has the correct return values", func() { + res, err := engine.CallPublicSymbol(ctx, "char_return_char", int8(3)) + Expect(err).To(BeNil()) + Expect(res).To(Equal(int8(3))) + }) + }) + + Context("the return type is long", func() { + It("gives an error on an invalid input", func() { + res, err := engine.CallPublicSymbol(ctx, "long_return_long", 1) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not get wire type of argument 0 (long): value must be of type int32, is int")) + } + Expect(res).To(BeNil()) + }) + It("has the correct return values", func() { + res, err := engine.CallPublicSymbol(ctx, "long_return_long", int32(3)) + Expect(err).To(BeNil()) + Expect(res).To(Equal(int32(6))) + }) + }) + + Context("the return type is short", func() { + It("gives an error on an invalid input", func() { + res, err := engine.CallPublicSymbol(ctx, "short_return_short", 1) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not get wire type of argument 0 (short): value must be of type int16, is int")) + } + Expect(res).To(BeNil()) + }) + It("has the correct return values", func() { + res, err := engine.CallPublicSymbol(ctx, "short_return_short", int16(3)) + Expect(err).To(BeNil()) + Expect(res).To(Equal(int16(6))) + }) + }) + + Context("the return type is unsigned char", func() { + It("gives an error on an invalid input", func() { + res, err := engine.CallPublicSymbol(ctx, "uchar_return_uchar", 1) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not get wire type of argument 0 (unsigned char): value must be of type uint8, is int")) + } + Expect(res).To(BeNil()) + }) + It("has the correct return values", func() { + res, err := engine.CallPublicSymbol(ctx, "uchar_return_uchar", uint8(3)) + Expect(err).To(BeNil()) + Expect(res).To(Equal(uint8(3))) + }) + }) + + Context("the return type is unsigned int", func() { + It("gives an error on an invalid input", func() { + res, err := engine.CallPublicSymbol(ctx, "uint_return_uint", 1) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not get wire type of argument 0 (unsigned int): value must be of type uint32, is int")) + } + Expect(res).To(BeNil()) + }) + It("has the correct return values", func() { + res, err := engine.CallPublicSymbol(ctx, "uint_return_uint", uint32(3)) + Expect(err).To(BeNil()) + Expect(res).To(Equal(uint32(6))) + }) + }) + + Context("the return type is unsigned long", func() { + It("gives an error on an invalid input", func() { + res, err := engine.CallPublicSymbol(ctx, "ulong_return_ulong", 1) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not get wire type of argument 0 (unsigned long): value must be of type uint32, is int")) + } + Expect(res).To(BeNil()) + }) + It("has the correct return values", func() { + res, err := engine.CallPublicSymbol(ctx, "ulong_return_ulong", uint32(3)) + Expect(err).To(BeNil()) + Expect(res).To(Equal(uint32(6))) + }) + }) + + Context("the return type is unsigned short", func() { + It("gives an error on an invalid input", func() { + res, err := engine.CallPublicSymbol(ctx, "ushort_return_ushort", 1) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not get wire type of argument 0 (unsigned short): value must be of type uint16, is int")) + } + Expect(res).To(BeNil()) + }) + It("has the correct return values", func() { + res, err := engine.CallPublicSymbol(ctx, "ushort_return_ushort", uint16(3)) + Expect(err).To(BeNil()) + Expect(res).To(Equal(uint16(6))) + }) + }) + + Context("the return type is long long", func() { + It("gives an error on an invalid input", func() { + res, err := engine.CallPublicSymbol(ctx, "longlong_return_longlong", 1) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not get wire type of argument 0 (int64_t): value must be of type int64")) + } + Expect(res).To(BeNil()) + }) + It("has the correct return values", func() { + res, err := engine.CallPublicSymbol(ctx, "longlong_return_longlong", int64(3)) + Expect(err).To(BeNil()) + Expect(res).To(Equal(int64(6))) + }) + }) + + Context("the return type is unsigned long long", func() { + It("gives an error on an invalid input", func() { + res, err := engine.CallPublicSymbol(ctx, "ulonglong_return_ulonglong", 1) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not get wire type of argument 0 (uint64_t): value must be of type uint64")) + } + Expect(res).To(BeNil()) + }) + It("has the correct return values", func() { + res, err := engine.CallPublicSymbol(ctx, "ulonglong_return_ulonglong", uint64(3)) + Expect(err).To(BeNil()) + Expect(res).To(Equal(uint64(6))) + }) + }) + + Context("the return type is std string", func() { + It("gives an error on an invalid input", func() { + res, err := engine.CallPublicSymbol(ctx, "std_string_return_std_string", 1) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not get wire type of argument 0 (std::string): value must be of type string")) + } + Expect(res).To(BeNil()) + }) + It("has the correct return values", func() { + res, err := engine.CallPublicSymbol(ctx, "std_string_return_std_string", "embind") + Expect(err).To(BeNil()) + Expect(res).To(Equal("Hello there embind")) + }) + }) + + Context("the return type is std wstring", func() { + It("gives an error on an invalid input", func() { + res, err := engine.CallPublicSymbol(ctx, "std_wstring_return_std_wstring", 1) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not get wire type of argument 0 (std::wstring): input must be a string, was int")) + } + Expect(res).To(BeNil()) + }) + It("has the correct return values", func() { + res, err := engine.CallPublicSymbol(ctx, "std_wstring_return_std_wstring", "embind") + Expect(err).To(BeNil()) + Expect(res).To(Equal("Hello there embind")) + }) + }) + + Context("the return type is std u16string", func() { + It("gives an error on an invalid input", func() { + res, err := engine.CallPublicSymbol(ctx, "std_u16string_return_std_u16string", 1) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not get wire type of argument 0 (std::u16string): input must be a string, was int")) + } + Expect(res).To(BeNil()) + }) + It("has the correct return values", func() { + res, err := engine.CallPublicSymbol(ctx, "std_u16string_return_std_u16string", "embind") + Expect(err).To(BeNil()) + Expect(res).To(Equal("Hello there embind")) + }) + }) + + Context("the return type is a vector", func() { + It("has the correct return value", func() { + res, err := engine.CallPublicSymbol(ctx, "return_vector") + Expect(err).To(BeNil()) + Expect(res).To(Not(BeNil())) + Expect(res).To(BeAssignableToTypeOf(&embind.ClassBase{})) + if obj, ok := res.(*embind.ClassBase); ok { + size, err := obj.CallInstanceMethod(ctx, obj, "size") + Expect(err).To(BeNil()) + Expect(size).To(Equal(uint32(10))) + + _, err = obj.CallInstanceMethod(ctx, obj, "resize", uint32(12), int32(1)) + Expect(err).To(BeNil()) + + size, err = obj.CallInstanceMethod(ctx, obj, "size") + Expect(err).To(BeNil()) + Expect(size).To(Equal(uint32(12))) + + val, err := obj.CallInstanceMethod(ctx, obj, "get", uint32(1)) + Expect(err).To(BeNil()) + Expect(val).To(Equal(int32(1))) + + _, err = obj.CallInstanceMethod(ctx, obj, "set", uint32(1), int32(2)) + Expect(err).To(BeNil()) + + val, err = obj.CallInstanceMethod(ctx, obj, "get", uint32(1)) + Expect(err).To(BeNil()) + Expect(val).To(Equal(int32(2))) + } + }) + }) + + Context("the return type is a map", func() { + It("has the correct return value", func() { + res, err := engine.CallPublicSymbol(ctx, "return_map") + Expect(err).To(BeNil()) + Expect(res).To(Not(BeNil())) + Expect(res).To(BeAssignableToTypeOf(&embind.ClassBase{})) + if obj, ok := res.(*embind.ClassBase); ok { + size, err := obj.CallInstanceMethod(ctx, obj, "size") + Expect(err).To(BeNil()) + Expect(size).To(Equal(uint32(1))) + + val, err := obj.CallInstanceMethod(ctx, obj, "get", int32(10)) + Expect(err).To(BeNil()) + Expect(val).To(Equal("This is a string.")) + + val, err = obj.CallInstanceMethod(ctx, obj, "get", int32(1)) + Expect(err).To(BeNil()) + Expect(val).To(Equal(types.Undefined)) + } + }) + }) + + Context("the return type is a memory view", func() { + Context("of type char", func() { + It("has the correct values", func() { + res, err := engine.CallPublicSymbol(ctx, "get_memory_view_char") + Expect(err).To(BeNil()) + Expect(res).To(Equal([]int8{0, 1, 2, 3, 4, 5})) + }) + }) + + Context("of type uchar", func() { + It("has the correct values", func() { + res, err := engine.CallPublicSymbol(ctx, "get_memory_view_unsigned_char") + Expect(err).To(BeNil()) + Expect(res).To(Equal([]uint8{0, 1, 2, 3, 4, 5})) + }) + }) + + Context("of type int", func() { + It("has the correct values", func() { + res, err := engine.CallPublicSymbol(ctx, "get_memory_view_int") + Expect(err).To(BeNil()) + Expect(res).To(Equal([]int32{0, 1, 2, 3, 4, 5})) + }) + }) + + Context("of type uint", func() { + It("has the correct values", func() { + res, err := engine.CallPublicSymbol(ctx, "get_memory_view_unsigned_int") + Expect(err).To(BeNil()) + Expect(res).To(Equal([]uint32{0, 1, 2, 3, 4, 5})) + }) + }) + + Context("of type long", func() { + It("has the correct values", func() { + res, err := engine.CallPublicSymbol(ctx, "get_memory_view_long") + Expect(err).To(BeNil()) + Expect(res).To(Equal([]int32{0, 1, 2, 3, 4, 5})) + }) + }) + + Context("of type unsigned long", func() { + It("has the correct values", func() { + res, err := engine.CallPublicSymbol(ctx, "get_memory_view_unsigned_long") + Expect(err).To(BeNil()) + Expect(res).To(Equal([]uint32{0, 1, 2, 3, 4, 5})) + }) + }) + + Context("of type short", func() { + It("has the correct values", func() { + res, err := engine.CallPublicSymbol(ctx, "get_memory_view_short") + Expect(err).To(BeNil()) + Expect(res).To(Equal([]int16{0, 1, 2, 3, 4, 5})) + }) + }) + + Context("of type ushort", func() { + It("has the correct values", func() { + res, err := engine.CallPublicSymbol(ctx, "get_memory_view_unsigned_short") + Expect(err).To(BeNil()) + Expect(res).To(Equal([]uint16{0, 1, 2, 3, 4, 5})) + }) + }) + + Context("of type longlong", func() { + It("has the correct values", func() { + res, err := engine.CallPublicSymbol(ctx, "get_memory_view_longlong") + Expect(err).To(BeNil()) + Expect(res).To(Equal([]int64{0, 1, 2, 3, 4, 5})) + }) + }) + + Context("of type unsigned longlong", func() { + It("has the correct values", func() { + res, err := engine.CallPublicSymbol(ctx, "get_memory_view_unsigned_longlong") + Expect(err).To(BeNil()) + Expect(res).To(Equal([]uint64{0, 1, 2, 3, 4, 5})) + }) + }) + + Context("of type double", func() { + It("has the correct values", func() { + res, err := engine.CallPublicSymbol(ctx, "get_memory_view_double") + Expect(err).To(BeNil()) + Expect(res).To(Equal([]float64{0, 1, 2, 3, 4, 5})) + }) + }) + + Context("of type float", func() { + It("has the correct values", func() { + res, err := engine.CallPublicSymbol(ctx, "get_memory_view_float") + Expect(err).To(BeNil()) + Expect(res).To(Equal([]float32{0, 1, 2, 3, 4, 5})) + }) + }) + }) + Context("when an overload table is used", func() { + It("gives an error on an unknown number of arguments", func() { + res, err := engine.CallPublicSymbol(ctx, "function_overload", 1, 2, 3) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("function 'function_overload' called with an invalid number of arguments (3) - expects one of (0, 1)")) + } + Expect(res).To(BeNil()) + }) + + It("gives an error on a wrong argument type", func() { + res, err := engine.CallPublicSymbol(ctx, "function_overload", "test") + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("function_overload: could not get wire type of argument 0 (int): value must be of type int32, is string")) + } + Expect(res).To(BeNil()) + }) + + It("picks the correct item from the overload table", func() { + res, err := engine.CallPublicSymbol(ctx, "function_overload") + Expect(err).To(BeNil()) + Expect(res).To(Equal(int32(1))) + + res, err = engine.CallPublicSymbol(ctx, "function_overload", int32(12)) + Expect(err).To(BeNil()) + Expect(res).To(Equal(int32(2))) + }) + }) + }) +}) + +var _ = Describe("Using embind constants", Label("library"), func() { + When("the constants are being registered", func() { + It("has the correct values", func() { + var constantsMap = map[string]any{} + constants := engine.GetConstants() + for i := range constants { + constantsMap[constants[i].Name()] = constants[i].Value() + } + + Expect(constantsMap).To(HaveKeyWithValue("SOME_CONSTANT_1", false)) + Expect(constantsMap).To(HaveKeyWithValue("SOME_CONSTANT_2", float32(2))) + Expect(constantsMap).To(HaveKeyWithValue("SOME_CONSTANT_3", float64(3))) + Expect(constantsMap).To(HaveKeyWithValue("SOME_CONSTANT_4", int32(4))) + Expect(constantsMap).To(HaveKeyWithValue("SOME_CONSTANT_5", "TestString")) + Expect(constantsMap).To(HaveKeyWithValue("SOME_CONSTANT_6", int8(67))) + Expect(constantsMap).To(HaveKeyWithValue("SOME_CONSTANT_7", int64(7))) + Expect(constantsMap).To(HaveKeyWithValue("SOME_CONSTANT_8", uint16(8))) + Expect(constantsMap).To(HaveKeyWithValue("SOME_CONSTANT_9", uint32(9))) + Expect(constantsMap).To(HaveKeyWithValue("SOME_CONSTANT_10", uint16(10))) + Expect(constantsMap).To(HaveKeyWithValue("SOME_CONSTANT_11", uint8(11))) + Expect(constantsMap).To(HaveKeyWithValue("SOME_CONSTANT_12", uint32(12))) + Expect(constantsMap).To(HaveKeyWithValue("SOME_CONSTANT_13", "TestWideString")) + Expect(constantsMap).To(HaveKeyWithValue("SOME_CONSTANT_14", true)) + Expect(constantsMap).To(HaveKeyWithValue("SOME_CONSTANT_15", uint64(15))) + + Expect(constantsMap).To(HaveKeyWithValue("hasUnboundTypeNames", true)) + Expect(constantsMap).To(HaveKeyWithValue("STRING_CONSTANT", "some string")) + Expect(constantsMap).To(HaveKey("VALUE_OBJECT_CONSTANT")) + Expect(constantsMap["VALUE_OBJECT_CONSTANT"]).To(HaveKeyWithValue("x", float32(1))) + Expect(constantsMap["VALUE_OBJECT_CONSTANT"]).To(HaveKeyWithValue("y", float32(2))) + Expect(constantsMap["VALUE_OBJECT_CONSTANT"]).To(HaveKeyWithValue("z", float32(3))) + Expect(constantsMap["VALUE_OBJECT_CONSTANT"]).To(HaveKeyWithValue("w", float32(4))) + Expect(constantsMap).To(HaveKeyWithValue("STATIC_CONST_INTEGER_VALUE_1000", int32(1000))) + Expect(constantsMap).To(HaveKeyWithValue("STATIC_CONST_INTEGER_VALUE_1", int32(1))) + Expect(constantsMap).To(HaveKeyWithValue("INT_CONSTANT", int32(10))) + Expect(constantsMap).To(HaveKeyWithValue("VALUE_ARRAY_CONSTANT", []any{float32(1), float32(2), float32(3), float32(4)})) + + Expect(constantsMap).To(HaveLen(22)) + }) + }) +}) + +var _ = Describe("Using embind enums", Label("library"), func() { + When("the enums are being registered", func() { + It("has the correct values", func() { + var enumsMap = map[string]map[string]any{} + enums := engine.GetEnums() + for i := range enums { + values := map[string]any{} + + enumValues := enums[i].Values() + for valI := range enumValues { + values[enumValues[valI].Name()] = enumValues[valI].Value() + } + + enumsMap[enums[i].Name()] = values + } + + Expect(enumsMap).To(HaveKeyWithValue("OldStyle", map[string]any{ + "ONE": uint32(0), + "TWO": uint32(1), + })) + Expect(enumsMap["OldStyle"]).To(HaveLen(2)) + Expect(enumsMap).To(HaveKeyWithValue("NewStyle", map[string]any{ + "ONE": int32(0), + "TWO": int32(1), + })) + Expect(enumsMap["NewStyle"]).To(HaveLen(2)) + }) + + It("can be encoded and decoded", func() { + res, err := engine.CallPublicSymbol(ctx, "enum_in_enum_out", int32(0)) + Expect(err).To(BeNil()) + Expect(res).To(Equal(uint32(1))) + }) + }) +}) + +var _ = Describe("Using embind structs", Label("library"), func() { + When("using the structs", func() { + It("can be decoded with an array as input", func() { + res, err := engine.CallPublicSymbol(ctx, "findPersonAtLocation", []any{float32(1), float32(2)}) + Expect(err).To(BeNil()) + Expect(res).To(Equal(map[string]any{ + "name": "123", + "age": int32(12), + "structArray": map[string]any{ + "field": []any{int32(1), int32(2)}, + }, + })) + }) + + It("can be encoded with an array and struct as input", func() { + res, err := engine.CallPublicSymbol(ctx, "setPersonAtLocation", []any{float32(1), float32(2)}, map[string]any{ + "name": "123", + "age": int32(12), + "structArray": map[string]any{ + "field": []any{int32(1), int32(2)}, + }, + }) + Expect(err).To(BeNil()) + Expect(res).To(BeNil()) + }) + + It("gives an error when not giving all fields as input", func() { + res, err := engine.CallPublicSymbol(ctx, "setPersonAtLocation", []any{float32(1), float32(2)}, map[string]any{ + "fakefield": "123", + }) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("missing field: name")) + } + Expect(res).To(BeNil()) + }) + + It("gives an error when an incomplete number of array elements is given", func() { + res, err := engine.CallPublicSymbol(ctx, "setPersonAtLocation", []any{float32(1), float32(2)}, map[string]any{ + "name": "123", + "age": int32(12), + "structArray": map[string]any{ + "field": []any{int32(1)}, + }, + }) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("incorrect number of tuple elements for array_int_2: expected=2, actual=1")) + } + Expect(res).To(BeNil()) + }) + }) +}) + +type webkitAudioContextOscillatorFrequency struct { + Value float64 `embind_property:"value"` +} + +type webkitAudioContextOscillator struct { + Typing string `embind_property:"type"` + Frequencdy *webkitAudioContextOscillatorFrequency `embind_property:"frequency"` +} + +func (waco *webkitAudioContextOscillator) Connect(destination string) error { + return nil +} + +func (waco *webkitAudioContextOscillator) Start(destination int32) error { + return nil +} + +func (waco *webkitAudioContextOscillator) MapFunction(name string, returnType string, argTypes []string) (string, error) { + if name == "start" { + return "Start", nil + } + return "", nil +} + +type webkitAudioContext struct { + Destination string `embind_arg:"0"` +} + +func (was *webkitAudioContext) CreateOscillator() (*webkitAudioContextOscillator, error) { + return &webkitAudioContextOscillator{ + Frequencdy: &webkitAudioContextOscillatorFrequency{}, + }, nil +} + +type ICreateOscillator interface { + CreateOscillator() *webkitAudioContextOscillator +} + +var _ = Describe("Using embind emval", Label("library"), func() { + When("using the Go struct mapping", func() { + It("fails when no struct is mapped", func() { + _, err := engine.CallPublicSymbol(ctx, "doEmval") + Expect(err).To(Not(BeNil())) + }) + + It("can map the struct", func() { + c2 := &webkitAudioContext{} + err := engine.RegisterEmvalSymbol("webkitAudioContext", c2) + Expect(err).To(BeNil()) + }) + + It("gives an error when a non pointer struct is already mapped", func() { + c2 := &webkitAudioContext{} + err := engine.RegisterEmvalSymbol("webkitAudioContext", c2) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not register symbol webkitAudioContext, already registered as type *embind_test.webkitAudioContext")) + } + }) + + It("can use the full struct from C++", func() { + res, err := engine.CallPublicSymbol(ctx, "doEmval") + Expect(err).To(BeNil()) + Expect(res).To(Equal(`No global AudioContext, trying webkitAudioContext +Got an AudioContext +Configuring oscillator +Playing +All done! +`)) + }) + + It("can create an array", func() { + array, err := engine.CallPublicSymbol(ctx, "emval_array") + Expect(err).To(BeNil()) + Expect(array).To(Equal([]any{})) + }) + }) +}) + +var _ = Describe("Using embind classes", Label("library"), func() { + When("Constructing a new class", func() { + It("fails when an invalid number of arguments is given", func() { + res, err := engine.CallPublicSymbol(ctx, "MyClass") + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("with invalid number of parameters (0) - expected (1 or 2) parameters instead")) + } + Expect(res).To(BeNil()) + }) + It("fails when an invalid argument is given", func() { + res, err := engine.CallPublicSymbol(ctx, "MyClass", float64(123)) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not get wire type of argument 0 (int): value must be of type int32, is float64")) + } + Expect(res).To(BeNil()) + }) + + It("succeeds to construct with both overloads", func() { + res, err := engine.CallPublicSymbol(ctx, "MyClass", int32(123)) + Expect(err).To(BeNil()) + Expect(res).To(Not(BeNil())) + Expect(res).To(BeAssignableToTypeOf(&embind.ClassBase{})) + + res, err = engine.CallPublicSymbol(ctx, "MyClass", int32(123), "test123") + Expect(err).To(BeNil()) + Expect(res).To(Not(BeNil())) + Expect(res).To(BeAssignableToTypeOf(&embind.ClassBase{})) + }) + + Context("when the class has been constructed", func() { + var myClass *embind.ClassBase + BeforeEach(func() { + res, err := engine.CallPublicSymbol(ctx, "MyClass", int32(123), "test") + Expect(err).To(BeNil()) + Expect(res).To(Not(BeNil())) + Expect(res).To(BeAssignableToTypeOf(&embind.ClassBase{})) + if obj, ok := res.(*embind.ClassBase); ok { + myClass = obj + } + }) + + AfterEach(func() { + if myClass != nil { + err := myClass.DeleteInstance(ctx, myClass) + Expect(err).To(BeNil()) + } + }) + + Context("when calling functions", func() { + It("gives an error on an unknown function", func() { + res, err := myClass.CallInstanceMethod(ctx, myClass, "unknown", 1, 2, 3) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("MyClass.unknown() is not found")) + } + Expect(res).To(BeNil()) + }) + + It("gives an error on a function with a wrong argument count", func() { + res, err := myClass.CallInstanceMethod(ctx, myClass, "combineY", 1, 2, 3) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("called with 3 argument(s), expected 1 arg(s)")) + } + Expect(res).To(BeNil()) + }) + + It("gives an error on a function with a wrong argument", func() { + res, err := myClass.CallInstanceMethod(ctx, myClass, "combineY", 1) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not get wire type of argument 0 (std::string): value must be of type string")) + } + Expect(res).To(BeNil()) + }) + + It("can call the method correctly", func() { + res, err := myClass.CallInstanceMethod(ctx, myClass, "combineY", "hello ") + Expect(err).To(BeNil()) + Expect(res).To(Equal("hello test")) + }) + + Context("that have overloads", func() { + It("fails when giving an invalid overload", func() { + res, err := myClass.CallInstanceMethod(ctx, myClass, "incrementX", 1, 2, 3) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("called with an invalid number of arguments (3) - expects one of (0, 1)")) + } + Expect(res).To(BeNil()) + }) + + It("works with each of the overloads", func() { + res, err := myClass.CallInstanceMethod(ctx, myClass, "incrementX", int32(1)) + Expect(err).To(BeNil()) + Expect(res).To(BeNil()) + + res, err = myClass.CallInstanceMethod(ctx, myClass, "incrementX") + Expect(err).To(BeNil()) + Expect(res).To(BeNil()) + }) + }) + }) + Context("when calling setters/getters", func() { + It("gives an error on an unknown property", func() { + res, err := myClass.GetInstanceProperty(ctx, myClass, "test") + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("MyClass.test is a not found")) + } + Expect(res).To(BeNil()) + + err = myClass.SetInstanceProperty(ctx, myClass, "test", 123) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("MyClass.test is a not found")) + } + Expect(res).To(BeNil()) + }) + + It("gives an error when setting on a readonly property", func() { + err := myClass.SetInstanceProperty(ctx, myClass, "y", "") + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("MyClass.y is a read-only property")) + } + }) + + It("gives an error when setting with a wrong argument", func() { + err := myClass.SetInstanceProperty(ctx, myClass, "x", "") + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("value must be of type int32, is string")) + } + }) + + It("allows setting and getting a property", func() { + err := myClass.SetInstanceProperty(ctx, myClass, "x", int32(3)) + Expect(err).To(BeNil()) + + res, err := myClass.GetInstanceProperty(ctx, myClass, "x") + Expect(err).To(BeNil()) + Expect(res).To(Equal(int32(3))) + }) + + It("allows getting a property", func() { + res, err := myClass.GetInstanceProperty(ctx, myClass, "x") + Expect(err).To(BeNil()) + Expect(res).To(Equal(int32(123))) + }) + }) + + Context("when calling static methods", func() { + It("gives an error on an unknown class", func() { + res, err := engine.CallStaticClassMethod(ctx, "MyClass123", "test") + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not find class MyClass123")) + } + Expect(res).To(BeNil()) + }) + + It("gives an error on an unknown method", func() { + res, err := engine.CallStaticClassMethod(ctx, "MyClass", "test") + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not find method test on class MyClass")) + } + Expect(res).To(BeNil()) + }) + + It("gives an error on an invalid argument", func() { + res, err := engine.CallStaticClassMethod(ctx, "MyClass", "getStringFromInstance", 123) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not get wire type of argument 0 (MyClass): invalid MyClass, check whether you constructed it properly through embind, the given value is a int")) + } + Expect(res).To(BeNil()) + }) + + It("gives an error on an invalid argument count", func() { + res, err := engine.CallStaticClassMethod(ctx, "MyClass", "getStringFromInstance", 1, 2) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("function MyClass.getStringFromInstance called with 2 argument(s), expected 1 arg(s)")) + } + Expect(res).To(BeNil()) + }) + + It("allows calling a static method", func() { + res, err := engine.CallStaticClassMethod(ctx, "MyClass", "getStringFromInstance", myClass) + Expect(err).To(BeNil()) + Expect(res).To(Equal("test")) + }) + }) + }) + }) + When("A class is mapped to a Go struct", func() { + It("fails to map when the class doesn't embed the class base", func() { + type ClassMyClass struct{} + err := engine.RegisterClass("MyClass", &ClassMyClass{}) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("it does not embed embind.ClassBase")) + } + }) + It("fails to map when the class isn't passed as pointer", func() { + type ClassMyClass struct { + embind_external.ClassBase + } + err := engine.RegisterClass("MyClass", ClassMyClass{}) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("given value should be a pointer type")) + } + }) + It("succeeds to construct with both overloads", func() { + type ClassMyClass struct { + embind_external.ClassBase + } + err := engine.RegisterClass("MyClass", &ClassMyClass{}) + Expect(err).To(BeNil()) + + res, err := engine.CallPublicSymbol(ctx, "MyClass", int32(123)) + Expect(err).To(BeNil()) + Expect(res).To(Not(BeNil())) + Expect(res).To(BeAssignableToTypeOf(&ClassMyClass{})) + + res, err = engine.CallPublicSymbol(ctx, "MyClass", int32(123), "test123") + Expect(err).To(BeNil()) + Expect(res).To(Not(BeNil())) + Expect(res).To(BeAssignableToTypeOf(&ClassMyClass{})) + + passThrough, err := engine.CallPublicSymbol(ctx, "passThrough", res) + Expect(err).To(BeNil()) + Expect(passThrough).To(Not(BeNil())) + Expect(passThrough).To(BeAssignableToTypeOf(&ClassMyClass{})) + Expect(passThrough).To(Equal(res)) + }) + + It("errors when it is already mapped", func() { + type ClassMyClass struct { + embind_external.ClassBase + } + err := engine.RegisterClass("MyClass", &ClassMyClass{}) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("could not register class MyClass, already registered as type *embind_test.ClassMyClass")) + } + }) + }) +}) + +var _ = Describe("Using the generator", Label("generator"), func() { + When("generating the code", func() { + It("succeeds generating the code", func() { + err := generator.Generate("./tests/generated", "./tests/generated/generate.go", wasmData, "_initialize") + Expect(err).To(BeNil()) + }) + }) +}) diff --git a/engine.go b/engine.go index 92dc7e8..71a253f 100644 --- a/engine.go +++ b/engine.go @@ -11,6 +11,8 @@ type Engine interface { NewFunctionExporterForModule(guest wazero.CompiledModule) FunctionExporter } +type DelayFunction internal.DelayFunction + type EngineKey = internal.EngineKey func CreateEngine(config internal.IEngineConfig) Engine { diff --git a/examples/classes/generated/classes.go b/examples/classes/generated/classes.go index af6d174..9358979 100644 --- a/examples/classes/generated/classes.go +++ b/examples/classes/generated/classes.go @@ -11,37 +11,118 @@ type ClassMyClass struct { embind.ClassBase } -func (class *ClassMyClass) GetX(ctx context.Context) (int32, error) { - res, err := class.GetProperty(ctx, class, "x") +func (class *ClassMyClass) Clone(ctx context.Context) (*ClassMyClass, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassMyClass), nil +} + +func (class *ClassMyClass) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassMyClass) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassMyClass) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassMyClass) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassMyClass) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassMyClass) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassMyClass) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassMyClass) GetPropertyX(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "x") if err != nil { return int32(0), err } + if res == nil { + return int32(0), nil + } + return res.(int32), nil } -func (class *ClassMyClass) SetX(ctx context.Context, val int32) error { - return class.SetProperty(ctx, class, "x", val) +func (class *ClassMyClass) SetPropertyX(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "x", val) } -func (class *ClassMyClass) IncrementX(ctx context.Context) error { - _, err := class.CallMethod(ctx, class, "incrementX") +func (class *ClassMyClass) IncrementX0(ctx context.Context) error { + _, err := class.CallMethod(ctx, "incrementX") return err } -func ClassMyClassStaticGetStringFromInstance(e embind.Engine, ctx context.Context, arg0 *ClassMyClass) (string, error) { +func (class *ClassMyClass) IncrementX1(ctx context.Context, arg0 int32) error { + _, err := class.CallMethod(ctx, "incrementX", arg0) + return err +} + +func (class *ClassMyClass) StaticGetStringFromInstance(ctx context.Context, arg0 embind.ClassBase) (string, error) { + res, err := class.CallInstanceMethod(ctx, nil, "getStringFromInstance", arg0) + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} +func ClassMyClassStaticGetStringFromInstance(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (string, error) { res, err := e.CallStaticClassMethod(ctx, "MyClass", "getStringFromInstance", arg0) if err != nil { return "", err } + if res == nil { + return "", nil + } + return res.(string), nil } -func NewClassMyClass(e embind.Engine, ctx context.Context, arg0 int32, arg1 string) (*ClassMyClass, error) { +func NewClassMyClass1(e embind.Engine, ctx context.Context, arg0 int32) (*ClassMyClass, error) { + res, err := e.CallPublicSymbol(ctx, "MyClass", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassMyClass), nil +} + +func NewClassMyClass2(e embind.Engine, ctx context.Context, arg0 int32, arg1 string) (*ClassMyClass, error) { res, err := e.CallPublicSymbol(ctx, "MyClass", arg0, arg1) if err != nil { return nil, err } + if res == nil { + return nil, nil + } + return res.(*ClassMyClass), nil } diff --git a/examples/classes/generated/functions.go b/examples/classes/generated/functions.go index 8253b2c..5a3c982 100644 --- a/examples/classes/generated/functions.go +++ b/examples/classes/generated/functions.go @@ -7,15 +7,18 @@ import ( "github.com/jerbob92/wazero-emscripten-embind" ) -func MyClass(e embind.Engine, ctx context.Context) (*ClassMyClass, error) { +func MyClass(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { res, err := e.CallPublicSymbol(ctx, "MyClass") if err != nil { return nil, err } - return res.(*ClassMyClass), nil + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil } -func PrintMyClass(e embind.Engine, ctx context.Context, arg0 *ClassMyClass) error { +func PrintMyClass(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) error { _, err := e.CallPublicSymbol(ctx, "printMyClass", arg0) return err } diff --git a/examples/classes/main.go b/examples/classes/main.go index bca73b0..eb6b0ab 100644 --- a/examples/classes/main.go +++ b/examples/classes/main.go @@ -72,7 +72,7 @@ func main() { } // Create a new class. - newClassInstance, err := generated.NewClassMyClass(engine, ctx, 23, "test123") + newClassInstance, err := generated.NewClassMyClass2(engine, ctx, 23, "test123") if err != nil { log.Fatal(err) } @@ -82,7 +82,7 @@ func main() { log.Fatal(err) } - err = newClassInstance.SetX(ctx, 42) + err = newClassInstance.SetPropertyX(ctx, 42) if err != nil { log.Fatal(err) } @@ -92,7 +92,7 @@ func main() { log.Fatal(err) } - err = newClassInstance.IncrementX(ctx) + err = newClassInstance.IncrementX0(ctx) if err != nil { log.Fatal(err) } diff --git a/examples/classes/wasm/classes.cpp b/examples/classes/wasm/classes.cpp index ae99a04..2ddbcaf 100644 --- a/examples/classes/wasm/classes.cpp +++ b/examples/classes/wasm/classes.cpp @@ -9,10 +9,17 @@ class MyClass { , y(y) {} + MyClass(int x) + : x(x) + {} + void incrementX() { ++x; } + void incrementX(int multiplier) { + x = x + (1 * multiplier); + } int getX() const { return x; } void setX(int x_) { x = x_; } @@ -34,7 +41,9 @@ void printMyClass(MyClass input) { EMSCRIPTEN_BINDINGS(my_module) { class_("MyClass") .constructor() - .function("incrementX", &MyClass::incrementX) + .constructor() + .function("incrementX", select_overload(&MyClass::incrementX)) + .function("incrementX", select_overload(&MyClass::incrementX)) .property("x", &MyClass::getX, &MyClass::setX) .class_function("getStringFromInstance", &MyClass::getStringFromInstance) ; diff --git a/examples/classes/wasm/classes.wasm b/examples/classes/wasm/classes.wasm index 6a1843a..7484182 100755 Binary files a/examples/classes/wasm/classes.wasm and b/examples/classes/wasm/classes.wasm differ diff --git a/examples/enums-and-constants/generated/constants.go b/examples/enums-and-constants/generated/constants.go index ba0720e..a35f9ab 100644 --- a/examples/enums-and-constants/generated/constants.go +++ b/examples/enums-and-constants/generated/constants.go @@ -2,15 +2,27 @@ package generated const Constant_SOME_CONSTANT_1 = bool(false) + const Constant_SOME_CONSTANT_10 = uint16(10) + const Constant_SOME_CONSTANT_11 = uint8(11) + const Constant_SOME_CONSTANT_12 = uint32(12) + const Constant_SOME_CONSTANT_13 = string("TestWideString") + const Constant_SOME_CONSTANT_2 = float32(2) + const Constant_SOME_CONSTANT_3 = float64(3) + const Constant_SOME_CONSTANT_4 = int32(4) + const Constant_SOME_CONSTANT_5 = string("TestString") + const Constant_SOME_CONSTANT_6 = int8(67) + const Constant_SOME_CONSTANT_7 = int64(7) + const Constant_SOME_CONSTANT_8 = uint16(8) + const Constant_SOME_CONSTANT_9 = uint32(9) diff --git a/examples/enums-and-constants/generated/functions.go b/examples/enums-and-constants/generated/functions.go index a2ca9c1..1272643 100644 --- a/examples/enums-and-constants/generated/functions.go +++ b/examples/enums-and-constants/generated/functions.go @@ -12,5 +12,8 @@ func Enum_in_enum_out(e embind.Engine, ctx context.Context, arg0 EnumNewStyle) ( if err != nil { return EnumOldStyle(0), err } + if res == nil { + return EnumOldStyle(0), nil + } return res.(EnumOldStyle), nil } diff --git a/examples/hello-world/generated/functions.go b/examples/hello-world/generated/functions.go index 460f162..4db298f 100644 --- a/examples/hello-world/generated/functions.go +++ b/examples/hello-world/generated/functions.go @@ -7,6 +7,16 @@ import ( "github.com/jerbob92/wazero-emscripten-embind" ) +func Function_overload0(e embind.Engine, ctx context.Context) error { + _, err := e.CallPublicSymbol(ctx, "function_overload") + return err +} + +func Function_overload1(e embind.Engine, ctx context.Context, arg0 int32) error { + _, err := e.CallPublicSymbol(ctx, "function_overload", arg0) + return err +} + func Hello_world(e embind.Engine, ctx context.Context, arg0 string) error { _, err := e.CallPublicSymbol(ctx, "hello_world", arg0) return err diff --git a/examples/hello-world/wasm/hello_world.cpp b/examples/hello-world/wasm/hello_world.cpp index 7d4913f..b484076 100644 --- a/examples/hello-world/wasm/hello_world.cpp +++ b/examples/hello-world/wasm/hello_world.cpp @@ -6,6 +6,15 @@ void hello_world(std::string who) { printf("Hello world and %s!\n", who.c_str()); } +void function_overload() { +} + +void function_overload_2(int x) { +} + EMSCRIPTEN_BINDINGS(my_module) { function("hello_world", &hello_world); + + function("function_overload", &function_overload); + function("function_overload", &function_overload_2); } \ No newline at end of file diff --git a/examples/hello-world/wasm/hello_world.wasm b/examples/hello-world/wasm/hello_world.wasm index 02b0f62..1f185fb 100755 Binary files a/examples/hello-world/wasm/hello_world.wasm and b/examples/hello-world/wasm/hello_world.wasm differ diff --git a/generator/generator.go b/generator/generator/generator.go similarity index 57% rename from generator/generator.go rename to generator/generator/generator.go index 500c3ae..83dac28 100644 --- a/generator/generator.go +++ b/generator/generator/generator.go @@ -1,18 +1,18 @@ -package main +package generator import ( "bytes" "context" "embed" - "flag" "fmt" "go/format" "go/token" "log" "os" "path" - "path/filepath" + "reflect" "sort" + "strconv" "strings" "text/template" "unicode" @@ -29,46 +29,15 @@ var ( //go:embed templates/* templates embed.FS ) -var ( - packagePath string - fileName string - initFunction *string - wasm *string - verbose *bool -) - -func init() { - fileName = os.Getenv("GOFILE") - wasm = flag.String("wasm", "", "the wasm file to process") - initFunction = flag.String("init", "_initialize", "the function to execute to make Emscripten register the types") - verbose = flag.Bool("v", false, "enable verbose logging") -} - -func Usage() { - fmt.Fprintf(os.Stderr, "Usage of wazero-emscripten-embind/generator:\n") - fmt.Fprintf(os.Stderr, "TODO\n") -} - -func main() { - flag.Usage = Usage - flag.Parse() - - dir, err := filepath.Abs(".") - if err != nil { - panic(err) - } +func Generate(dir string, fileName string, wasm []byte, initFunction string) error { fset := token.NewFileSet() pkgs, err := packages.Load(&packages.Config{ Fset: fset, Mode: packages.NeedSyntax | packages.NeedName | packages.NeedModule | packages.NeedTypes | packages.NeedTypesInfo, }, fmt.Sprintf("file=%s", fileName)) if err != nil { - panic(err) - } - - if wasm == nil { - log.Fatal("No wasm file given") + return err } ctx := context.Background() @@ -77,23 +46,18 @@ func main() { defer r.Close(ctx) if _, err := wasi_snapshot_preview1.Instantiate(ctx, r); err != nil { - log.Fatal(err) + return err } - wasmData, err := os.ReadFile(*wasm) + compiledModule, err := r.CompileModule(ctx, wasm) if err != nil { - log.Fatal(err) - } - - compiledModule, err := r.CompileModule(ctx, wasmData) - if err != nil { - log.Fatal(err) + return err } builder := r.NewHostModuleBuilder("env") emscriptenExporter, err := emscripten.NewFunctionExporterForModule(compiledModule) if err != nil { - log.Fatal(err) + return err } emscriptenExporter.ExportFunctions(builder) @@ -103,12 +67,12 @@ func main() { embindExporter := engine.NewFunctionExporterForModule(compiledModule) err = embindExporter.ExportFunctions(builder) if err != nil { - log.Fatal(err) + return err } _, err = builder.Instantiate(ctx) if err != nil { - log.Fatal(err) + return err } moduleConfig := wazero.NewModuleConfig(). @@ -117,17 +81,17 @@ func main() { mod, err := r.InstantiateModule(ctx, compiledModule, moduleConfig) if err != nil { - log.Fatal(err) + return err } - initFunc := mod.ExportedFunction(*initFunction) + initFunc := mod.ExportedFunction(initFunction) if initFunc == nil { - log.Fatalf("init function %s does not exist", *initFunction) + log.Fatalf("init function %s does not exist", initFunction) } res, err := initFunc.Call(ctx) if res != nil { - log.Fatal(fmt.Errorf("could not call init function %w", err)) + return fmt.Errorf("could not call init function %w", err) } packageName := pkgs[0].Name @@ -157,11 +121,14 @@ func main() { return upperFirst } - typeNameToGeneratedName := func(name string, isClass, isEnum bool) string { + typeNameToGeneratedName := func(name string, isClass, isEnum, isArgument bool) string { if isClass { name = strings.TrimPrefix(name, "*") name = "Class" + generateGoName(name) name = "*" + name + if isArgument { + name = "embind.ClassBase" + } } else if isEnum { name = "Enum" + generateGoName(name) } @@ -170,7 +137,7 @@ func main() { } typeNameToErrorValue := func(name string, isClass, isEnum bool) string { - convertedName := typeNameToGeneratedName(name, isClass, isEnum) + convertedName := typeNameToGeneratedName(name, isClass, isEnum, false) if isClass || convertedName == "any" || strings.HasPrefix(convertedName, "[]") || strings.HasPrefix(convertedName, "map[") { return "nil" } @@ -189,17 +156,31 @@ func main() { constants := engine.GetConstants() for i := range constants { + constantValue := constants[i].Value() + formattedConstantValue := fmt.Sprintf("%#v", constantValue) + constant := TemplateConstant{ - Name: constants[i].Name(), - GoName: "Constant_" + constants[i].Name(), - Value: fmt.Sprintf("%v", constants[i].Value()), - GoType: typeNameToGeneratedName(constants[i].Type().Type(), constants[i].Type().IsClass(), constants[i].Type().IsEnum()), - ValuePrefix: "(", - ValueSuffix: ")", + Name: constants[i].Name(), + GoName: "Constant_" + constants[i].Name(), + Value: formattedConstantValue, + CanBeConstant: true, + GoType: typeNameToGeneratedName(constants[i].Type().Type(), constants[i].Type().IsClass(), constants[i].Type().IsEnum(), false), + ValuePrefix: "(", + ValueSuffix: ")", } - if constant.GoType == "string" { - constant.Value = "\"" + constant.Value + "\"" + if constantValue != nil { + typeOfConstant := reflect.TypeOf(constantValue) + switch typeOfConstant.Kind() { + case reflect.Map, reflect.Pointer, reflect.Struct, reflect.Slice, + reflect.Array, reflect.UnsafePointer, reflect.Chan: + constant.CanBeConstant = false + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, + reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, + reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64: + // Pretty print numbers + constant.Value = fmt.Sprintf("%v", constantValue) + } } data.Constants = append(data.Constants, constant) @@ -214,30 +195,55 @@ func main() { exposedArgumentTypes := symbols[i].ArgumentTypes() argumentTypes := make([]string, len(exposedArgumentTypes)) for i := range exposedArgumentTypes { - argumentTypes[i] = typeNameToGeneratedName(exposedArgumentTypes[i].Type(), exposedArgumentTypes[i].IsClass(), exposedArgumentTypes[i].IsEnum()) + argumentTypes[i] = typeNameToGeneratedName(exposedArgumentTypes[i].Type(), exposedArgumentTypes[i].IsClass(), exposedArgumentTypes[i].IsEnum(), true) + } + + goName := generateGoName(symbols[i].Symbol()) + if symbols[i].IsOverload() && symbols[i].OverloadCount() > 1 { + goName += strconv.Itoa(len(argumentTypes)) } symbol := TemplateSymbol{ Symbol: symbols[i].Symbol(), - GoName: generateGoName(symbols[i].Symbol()), + GoName: goName, ArgumentTypes: argumentTypes, - ReturnType: typeNameToGeneratedName(symbols[i].ReturnType().Type(), symbols[i].ReturnType().IsClass(), symbols[i].ReturnType().IsEnum()), - ErrorValue: typeNameToErrorValue(symbols[i].ReturnType().Type(), symbols[i].ReturnType().IsClass(), symbols[i].ReturnType().IsEnum()), + ReturnType: "any", + ErrorValue: "nil", + } + + returnType := symbols[i].ReturnType() + if returnType != nil { + symbol.ReturnType = typeNameToGeneratedName(returnType.Type(), returnType.IsClass(), returnType.IsEnum(), true) + symbol.ErrorValue = typeNameToErrorValue(returnType.Type(), returnType.IsClass(), returnType.IsEnum()) } data.Symbols = append(data.Symbols, symbol) } sort.Slice(data.Symbols, func(i, j int) bool { + if data.Symbols[i].GoName == data.Symbols[j].GoName { + return data.Symbols[i].Symbol < data.Symbols[j].Symbol + } return data.Symbols[i].GoName < data.Symbols[j].GoName }) + // Prevent duplicate names. + seenNames := map[string]bool{} + for i := range data.Symbols { + _, ok := seenNames[data.Symbols[i].GoName] + if ok { + data.Symbols[i].GoName += "_" + } + + seenNames[data.Symbols[i].GoName] = true + } + enums := engine.GetEnums() for i := range enums { enum := TemplateEnum{ Name: enums[i].Name(), GoName: "Enum" + generateGoName(enums[i].Name()), - GoType: typeNameToGeneratedName(enums[i].Type().Type(), enums[i].Type().IsClass(), enums[i].Type().IsEnum()), + GoType: typeNameToGeneratedName(enums[i].Type().Type(), enums[i].Type().IsClass(), enums[i].Type().IsEnum(), false), Values: []TemplateEnumValue{}, } @@ -250,6 +256,10 @@ func main() { }) } + sort.Slice(enum.Values, func(i, j int) bool { + return enum.Values[i].GoName < enum.Values[j].GoName + }) + data.Enums = append(data.Enums, enum) } @@ -270,7 +280,7 @@ func main() { exposedArgumentTypes := constructors[ci].ArgumentTypes() argumentTypes := make([]string, len(exposedArgumentTypes)) for i := range exposedArgumentTypes { - argumentTypes[i] = typeNameToGeneratedName(exposedArgumentTypes[i].Type(), exposedArgumentTypes[i].IsClass(), exposedArgumentTypes[i].IsEnum()) + argumentTypes[i] = typeNameToGeneratedName(exposedArgumentTypes[i].Type(), exposedArgumentTypes[i].IsClass(), exposedArgumentTypes[i].IsEnum(), true) } constructor := TemplateClassConstructor{ @@ -291,12 +301,23 @@ func main() { Name: properties[pi].Name(), GoName: generateGoName(properties[pi].Name()), ReadOnly: properties[pi].ReadOnly(), - GetterType: typeNameToGeneratedName(properties[pi].GetterType().Type(), properties[pi].GetterType().IsClass(), properties[pi].GetterType().IsEnum()), - ErrorValue: typeNameToErrorValue(properties[pi].GetterType().Type(), properties[pi].GetterType().IsClass(), properties[pi].GetterType().IsEnum()), + GetterType: "any", + ErrorValue: "nil", + } + + getterType := properties[pi].GetterType() + if getterType != nil { + property.GetterType = typeNameToGeneratedName(getterType.Type(), getterType.IsClass(), getterType.IsEnum(), true) + property.ErrorValue = typeNameToErrorValue(getterType.Type(), getterType.IsClass(), getterType.IsEnum()) } if !property.ReadOnly { - property.SetterType = typeNameToGeneratedName(properties[pi].SetterType().Type(), properties[pi].SetterType().IsClass(), properties[pi].SetterType().IsEnum()) + setterType := properties[pi].SetterType() + if setterType != nil { + property.SetterType = typeNameToGeneratedName(setterType.Type(), setterType.IsClass(), setterType.IsEnum(), true) + } else { + property.SetterType = "any" + } } class.Properties = append(class.Properties, property) @@ -306,20 +327,63 @@ func main() { return class.Properties[i].GoName < class.Properties[j].GoName }) + staticProperties := classes[i].StaticProperties() + for pi := range staticProperties { + property := TemplateClassProperty{ + Name: staticProperties[pi].Name(), + GoName: generateGoName(staticProperties[pi].Name()), + ReadOnly: staticProperties[pi].ReadOnly(), + GetterType: "any", + ErrorValue: "nil", + } + + getterType := staticProperties[pi].GetterType() + if getterType != nil { + property.GetterType = typeNameToGeneratedName(getterType.Type(), getterType.IsClass(), getterType.IsEnum(), true) + property.ErrorValue = typeNameToErrorValue(getterType.Type(), getterType.IsClass(), getterType.IsEnum()) + } + + if !property.ReadOnly { + setterType := staticProperties[pi].SetterType() + if setterType != nil { + property.SetterType = typeNameToGeneratedName(setterType.Type(), setterType.IsClass(), setterType.IsEnum(), true) + } else { + property.SetterType = "any" + } + } + + class.StaticProperties = append(class.StaticProperties, property) + } + + sort.Slice(class.StaticProperties, func(i, j int) bool { + return class.StaticProperties[i].GoName < class.StaticProperties[j].GoName + }) + methods := classes[i].Methods() for mi := range methods { exposedArgumentTypes := methods[mi].ArgumentTypes() argumentTypes := make([]string, len(exposedArgumentTypes)) for i := range exposedArgumentTypes { - argumentTypes[i] = typeNameToGeneratedName(exposedArgumentTypes[i].Type(), exposedArgumentTypes[i].IsClass(), exposedArgumentTypes[i].IsEnum()) + argumentTypes[i] = typeNameToGeneratedName(exposedArgumentTypes[i].Type(), exposedArgumentTypes[i].IsClass(), exposedArgumentTypes[i].IsEnum(), true) + } + + goName := generateGoName(methods[mi].Symbol()) + if methods[mi].IsOverload() && methods[mi].OverloadCount() > 1 { + goName += strconv.Itoa(len(argumentTypes)) } method := TemplateClassMethod{ Name: methods[mi].Symbol(), - GoName: generateGoName(methods[mi].Symbol()), + GoName: goName, ArgumentTypes: argumentTypes, - ReturnType: typeNameToGeneratedName(methods[mi].ReturnType().Type(), methods[mi].ReturnType().IsClass(), methods[mi].ReturnType().IsEnum()), - ErrorValue: typeNameToErrorValue(methods[mi].ReturnType().Type(), methods[mi].ReturnType().IsClass(), methods[mi].ReturnType().IsEnum()), + ReturnType: "any", + ErrorValue: "nil", + } + + returnType := methods[mi].ReturnType() + if returnType != nil { + method.ReturnType = typeNameToGeneratedName(returnType.Type(), returnType.IsClass(), returnType.IsEnum(), true) + method.ErrorValue = typeNameToErrorValue(returnType.Type(), returnType.IsClass(), returnType.IsEnum()) } class.Methods = append(class.Methods, method) @@ -334,15 +398,26 @@ func main() { exposedArgumentTypes := staticMethods[smi].ArgumentTypes() argumentTypes := make([]string, len(exposedArgumentTypes)) for i := range exposedArgumentTypes { - argumentTypes[i] = typeNameToGeneratedName(exposedArgumentTypes[i].Type(), exposedArgumentTypes[i].IsClass(), exposedArgumentTypes[i].IsEnum()) + argumentTypes[i] = typeNameToGeneratedName(exposedArgumentTypes[i].Type(), exposedArgumentTypes[i].IsClass(), exposedArgumentTypes[i].IsEnum(), true) + } + + goName := generateGoName(staticMethods[smi].Symbol()) + if staticMethods[smi].IsOverload() && staticMethods[smi].OverloadCount() > 1 { + goName += strconv.Itoa(len(argumentTypes)) } method := TemplateClassMethod{ Name: staticMethods[smi].Symbol(), - GoName: generateGoName(staticMethods[smi].Symbol()), + GoName: goName, ArgumentTypes: argumentTypes, - ReturnType: typeNameToGeneratedName(staticMethods[smi].ReturnType().Type(), staticMethods[smi].ReturnType().IsClass(), staticMethods[smi].ReturnType().IsEnum()), - ErrorValue: typeNameToErrorValue(staticMethods[smi].ReturnType().Type(), staticMethods[smi].ReturnType().IsClass(), staticMethods[smi].ReturnType().IsEnum()), + ReturnType: "any", + ErrorValue: "nil", + } + + returnType := staticMethods[smi].ReturnType() + if returnType != nil { + method.ReturnType = typeNameToGeneratedName(returnType.Type(), returnType.IsClass(), returnType.IsEnum(), true) + method.ErrorValue = typeNameToErrorValue(returnType.Type(), returnType.IsClass(), returnType.IsEnum()) } class.StaticMethods = append(class.StaticMethods, method) @@ -360,54 +435,73 @@ func main() { }) if len(data.Classes) > 0 { - ExecuteTemplate(templates, "classes.tmpl", path.Join(dir, "classes.go"), data) + err = ExecuteTemplate(templates, "classes.tmpl", path.Join(dir, "classes.go"), data) + if err != nil { + return err + } } else { _ = os.Remove(path.Join(dir, "classes.go")) } if len(data.Constants) > 0 { - ExecuteTemplate(templates, "constants.tmpl", path.Join(dir, "constants.go"), data) + err = ExecuteTemplate(templates, "constants.tmpl", path.Join(dir, "constants.go"), data) + if err != nil { + return err + } } else { _ = os.Remove(path.Join(dir, "constants.go")) } if len(data.Symbols) > 0 { - ExecuteTemplate(templates, "functions.tmpl", path.Join(dir, "functions.go"), data) + err = ExecuteTemplate(templates, "functions.tmpl", path.Join(dir, "functions.go"), data) + if err != nil { + return err + } } else { _ = os.Remove(path.Join(dir, "functions.go")) } if len(data.Enums) > 0 { - ExecuteTemplate(templates, "enums.tmpl", path.Join(dir, "enums.go"), data) + err = ExecuteTemplate(templates, "enums.tmpl", path.Join(dir, "enums.go"), data) + if err != nil { + return err + } } else { _ = os.Remove(path.Join(dir, "enums.go")) } - ExecuteTemplate(templates, "engine.tmpl", path.Join(dir, "engine.go"), data) + + err = ExecuteTemplate(templates, "engine.tmpl", path.Join(dir, "engine.go"), data) + if err != nil { + return err + } + + return nil } var TemplateFunctions = template.FuncMap{ "lower": strings.ToLower, } -func ExecuteTemplate(tmpl *template.Template, name string, path string, data TemplateData) { +func ExecuteTemplate(tmpl *template.Template, name string, path string, data TemplateData) error { writer := bytes.NewBuffer(nil) err := tmpl.ExecuteTemplate(writer, name, data) if err != nil { - panic(err) + return err } fileBytes := writer.Bytes() formattedSource, err := format.Source(fileBytes) if err != nil { - panic(err) + return fmt.Errorf("could not format %s: %w\nsource:\n%s", name, err, fileBytes) } fileWriter, err := os.Create(path) if err != nil { - panic(err) + return err } defer fileWriter.Close() _, err = fileWriter.Write(formattedSource) if err != nil { - panic(err) + return err } + return nil } type TemplateData struct { @@ -420,12 +514,13 @@ type TemplateData struct { } type TemplateConstant struct { - Name string - GoName string - Value string - GoType string - ValuePrefix string - ValueSuffix string + Name string + GoName string + Value string + GoType string + ValuePrefix string + ValueSuffix string + CanBeConstant bool } type TemplateEnum struct { @@ -442,12 +537,13 @@ type TemplateEnumValue struct { } type TemplateClass struct { - Name string - GoName string - Constructors []TemplateClassConstructor - Properties []TemplateClassProperty - Methods []TemplateClassMethod - StaticMethods []TemplateClassMethod + Name string + GoName string + Constructors []TemplateClassConstructor + Properties []TemplateClassProperty + StaticProperties []TemplateClassProperty + Methods []TemplateClassMethod + StaticMethods []TemplateClassMethod } type TemplateClassProperty struct { diff --git a/generator/generator/templates/classes.tmpl b/generator/generator/templates/classes.tmpl new file mode 100644 index 0000000..6ce394c --- /dev/null +++ b/generator/generator/templates/classes.tmpl @@ -0,0 +1,179 @@ +// Code generated by wazero-emscripten-embind, DO NOT EDIT. +package {{ $.Pkg }} + +import ( + "context" + + "github.com/jerbob92/wazero-emscripten-embind" +) + +{{ range $index, $class := $.Classes }} +type {{ $class.GoName }} struct { + embind.ClassBase +} + +func (class *{{ $class.GoName }}) Clone(ctx context.Context) (*{{ $class.GoName }}, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*{{ $class.GoName }}), nil +} + +func (class *{{ $class.GoName }}) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *{{ $class.GoName }}) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *{{ $class.GoName }}) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *{{ $class.GoName }}) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *{{ $class.GoName }}) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *{{ $class.GoName }}) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *{{ $class.GoName }}) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +{{ range $index, $property := $class.Properties }} +func (class *{{ $class.GoName }}) GetProperty{{ $property.GoName }}(ctx context.Context) ({{ $property.GetterType }}, error) { + res, err := class.GetProperty(ctx, "{{ $property.Name }}") + if err != nil { + return {{ $property.ErrorValue }}, err + } + + if res == nil { + return {{ $property.ErrorValue }}, nil + } + + return res.({{ $property.GetterType }}), nil +} +{{ if not ($property.ReadOnly) -}} +func (class *{{ $class.GoName }}) SetProperty{{ $property.GoName }}(ctx context.Context, val {{ $property.SetterType }}) error { + return class.SetProperty(ctx, "{{ $property.Name }}", val) +} +{{ end }} +{{ end }} +{{ range $index, $method := $class.Methods }} +{{ if $method.ReturnType }} +func (class *{{ $class.GoName }}) {{ $method.GoName }}(ctx context.Context{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }} {{ $argumentType }}{{ end }}) ({{ $method.ReturnType }}, error) { + res, err := class.CallMethod(ctx, "{{ $method.Name }}"{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }}{{ end }}) + if err != nil { + return {{ $method.ErrorValue }}, err + } + + if res == nil { + return {{ $method.ErrorValue }}, nil + } + + return res.({{ $method.ReturnType }}), nil +} +{{ else }} +func (class *{{ $class.GoName }}) {{ $method.GoName }}(ctx context.Context{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }} {{ $argumentType }}{{ end }}) error { + _, err := class.CallMethod(ctx, "{{ $method.Name }}"{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }}{{ end }}) + return err +} +{{ end }} +{{ end }} +{{ range $index, $method := $class.StaticMethods }} +{{ if $method.ReturnType }} +func (class *{{ $class.GoName }}) Static{{ $method.GoName }}(ctx context.Context{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }} {{ $argumentType }}{{ end }}) ({{ $method.ReturnType }}, error) { + res, err := class.CallInstanceMethod(ctx, nil, "{{ $method.Name }}"{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }}{{ end }}) + if err != nil { + return {{ $method.ErrorValue }}, err + } + + if res == nil { + return {{ $method.ErrorValue }}, nil + } + + return res.({{ $method.ReturnType }}), nil +} +func {{ $class.GoName }}Static{{ $method.GoName }}(e embind.Engine, ctx context.Context{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }} {{ $argumentType }}{{ end }}) ({{ $method.ReturnType }}, error) { + res, err := e.CallStaticClassMethod(ctx, "{{ $class.Name }}", "{{ $method.Name }}"{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }}{{ end }}) + if err != nil { + return {{ $method.ErrorValue }}, err + } + + if res == nil { + return {{ $method.ErrorValue }}, nil + } + + return res.({{ $method.ReturnType }}), nil +} +{{ else }} +func (class *{{ $class.GoName }}) Static{{ $method.GoName }}(ctx context.Context{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }} {{ $argumentType }}{{ end }}) error { + _, err := class.CallInstanceMethod(ctx, nil, "{{ $method.Name }}"{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }}{{ end }}) + return err +} +func {{ $class.GoName }}Static{{ $method.GoName }}(e embind.Engine, ctx context.Context{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }} {{ $argumentType }}{{ end }}) error { + _, err := e.CallStaticClassMethod(ctx, "{{ $class.Name }}", "{{ $method.Name }}"{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }}{{ end }}) + return err +} +{{ end }} +{{ end }} +{{ range $index, $property := $class.StaticProperties }} +func (class *{{ $class.GoName }}) GetStaticProperty{{ $property.GoName }}(ctx context.Context) ({{ $property.GetterType }}, error) { + res, err := class.GetInstanceProperty(ctx, nil, "{{ $property.Name }}") + if err != nil { + return {{ $property.ErrorValue }}, err + } + + if res == nil { + return {{ $property.ErrorValue }}, nil + } + + return res.({{ $property.GetterType }}), nil +} +func {{ $class.GoName }}GetStaticProperty{{ $property.GoName }}(e embind.Engine, ctx context.Context) ({{ $property.GetterType }}, error) { + res, err := e.GetStaticClassProperty(ctx, "{{ $class.Name }}", "{{ $property.Name }}") + if err != nil { + return {{ $property.ErrorValue }}, err + } + + if res == nil { + return {{ $property.ErrorValue }}, nil + } + + return res.({{ $property.GetterType }}), nil +} +{{ if not ($property.ReadOnly) -}} +func (class *{{ $class.GoName }}) SetStaticProperty{{ $property.GoName }}(ctx context.Context, val {{ $property.SetterType }}) error { + return class.SetInstanceProperty(ctx, nil, "{{ $property.Name }}", val) +} +func {{ $class.GoName }}SetStaticProperty{{ $property.GoName }}(e embind.Engine, ctx context.Context, val {{ $property.SetterType }}) error { + return e.SetStaticClassProperty(ctx, "{{ $class.Name }}", "{{ $property.Name }}", val) +} +{{ end }} +{{ end }} +{{ range $index, $constructor := $class.Constructors }} +func New{{ $class.GoName }}{{ $constructor.Name }}(e embind.Engine, ctx context.Context{{ range $index, $argumentType := $constructor.ArgumentTypes -}}, arg{{ $index }} {{ $argumentType }}{{ end }}) (*{{ $class.GoName }}, error) { + res, err := e.CallPublicSymbol(ctx, "{{ $class.Name }}"{{ range $index, $argumentType := $constructor.ArgumentTypes -}}, arg{{ $index }}{{ end }}) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*{{ $class.GoName }}), nil +} +{{ end }} +{{ end }} diff --git a/generator/templates/constants.tmpl b/generator/generator/templates/constants.tmpl similarity index 63% rename from generator/templates/constants.tmpl rename to generator/generator/templates/constants.tmpl index a7d7436..a1a6648 100644 --- a/generator/templates/constants.tmpl +++ b/generator/generator/templates/constants.tmpl @@ -2,5 +2,9 @@ package {{ $.Pkg }} {{ range $index, $constant := $.Constants -}} +{{ if $constant.CanBeConstant }} const {{ $constant.GoName }} = {{ $constant.GoType }}{{ $constant.ValuePrefix }}{{ $constant.Value }}{{ $constant.ValueSuffix }} +{{ else }} +var {{ $constant.GoName }} = {{ $constant.Value }} // Not all types can be actual constants in Go. +{{ end }} {{ end }} \ No newline at end of file diff --git a/generator/templates/engine.tmpl b/generator/generator/templates/engine.tmpl similarity index 100% rename from generator/templates/engine.tmpl rename to generator/generator/templates/engine.tmpl diff --git a/generator/templates/enums.tmpl b/generator/generator/templates/enums.tmpl similarity index 100% rename from generator/templates/enums.tmpl rename to generator/generator/templates/enums.tmpl diff --git a/generator/templates/functions.tmpl b/generator/generator/templates/functions.tmpl similarity index 93% rename from generator/templates/functions.tmpl rename to generator/generator/templates/functions.tmpl index c312159..278677b 100644 --- a/generator/templates/functions.tmpl +++ b/generator/generator/templates/functions.tmpl @@ -13,6 +13,9 @@ func {{ $symbol.GoName }}(e embind.Engine, ctx context.Context{{ range $index, $ if err != nil { return {{ $symbol.ErrorValue }}, err } + if res == nil { + return {{ $symbol.ErrorValue }}, nil + } return res.({{ $symbol.ReturnType }}), nil } {{- else }} diff --git a/generator/main.go b/generator/main.go new file mode 100644 index 0000000..84dfc92 --- /dev/null +++ b/generator/main.go @@ -0,0 +1,55 @@ +package main + +import ( + "flag" + "fmt" + "log" + "os" + "path/filepath" + + "github.com/jerbob92/wazero-emscripten-embind/generator/generator" +) + +var ( + packagePath string + fileName string + initFunction *string + wasm *string + verbose *bool +) + +func init() { + fileName = os.Getenv("GOFILE") + wasm = flag.String("wasm", "", "the wasm file to process") + initFunction = flag.String("init", "_initialize", "the function to execute to make Emscripten register the types") + verbose = flag.Bool("v", false, "enable verbose logging") +} + +func Usage() { + fmt.Fprintf(os.Stderr, "Usage of wazero-emscripten-embind/generator:\n") + fmt.Fprintf(os.Stderr, "TODO\n") +} + +func main() { + flag.Usage = Usage + flag.Parse() + + dir, err := filepath.Abs(".") + if err != nil { + panic(err) + } + + if wasm == nil { + log.Fatal("No wasm file given") + } + + wasmData, err := os.ReadFile(*wasm) + if err != nil { + log.Fatal(err) + } + + err = generator.Generate(dir, fileName, wasmData, *initFunction) + if err != nil { + log.Fatal(err) + } +} diff --git a/generator/templates/classes.tmpl b/generator/templates/classes.tmpl deleted file mode 100644 index 46587c5..0000000 --- a/generator/templates/classes.tmpl +++ /dev/null @@ -1,73 +0,0 @@ -// Code generated by wazero-emscripten-embind, DO NOT EDIT. -package {{ $.Pkg }} - -import ( - "context" - - "github.com/jerbob92/wazero-emscripten-embind" -) - -{{ range $index, $class := $.Classes }} -type {{ $class.GoName }} struct { - embind.ClassBase -} -{{ range $index, $property := $class.Properties }} -func (class *{{ $class.GoName }}) Get{{ $property.GoName }}(ctx context.Context) ({{ $property.GetterType }}, error) { - res, err := class.GetProperty(ctx, class, "{{ $property.Name }}") - if err != nil { - return {{ $property.ErrorValue }}, err - } - - return res.({{ $property.GetterType }}), nil -} -{{ if not ($property.ReadOnly) -}} -func (class *{{ $class.GoName }}) Set{{ $property.GoName }}(ctx context.Context, val {{ $property.SetterType }}) error { - return class.SetProperty(ctx, class, "{{ $property.Name }}", val) -} -{{ end }} -{{ end }} -{{ range $index, $method := $class.Methods }} -{{ if $method.ReturnType }} -func (class *{{ $class.GoName }}) {{ $method.GoName }}(ctx context.Context{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }} {{ $argumentType }}{{ end }}) ({{ $method.ReturnType }}, error) { - res, err := class.CallMethod(ctx, class, "{{ $method.Name }}"{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }}{{ end }}) - if err != nil { - return {{ $method.ErrorValue }}, err - } - - return res.({{ $method.ReturnType }}), nil -} -{{ else }} -func (class *{{ $class.GoName }}) {{ $method.GoName }}(ctx context.Context{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }} {{ $argumentType }}{{ end }}) error { - _, err := class.CallMethod(ctx, class, "{{ $method.Name }}"{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }}{{ end }}) - return err -} -{{ end }} -{{ end }} -{{ range $index, $method := $class.StaticMethods }} -{{ if $method.ReturnType }} -func {{ $class.GoName }}Static{{ $method.GoName }}(e embind.Engine, ctx context.Context{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }} {{ $argumentType }}{{ end }}) ({{ $method.ReturnType }}, error) { - res, err := e.CallStaticClassMethod(ctx, "{{ $class.Name }}", "{{ $method.Name }}"{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }}{{ end }}) - if err != nil { - return {{ $method.ErrorValue }}, err - } - - return res.({{ $method.ReturnType }}), nil -} -{{ else }} -func {{ $class.GoName }}Static{{ $method.GoName }}(e embind.Engine, ctx context.Context{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }} {{ $argumentType }}{{ end }}) error { - _, err := e.CallStaticClassMethod(ctx, "{{ $class.Name }}", "{{ $method.Name }}"{{ range $index, $argumentType := $method.ArgumentTypes -}}, arg{{ $index }}{{ end }}) - return err -} -{{ end }} -{{ end }} -{{ range $index, $constructor := $class.Constructors }} -func New{{ $class.GoName }}{{ $constructor.Name }}(e embind.Engine, ctx context.Context{{ range $index, $argumentType := $constructor.ArgumentTypes -}}, arg{{ $index }} {{ $argumentType }}{{ end }}) (*{{ $class.GoName }}, error) { - res, err := e.CallPublicSymbol(ctx, "{{ $class.Name }}"{{ range $index, $argumentType := $constructor.ArgumentTypes -}}, arg{{ $index }}{{ end }}) - if err != nil { - return nil, err - } - - return res.(*{{ $class.GoName }}), nil -} -{{ end }} -{{ end }} diff --git a/go.mod b/go.mod index 0178dab..4f89084 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,20 @@ module github.com/jerbob92/wazero-emscripten-embind go 1.19 require ( + github.com/onsi/ginkgo/v2 v2.12.0 + github.com/onsi/gomega v1.27.10 github.com/tetratelabs/wazero v1.5.0 golang.org/x/text v0.13.0 golang.org/x/tools v0.13.0 ) require ( + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect golang.org/x/mod v0.12.0 // indirect + golang.org/x/net v0.15.0 // indirect golang.org/x/sys v0.12.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 3776039..42b1258 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,45 @@ +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/onsi/ginkgo/v2 v2.12.0 h1:UIVDowFPwpg6yMUpPjGkYvf06K3RAiJXUhCxEwQVHRI= +github.com/onsi/ginkgo/v2 v2.12.0/go.mod h1:ZNEzXISYlqpb8S36iN71ifqLi3vVD1rVJGvWRCJOUpQ= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tetratelabs/wazero v1.5.0 h1:Yz3fZHivfDiZFUXnWMPUoiW7s8tC1sjdBtlJn08qYa0= github.com/tetratelabs/wazero v1.5.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/any.go b/internal/any.go new file mode 100644 index 0000000..fed042b --- /dev/null +++ b/internal/any.go @@ -0,0 +1,31 @@ +package embind + +import ( + "context" + "fmt" + "github.com/tetratelabs/wazero/api" +) + +type anyType struct { + baseType +} + +func (at *anyType) FromWireType(ctx context.Context, mod api.Module, ptr uint64) (any, error) { + return nil, fmt.Errorf("FromWireType on anyType should never be called") +} + +func (at *anyType) ToWireType(ctx context.Context, mod api.Module, destructors *[]*destructorFunc, o any) (uint64, error) { + return 0, fmt.Errorf("ToWireType on anyType should never be called") +} + +func (at *anyType) GoType() string { + return "any" +} + +func createAnyTypeArray(length int32) []registeredType { + anyTypeArray := make([]registeredType, length) + for i := range anyTypeArray { + anyTypeArray[i] = &anyType{} + } + return anyTypeArray +} diff --git a/internal/array.go b/internal/array.go index 887ec35..25c6cd4 100644 --- a/internal/array.go +++ b/internal/array.go @@ -3,7 +3,6 @@ package embind import ( "context" "fmt" - "github.com/tetratelabs/wazero/api" ) @@ -46,10 +45,10 @@ func (at *arrayType) ToWireType(ctx context.Context, mod api.Module, destructors return 0, err } - ptr := res[0] + ptr := api.DecodeU32(res[0]) for i := 0; i < at.elementsLength; i++ { - err = at.reg.elements[i].write(ctx, mod, api.DecodeI32(ptr), arr[i]) + err = at.reg.elements[i].write(ctx, mod, int32(ptr), arr[i]) if err != nil { return 0, err } @@ -57,13 +56,11 @@ func (at *arrayType) ToWireType(ctx context.Context, mod api.Module, destructors if destructors != nil { destructorsRef := *destructors - destructorsRef = append(destructorsRef, &destructorFunc{ - apiFunction: at.reg.rawDestructor, - args: []uint64{ptr}, - }) + destructorsRef = append(destructorsRef, at.DestructorFunction(ctx, mod, ptr)) *destructors = destructorsRef } - return ptr, nil + + return api.EncodeU32(ptr), nil } func (at *arrayType) ReadValueFromPointer(ctx context.Context, mod api.Module, pointer uint32) (any, error) { @@ -74,17 +71,152 @@ func (at *arrayType) ReadValueFromPointer(ctx context.Context, mod api.Module, p return at.FromWireType(ctx, mod, api.EncodeU32(ptr)) } -func (at *arrayType) HasDestructorFunction() bool { - return true +func (at *arrayType) DestructorFunctionUndefined() bool { + return false } -func (at *arrayType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) (*destructorFunc, error) { +func (at *arrayType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) *destructorFunc { return &destructorFunc{ apiFunction: at.reg.rawDestructor, args: []uint64{api.EncodeU32(pointer)}, - }, nil + } } func (at *arrayType) GoType() string { return "[]any" } + +func (at *arrayType) FromF64(o float64) uint64 { + return uint64(o) +} + +var RegisterValueArray = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + rawType := api.DecodeI32(stack[0]) + namePtr := api.DecodeI32(stack[1]) + constructorSignature := api.DecodeI32(stack[2]) + rawConstructor := api.DecodeI32(stack[3]) + destructorSignature := api.DecodeI32(stack[4]) + rawDestructor := api.DecodeI32(stack[5]) + + name, err := engine.readCString(uint32(namePtr)) + if err != nil { + panic(fmt.Errorf("could not read name: %w", err)) + } + + rawConstructorFunc, err := engine.newInvokeFunc(constructorSignature, rawConstructor, []api.ValueType{}, []api.ValueType{api.ValueTypeI32}) + if err != nil { + panic(fmt.Errorf("could not create rawConstructorFunc: %w", err)) + } + + rawDestructorFunc, err := engine.newInvokeFunc(destructorSignature, rawDestructor, []api.ValueType{api.ValueTypeI32}, []api.ValueType{}) + if err != nil { + panic(fmt.Errorf("could not create rawDestructorFunc: %w", err)) + } + + engine.registeredTuples[rawType] = ®isteredTuple{ + name: name, + rawConstructor: rawConstructorFunc, + rawDestructor: rawDestructorFunc, + elements: []*registeredTupleElement{}, + } +}) + +var RegisterValueArrayElement = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + rawTupleType := api.DecodeI32(stack[0]) + getterReturnType := api.DecodeI32(stack[1]) + getterSignature := api.DecodeI32(stack[2]) + getter := api.DecodeI32(stack[3]) + getterContext := api.DecodeI32(stack[4]) + setterArgumentType := api.DecodeI32(stack[5]) + setterSignature := api.DecodeI32(stack[6]) + setter := api.DecodeI32(stack[7]) + setterContext := api.DecodeI32(stack[8]) + + engine.registeredTuples[rawTupleType].elements = append(engine.registeredTuples[rawTupleType].elements, ®isteredTupleElement{ + getter: getter, + getterSignature: getterSignature, + getterReturnType: getterReturnType, + getterContext: getterContext, + setter: setter, + setterSignature: setterSignature, + setterArgumentType: setterArgumentType, + setterContext: setterContext, + }) +}) + +var FinalizeValueArray = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + rawTupleType := api.DecodeI32(stack[0]) + reg := engine.registeredTuples[rawTupleType] + delete(engine.registeredTuples, rawTupleType) + elements := reg.elements + elementsLength := len(elements) + + elementTypes := make([]int32, len(elements)*2) + for i := range elements { + elementTypes[i] = elements[i].getterReturnType + elementTypes[i+len(elements)] = elements[i].setterArgumentType + } + + err := engine.whenDependentTypesAreResolved([]int32{rawTupleType}, elementTypes, func(types []registeredType) ([]registeredType, error) { + for i := range elements { + element := elements[i] + getterReturnType := types[i] + + getterFunc, err := engine.newInvokeFunc(element.getterSignature, element.getter, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{getterReturnType.NativeType()}) + if err != nil { + return nil, fmt.Errorf("could not create getterFunc: %w", err) + } + + setterArgumentType := types[i+len(elements)] + setterFunc, err := engine.newInvokeFunc(element.setterSignature, element.setter, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, setterArgumentType.NativeType()}, []api.ValueType{}) + if err != nil { + return nil, fmt.Errorf("could not create setterFunc: %w", err) + } + + element.read = func(ctx context.Context, mod api.Module, ptr int32) (any, error) { + res, err := getterFunc.Call(ctx, api.EncodeI32(element.getterContext), api.EncodeI32(ptr)) + if err != nil { + return nil, err + } + return getterReturnType.FromWireType(ctx, mod, res[0]) + } + element.write = func(ctx context.Context, mod api.Module, ptr int32, o any) error { + destructors := &[]*destructorFunc{} + res, err := setterArgumentType.ToWireType(ctx, mod, destructors, o) + if err != nil { + return err + } + + _, err = setterFunc.Call(ctx, api.EncodeI32(element.setterContext), api.EncodeI32(ptr), res) + if err != nil { + return err + } + + err = engine.runDestructors(ctx, *destructors) + if err != nil { + return err + } + + return nil + } + } + + return []registeredType{ + &arrayType{ + baseType: baseType{ + rawType: rawTupleType, + name: reg.name, + argPackAdvance: 8, + }, + reg: reg, + elementsLength: elementsLength, + }, + }, nil + }) + if err != nil { + panic(fmt.Errorf("could not call whenDependentTypesAreResolved: %w", err)) + } +}) diff --git a/internal/bigint.go b/internal/bigint.go index 470d6ca..de8d589 100644 --- a/internal/bigint.go +++ b/internal/bigint.go @@ -3,6 +3,7 @@ package embind import ( "context" "fmt" + "strings" "github.com/tetratelabs/wazero/api" ) @@ -72,9 +73,36 @@ func (bt *bigintType) GoType() string { return "int64" } +func (bt *bigintType) DestructorFunctionUndefined() bool { + return false +} + func (bt *bigintType) FromF64(o float64) uint64 { if !bt.signed { return uint64(o) } return api.EncodeI64(int64(o)) } + +var RegisterBigInt = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + + rawType := api.DecodeI32(stack[0]) + name, err := engine.readCString(uint32(api.DecodeI32(stack[1]))) + if err != nil { + panic(fmt.Errorf("could not read name: %w", err)) + } + + err = engine.registerType(rawType, &bigintType{ + baseType: baseType{ + rawType: rawType, + name: name, + argPackAdvance: 8, + }, + size: api.DecodeI32(stack[2]), + signed: !strings.HasPrefix(name, "u"), + }, nil) + if err != nil { + panic(fmt.Errorf("could not register: %w", err)) + } +}) diff --git a/internal/bool.go b/internal/bool.go index 06984d1..dd8cbc2 100644 --- a/internal/bool.go +++ b/internal/bool.go @@ -4,6 +4,8 @@ import ( "context" "fmt" + "github.com/jerbob92/wazero-emscripten-embind/types" + "github.com/tetratelabs/wazero/api" ) @@ -21,7 +23,7 @@ func (bt *boolType) FromWireType(ctx context.Context, mod api.Module, value uint } func (bt *boolType) ToWireType(ctx context.Context, mod api.Module, destructors *[]*destructorFunc, o any) (uint64, error) { - if o == nil || o == undefined { + if o == nil || o == types.Undefined { return api.EncodeI32(bt.falseVal), nil } @@ -33,6 +35,14 @@ func (bt *boolType) ToWireType(ctx context.Context, mod api.Module, destructors return api.EncodeI32(bt.falseVal), nil } + stringVal, ok := o.(string) + if ok { + if stringVal != "" { + return api.EncodeI32(bt.trueVal), nil + } + return api.EncodeI32(bt.falseVal), nil + } + // Float64 is big enough for any number. numberVal := float64(0) hasNumberVal := false @@ -106,3 +116,48 @@ func (bt *boolType) ReadValueFromPointer(ctx context.Context, mod api.Module, po func (bt *boolType) GoType() string { return "bool" } + +func (bt *boolType) DestructorFunctionUndefined() bool { + return false +} + +var RegisterBool = func(hasSize bool) api.GoModuleFunc { + return api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + + rawType := api.DecodeI32(stack[0]) + + name, err := engine.readCString(uint32(api.DecodeI32(stack[1]))) + if err != nil { + panic(fmt.Errorf("could not read name: %w", err)) + } + + var size, trueVal, falseVal int32 + + // Since Emscripten 3.1.45, the size of the boolean is put to 1, while + // before the size was part of the registration. + if hasSize { + size = api.DecodeI32(stack[2]) + trueVal = api.DecodeI32(stack[3]) + falseVal = api.DecodeI32(stack[4]) + } else { + size = int32(1) + trueVal = api.DecodeI32(stack[2]) + falseVal = api.DecodeI32(stack[3]) + } + + err = engine.registerType(rawType, &boolType{ + baseType: baseType{ + rawType: rawType, + name: name, + argPackAdvance: 8, + }, + size: size, + trueVal: trueVal, + falseVal: falseVal, + }, nil) + if err != nil { + panic(fmt.Errorf("could not register: %w", err)) + } + }) +} diff --git a/internal/class.go b/internal/class.go index 529f2fb..97baa0d 100644 --- a/internal/class.go +++ b/internal/class.go @@ -4,6 +4,9 @@ import ( "context" "fmt" "reflect" + "sort" + "strconv" + "strings" "github.com/tetratelabs/wazero/api" ) @@ -13,6 +16,7 @@ type classProperty struct { enumerable bool configurable bool readOnly bool + isStatic bool setterType registeredType getterType registeredType set func(ctx context.Context, this any, v any) error @@ -24,12 +28,18 @@ func (cp *classProperty) Name() string { } func (cp *classProperty) GetterType() IType { + if cp.getterType == nil { + return nil + } return &exposedType{ registeredType: cp.getterType, } } func (cp *classProperty) SetterType() IType { + if cp.setterType == nil { + return nil + } return &exposedType{ registeredType: cp.setterType, } @@ -39,6 +49,10 @@ func (cp *classProperty) ReadOnly() bool { return cp.readOnly } +func (cp *classProperty) Static() bool { + return cp.isStatic +} + type classConstructor struct { fn publicSymbolFn argumentTypes []registeredType @@ -100,11 +114,11 @@ func (erc *classType) validate() error { return nil } -func (erc *classType) isDeleted(handle IClassBase) bool { +func (erc *classType) isDeleted(ctx context.Context, handle IClassBase) bool { return handle.getRegisteredPtrTypeRecord().ptr == 0 } -func (erc *classType) deleteLater(handle IClassBase) (any, error) { +func (erc *classType) deleteLater(ctx context.Context, handle IClassBase) (IClassBase, error) { registeredPtrTypeRecord := handle.getRegisteredPtrTypeRecord() if registeredPtrTypeRecord.ptr == 0 { return nil, fmt.Errorf("class handle already deleted") @@ -114,13 +128,17 @@ func (erc *classType) deleteLater(handle IClassBase) (any, error) { return nil, fmt.Errorf("object already scheduled for deletion") } - // @todo: implement me. - /* - deletionQueue.push(this); - if (deletionQueue.length === 1 && delayFunction) { - delayFunction(flushPendingDeletes); - } - */ + e := MustGetEngineFromContext(ctx, nil).(*engine) + e.deletionQueue = append(e.deletionQueue, handle) + + if len(e.deletionQueue) == 1 && e.delayFunction != nil { + err := e.delayFunction(func(ctx context.Context) error { + return e.FlushPendingDeletes(ctx) + }) + if err != nil { + return nil, err + } + } registeredPtrTypeRecord.deleteScheduled = true @@ -154,7 +172,7 @@ func (erc *classType) isAliasOf(ctx context.Context, first, second IClassBase) ( return leftClass == rightClass && left == right, nil } -func (erc *classType) clone(from IClassBase) (IClassBase, error) { +func (erc *classType) clone(ctx context.Context, from IClassBase) (IClassBase, error) { registeredPtrTypeRecord := from.getRegisteredPtrTypeRecord() if registeredPtrTypeRecord.ptr == 0 { return nil, fmt.Errorf("class handle already deleted") @@ -165,7 +183,7 @@ func (erc *classType) clone(from IClassBase) (IClassBase, error) { return from, nil } - clone, err := erc.getNewInstance(registeredPtrTypeRecord.shallowCopyInternalPointer()) + clone, err := erc.getNewInstance(ctx, registeredPtrTypeRecord.shallowCopyInternalPointer()) if err != nil { return nil, err } @@ -199,7 +217,7 @@ func (erc *classType) delete(ctx context.Context, handle IClassBase) error { return err } - if registeredPtrTypeRecord.preservePointerOnDelete { + if !registeredPtrTypeRecord.preservePointerOnDelete { registeredPtrTypeRecord.smartPtr = 0 registeredPtrTypeRecord.ptr = 0 } @@ -207,12 +225,14 @@ func (erc *classType) delete(ctx context.Context, handle IClassBase) error { return nil } -func (erc *classType) getNewInstance(record *registeredPointerTypeRecord) (IClassBase, error) { +func (erc *classType) getNewInstance(ctx context.Context, record *registeredPointerTypeRecord) (IClassBase, error) { + e := MustGetEngineFromContext(ctx, nil).(*engine) classBase := &ClassBase{ classType: erc, ptr: record.ptr, ptrType: record.ptrType, registeredPtrTypeRecord: record, + engine: e, } // If we have a Go struct, wrap the resulting class in it. @@ -232,10 +252,20 @@ func (erc *classType) getNewInstance(record *registeredPointerTypeRecord) (IClas return classBase, nil } +func (erc *classType) getDerivedClassesRecursive() []*classType { + derivedClasses := []*classType{} + for i := range erc.derivedClasses { + derivedClasses = append(derivedClasses, erc.derivedClasses[i]) + derivedClasses = append(derivedClasses, erc.derivedClasses[i].getDerivedClassesRecursive()...) + } + return derivedClasses +} + type IClassType interface { Name() string Type() IType Properties() []IClassTypeProperty + StaticProperties() []IClassTypeProperty Constructors() []IClassTypeConstructor Methods() []IClassTypeMethod StaticMethods() []IClassTypeMethod @@ -258,6 +288,8 @@ type IClassTypeMethod interface { Symbol() string ReturnType() IType ArgumentTypes() []IType + IsOverload() bool + OverloadCount() int } func (erc *classType) Name() string { @@ -272,6 +304,22 @@ func (erc *classType) Properties() []IClassTypeProperty { properties := make([]IClassTypeProperty, 0) for i := range erc.properties { + if erc.properties[i].isStatic { + continue + } + properties = append(properties, erc.properties[i]) + } + + return properties +} + +func (erc *classType) StaticProperties() []IClassTypeProperty { + properties := make([]IClassTypeProperty, 0) + + for i := range erc.properties { + if !erc.properties[i].isStatic { + continue + } properties = append(properties, erc.properties[i]) } @@ -285,7 +333,15 @@ func (erc *classType) Methods() []IClassTypeMethod { if erc.methods[i].isStatic { continue } - methods = append(methods, erc.methods[i]) + + if erc.methods[i].overloadTable != nil { + for overload := range erc.methods[i].overloadTable { + erc.methods[i].overloadTable[overload].overloadCount = len(erc.methods[i].overloadTable) + methods = append(methods, erc.methods[i].overloadTable[overload]) + } + } else { + methods = append(methods, erc.methods[i]) + } } return methods @@ -298,7 +354,15 @@ func (erc *classType) StaticMethods() []IClassTypeMethod { if !erc.methods[i].isStatic { continue } - methods = append(methods, erc.methods[i]) + + if erc.methods[i].overloadTable != nil { + for overload := range erc.methods[i].overloadTable { + erc.methods[i].overloadTable[overload].overloadCount = len(erc.methods[i].overloadTable) + methods = append(methods, erc.methods[i].overloadTable[overload]) + } + } else { + methods = append(methods, erc.methods[i]) + } } return methods @@ -364,6 +428,10 @@ func (ecb *ClassBase) getClassType() *classType { return ecb.classType } +func (ecb *ClassBase) String() string { + return fmt.Sprintf("%s, ptr: %d", ecb.classType.name, ecb.ptr) +} + func (ecb *ClassBase) getPtr() uint32 { return ecb.ptr } @@ -380,47 +448,78 @@ func (ecb *ClassBase) isValid() bool { return ecb != nil } -func (ecb *ClassBase) Clone(this IClassBase) (IClassBase, error) { - return ecb.classType.clone(this) +func (ecb *ClassBase) CloneInstance(ctx context.Context, this IClassBase) (IClassBase, error) { + return ecb.classType.clone(ctx, this) } -func (ecb *ClassBase) Delete(ctx context.Context, this IClassBase) error { +func (ecb *ClassBase) DeleteInstance(ctx context.Context, this IClassBase) error { return ecb.classType.delete(ctx, this) } -func (ecb *ClassBase) CallMethod(ctx context.Context, this any, name string, arguments ...any) (any, error) { +func (ecb *ClassBase) DeleteInstanceLater(ctx context.Context, this IClassBase) (IClassBase, error) { + return ecb.classType.deleteLater(ctx, this) +} + +func (ecb *ClassBase) IsInstanceDeleted(ctx context.Context, this IClassBase) bool { + return ecb.classType.isDeleted(ctx, this) +} + +func (ecb *ClassBase) IsAliasOfInstance(ctx context.Context, this IClassBase, second IClassBase) (bool, error) { + return ecb.classType.isAliasOf(ctx, this, second) +} + +func (ecb *ClassBase) CallInstanceMethod(ctx context.Context, this any, name string, arguments ...any) (any, error) { method, ok := ecb.classType.methods[name] if !ok { - return nil, fmt.Errorf("method %s is not found on %T", name, this) + return nil, fmt.Errorf("%s.%s() is not found", ecb.classType.name, name) } // Ensure that the engine is attached. Allows calling methods on the class // without keeping track of the engine. ctx = ecb.engine.Attach(ctx) + + if method.isStatic && this != nil { + return nil, fmt.Errorf("%s.%s() is static", ecb.classType.name, name) + } + return method.fn(ctx, this, arguments...) } -func (ecb *ClassBase) SetProperty(ctx context.Context, this any, name string, value any) error { +func (ecb *ClassBase) SetInstanceProperty(ctx context.Context, this any, name string, value any) error { property, ok := ecb.classType.properties[name] if !ok { - return fmt.Errorf("property %s is not found on %T", name, this) + return fmt.Errorf("%s.%s is a not found", ecb.classType.name, name) } // Ensure that the engine is attached. Allows setting properties on the // class without keeping track of the engine. ctx = ecb.engine.Attach(ctx) + + if property.Static() && this != nil { + return fmt.Errorf("%s.%s is static", ecb.classType.name, name) + } + + if property.ReadOnly() { + return fmt.Errorf("%s.%s is a read-only property", ecb.classType.name, name) + } + return property.set(ctx, this, value) } -func (ecb *ClassBase) GetProperty(ctx context.Context, this any, name string) (any, error) { +func (ecb *ClassBase) GetInstanceProperty(ctx context.Context, this any, name string) (any, error) { property, ok := ecb.classType.properties[name] if !ok { - return nil, fmt.Errorf("property %s is not found on %T", name, this) + return nil, fmt.Errorf("%s.%s is a not found", ecb.classType.name, name) } // Ensure that the engine is attached. Allows setting properties on the // class without keeping track of the engine. ctx = ecb.engine.Attach(ctx) + + if property.Static() && this != nil { + return nil, fmt.Errorf("%s.%s is static", ecb.classType.name, name) + } + return property.get(ctx, this) } @@ -430,9 +529,987 @@ type IClassBase interface { getPtrType() *registeredPointerType getRegisteredPtrTypeRecord() *registeredPointerTypeRecord isValid() bool - Clone(this IClassBase) (IClassBase, error) - Delete(ctx context.Context, this IClassBase) error - CallMethod(ctx context.Context, this any, name string, arguments ...any) (any, error) - SetProperty(ctx context.Context, this any, name string, value any) error - GetProperty(ctx context.Context, this any, name string) (any, error) + CloneInstance(ctx context.Context, this IClassBase) (IClassBase, error) + DeleteInstance(ctx context.Context, this IClassBase) error + DeleteInstanceLater(ctx context.Context, this IClassBase) (IClassBase, error) + IsInstanceDeleted(ctx context.Context, this IClassBase) bool + IsAliasOfInstance(ctx context.Context, this IClassBase, second IClassBase) (bool, error) + CallInstanceMethod(ctx context.Context, this any, name string, arguments ...any) (any, error) + SetInstanceProperty(ctx context.Context, this any, name string, value any) error + GetInstanceProperty(ctx context.Context, this any, name string) (any, error) +} + +var RegisterClass = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + rawType := api.DecodeI32(stack[0]) + rawPointerType := api.DecodeI32(stack[1]) + rawConstPointerType := api.DecodeI32(stack[2]) + baseClassRawType := api.DecodeI32(stack[3]) + getActualTypeSignature := api.DecodeI32(stack[4]) + getActualType := api.DecodeI32(stack[5]) + upcastSignature := api.DecodeI32(stack[6]) + upcast := api.DecodeI32(stack[7]) + downcastSignature := api.DecodeI32(stack[8]) + downcast := api.DecodeI32(stack[9]) + namePtr := api.DecodeI32(stack[10]) + destructorSignature := api.DecodeI32(stack[11]) + rawDestructor := api.DecodeI32(stack[12]) + + name, err := engine.readCString(uint32(namePtr)) + if err != nil { + panic(fmt.Errorf("could not read name: %w", err)) + } + + getActualTypeFunc, err := engine.newInvokeFunc(getActualTypeSignature, getActualType, []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}) + if err != nil { + panic(fmt.Errorf("could not read getActualType: %w", err)) + } + + var upcastFunc api.Function + if upcast > 0 { + upcastFunc, err = engine.newInvokeFunc(upcastSignature, upcast, []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}) + if err != nil { + panic(fmt.Errorf("could not read upcast: %w", err)) + } + } + + var downcastFunc api.Function + if downcast > 0 { + downcastFunc, err = engine.newInvokeFunc(downcastSignature, downcast, []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}) + if err != nil { + panic(fmt.Errorf("could not read downcast: %w", err)) + } + } + + rawDestructorFunc, err := engine.newInvokeFunc(destructorSignature, rawDestructor, []api.ValueType{api.ValueTypeI32}, []api.ValueType{}) + if err != nil { + panic(fmt.Errorf("could not read rawDestructor: %w", err)) + } + + legalFunctionName := engine.makeLegalFunctionName(name) + + // Set a default callback that errors out when not all types are resolved. + err = engine.exposePublicSymbol(legalFunctionName, func(ctx context.Context, this any, arguments ...any) (any, error) { + return nil, engine.createUnboundTypeError(ctx, fmt.Sprintf("Cannot call %s due to unbound types", name), []int32{baseClassRawType}) + }, nil) + if err != nil { + panic(fmt.Errorf("could not expose public symbol: %w", err)) + } + + dependentTypes := make([]int32, 0) + if baseClassRawType > 0 { + dependentTypes = append(dependentTypes, baseClassRawType) + } + + err = engine.whenDependentTypesAreResolved([]int32{rawType, rawPointerType, rawConstPointerType}, dependentTypes, func(resolvedTypes []registeredType) ([]registeredType, error) { + existingClass, ok := engine.registeredClasses[name] + if ok { + if existingClass.baseType.rawType != 0 { + return nil, fmt.Errorf("could not register class %s, already registered as raw type %d", name, existingClass.baseType.rawType) + } + } else { + engine.registeredClasses[name] = &classType{ + baseType: baseType{ + rawType: rawType, + name: name, + }, + pureVirtualFunctions: []string{}, + methods: map[string]*publicSymbol{}, + properties: map[string]*classProperty{}, + } + } + + engine.registeredClasses[name].hasCppClass = true + engine.registeredClasses[name].legalFunctionName = legalFunctionName + engine.registeredClasses[name].rawDestructor = rawDestructorFunc + engine.registeredClasses[name].getActualType = getActualTypeFunc + engine.registeredClasses[name].upcast = upcastFunc + engine.registeredClasses[name].downcast = downcastFunc + + if baseClassRawType > 0 { + engine.registeredClasses[name].baseClass = resolvedTypes[0].(*registeredPointerType).registeredClass + if engine.registeredClasses[name].baseClass.derivedClasses == nil { + engine.registeredClasses[name].baseClass.derivedClasses = []*classType{engine.registeredClasses[name]} + } else { + engine.registeredClasses[name].baseClass.derivedClasses = append(engine.registeredClasses[name].baseClass.derivedClasses, engine.registeredClasses[name]) + } + } + + referenceConverter := ®isteredPointerType{ + baseType: baseType{ + argPackAdvance: 8, + name: name, + }, + registeredClass: engine.registeredClasses[name], + isReference: true, + isConst: false, + isSmartPointer: false, + } + + pointerConverter := ®isteredPointerType{ + baseType: baseType{ + argPackAdvance: 8, + name: name + "*", + }, + registeredClass: engine.registeredClasses[name], + isReference: false, + isConst: false, + isSmartPointer: false, + } + + constPointerConverter := ®isteredPointerType{ + baseType: baseType{ + argPackAdvance: 8, + name: name + " const*", + }, + registeredClass: engine.registeredClasses[name], + isReference: false, + isConst: true, + isSmartPointer: false, + } + + engine.registeredPointers[rawType] = ®isteredPointer{ + pointerType: pointerConverter, + constPointerType: constPointerConverter, + } + + err := engine.registeredClasses[name].validate() + if err != nil { + return nil, err + } + + err = engine.replacePublicSymbol(legalFunctionName, func(ctx context.Context, _ any, arguments ...any) (any, error) { + if engine.registeredClasses[name].constructors == nil { + return nil, fmt.Errorf("%s has no accessible constructor", name) + } + + constructor, ok := engine.registeredClasses[name].constructors[int32(len(arguments))] + if !ok { + availableLengths := make([]string, 0) + for i := range engine.registeredClasses[name].constructors { + availableLengths = append(availableLengths, strconv.Itoa(int(i))) + } + sort.Strings(availableLengths) + return nil, fmt.Errorf("tried to invoke ctor of %s with invalid number of parameters (%d) - expected (%s) parameters instead", name, len(arguments), strings.Join(availableLengths, " or ")) + } + + return constructor.fn(ctx, nil, arguments...) + }, nil, nil, referenceConverter) + + if err != nil { + panic(fmt.Errorf("could not replace public symbol: %w", err)) + } + + return []registeredType{referenceConverter, pointerConverter, constPointerConverter}, nil + }) + + if err != nil { + panic(fmt.Errorf("could not call whenDependentTypesAreResolved: %w", err)) + } +}) + +var RegisterClassConstructor = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + rawClassType := api.DecodeI32(stack[0]) + argCount := api.DecodeI32(stack[1]) + rawArgTypesAddr := api.DecodeI32(stack[2]) + invokerSignature := api.DecodeI32(stack[3]) + invoker := api.DecodeI32(stack[4]) + rawConstructor := api.DecodeI32(stack[5]) + + rawArgTypes, err := engine.heap32VectorToArray(argCount, rawArgTypesAddr) + if err != nil { + panic(fmt.Errorf("could not read arg types: %w", err)) + } + + err = engine.whenDependentTypesAreResolved([]int32{}, []int32{rawClassType}, func(resolvedTypes []registeredType) ([]registeredType, error) { + classType := resolvedTypes[0].(*registeredPointerType) + humanName := "constructor " + classType.name + + if classType.registeredClass.constructors == nil { + classType.registeredClass.constructors = map[int32]*classConstructor{} + } + + if _, ok := classType.registeredClass.constructors[argCount-1]; ok { + return nil, fmt.Errorf("cannot register multiple constructors with identical number of parameters (%d) for class '%s'! Overload resolution is currently only performed using the parameter count, not actual type info", argCount-1, classType.name) + } + + classType.registeredClass.constructors[argCount-1] = &classConstructor{ + fn: func(ctx context.Context, this any, arguments ...any) (any, error) { + return nil, engine.createUnboundTypeError(ctx, fmt.Sprintf("Cannot call %s due to unbound types", classType.name), rawArgTypes) + }, + argumentTypes: createAnyTypeArray(argCount - 1), + resultType: &anyType{}, + } + + err := engine.whenDependentTypesAreResolved([]int32{}, rawArgTypes, func(argTypes []registeredType) ([]registeredType, error) { + // Insert empty slot for context type (argTypes[1]). + newArgTypes := []registeredType{argTypes[0], nil} + if len(argTypes) > 1 { + newArgTypes = append(newArgTypes, argTypes[1:]...) + } + + expectedParamTypes := make([]api.ValueType, len(newArgTypes[2:])+1) + expectedParamTypes[0] = api.ValueTypeI32 // fn + for i := range newArgTypes[2:] { + expectedParamTypes[i+1] = newArgTypes[i+2].NativeType() + } + + invokerFunc, err := engine.newInvokeFunc(invokerSignature, invoker, expectedParamTypes, []api.ValueType{argTypes[0].NativeType()}) + if err != nil { + return nil, fmt.Errorf("could not create invoke func: %w", err) + } + + classType.registeredClass.constructors[argCount-1].resultType = argTypes[0] + classType.registeredClass.constructors[argCount-1].argumentTypes = argTypes[1:] + classType.registeredClass.constructors[argCount-1].fn = engine.craftInvokerFunction(humanName, newArgTypes, nil, invokerFunc, rawConstructor, false) + return []registeredType{}, err + }) + + return []registeredType{}, err + }) + + if err != nil { + panic(fmt.Errorf("could not call whenDependentTypesAreResolved: %w", err)) + } +}) + +var RegisterClassFunction = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + rawClassType := api.DecodeI32(stack[0]) + methodNamePtr := api.DecodeI32(stack[1]) + argCount := api.DecodeI32(stack[2]) + rawArgTypesAddr := api.DecodeI32(stack[3]) + invokerSignature := api.DecodeI32(stack[4]) + rawInvoker := api.DecodeI32(stack[5]) + contextPtr := api.DecodeI32(stack[6]) + isPureVirtual := api.DecodeI32(stack[7]) + isAsync := api.DecodeI32(stack[8]) + + rawArgTypes, err := engine.heap32VectorToArray(argCount, rawArgTypesAddr) + if err != nil { + panic(fmt.Errorf("could not read arg types: %w", err)) + } + + methodName, err := engine.readCString(uint32(methodNamePtr)) + if err != nil { + panic(fmt.Errorf("could not read method name: %w", err)) + } + + err = engine.whenDependentTypesAreResolved([]int32{}, []int32{rawClassType}, func(classTypes []registeredType) ([]registeredType, error) { + classType := classTypes[0].(*registeredPointerType) + humanName := classType.Name() + "." + methodName + + if strings.HasPrefix(methodName, "@@") { + return nil, fmt.Errorf("could not get function name %s: well-known symbols are not supported in Go", methodName) + } + + if isPureVirtual > 0 { + classType.registeredClass.pureVirtualFunctions = append(classType.registeredClass.pureVirtualFunctions, methodName) + } + + unboundTypesHandler := &publicSymbol{ + name: methodName, + fn: func(ctx context.Context, this any, arguments ...any) (any, error) { + return nil, engine.createUnboundTypeError(ctx, fmt.Sprintf("Cannot call %s due to unbound types", humanName), rawArgTypes) + }, + argumentTypes: createAnyTypeArray(argCount - 2), + resultType: &anyType{}, + } + + newMethodArgCount := argCount - 2 + existingMethod, ok := classType.registeredClass.methods[methodName] + if !ok || (existingMethod.overloadTable == nil && existingMethod.className != classType.name && *existingMethod.argCount == newMethodArgCount) { + // This is the first overload to be registered, OR we are replacing a + // function in the base class with a function in the derived class. + unboundTypesHandler.argCount = &newMethodArgCount + unboundTypesHandler.className = classType.name + unboundTypesHandler.isOverload = true + classType.registeredClass.methods[methodName] = unboundTypesHandler + } else { + // There was an existing function with the same name registered. Set up + // a function overload routing table. + engine.ensureOverloadTable(classType.registeredClass.methods, methodName, humanName) + classType.registeredClass.methods[methodName].overloadTable[argCount-2] = unboundTypesHandler + } + + err = engine.whenDependentTypesAreResolved([]int32{}, rawArgTypes, func(argTypes []registeredType) ([]registeredType, error) { + expectedResultTypes := make([]api.ValueType, len(argTypes)) + expectedResultTypes[0] = api.ValueTypeI32 // contextPtr + for i := range argTypes[1:] { + expectedResultTypes[i+1] = argTypes[i+1].NativeType() + } + + rawInvokerFunc, err := engine.newInvokeFunc(invokerSignature, rawInvoker, expectedResultTypes, []api.ValueType{argTypes[0].NativeType()}) + if err != nil { + panic(fmt.Errorf("could not create _embind_register_class_function raw invoke func: %w", err)) + } + + fn := engine.craftInvokerFunction(humanName, argTypes, classType, rawInvokerFunc, contextPtr, isAsync > 0) + + memberFunction := &publicSymbol{ + name: methodName, + resultType: argTypes[0], + argumentTypes: argTypes[2:], + fn: fn, + } + + // Replace the initial unbound-handler-stub function with the appropriate member function, now that all types + // are resolved. If multiple overloads are registered for this function, the function goes into an overload table. + if classType.registeredClass.methods[methodName].overloadTable == nil { + // Set argCount in case an overload is registered later + memberFunction.argCount = &newMethodArgCount + classType.registeredClass.methods[methodName] = memberFunction + } else { + memberFunction.isOverload = true + classType.registeredClass.methods[methodName].overloadTable[argCount-2] = memberFunction + } + + derivesClasses := classType.registeredClass.getDerivedClassesRecursive() + if derivesClasses != nil { + for i := range derivesClasses { + derivedMemberFunction := &publicSymbol{ + name: methodName, + resultType: argTypes[0], + argumentTypes: argTypes[2:], + fn: fn, + } + + derivedClass := derivesClasses[i] + _, ok := derivedClass.methods[methodName] + if !ok { + derivedMemberFunction.argCount = &newMethodArgCount + // This is the first function to be registered with this name. + derivedClass.methods[methodName] = derivedMemberFunction + } else { + // There was an existing function with the same name registered. Set up + // a function overload routing table. + engine.ensureOverloadTable(derivedClass.methods, methodName, humanName) + derivedMemberFunction.isOverload = true + + // Do not override already registered methods. + _, ok := derivedClass.methods[methodName].overloadTable[argCount-2] + if !ok { + derivedClass.methods[methodName].overloadTable[argCount-2] = derivedMemberFunction + } + } + } + } + + return []registeredType{}, nil + }) + + return []registeredType{}, err + }) + + if err != nil { + panic(fmt.Errorf("could not call whenDependentTypesAreResolved: %w", err)) + } +}) + +var RegisterClassClassFunction = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + rawClassType := api.DecodeI32(stack[0]) + methodNamePtr := api.DecodeI32(stack[1]) + argCount := api.DecodeI32(stack[2]) + rawArgTypesAddr := api.DecodeI32(stack[3]) + invokerSignature := api.DecodeI32(stack[4]) + rawInvoker := api.DecodeI32(stack[5]) + fn := api.DecodeI32(stack[6]) + isAsync := api.DecodeI32(stack[7]) + + rawArgTypes, err := engine.heap32VectorToArray(argCount, rawArgTypesAddr) + if err != nil { + panic(fmt.Errorf("could not read arg types: %w", err)) + } + + methodName, err := engine.readCString(uint32(methodNamePtr)) + if err != nil { + panic(fmt.Errorf("could not read method name: %w", err)) + } + + err = engine.whenDependentTypesAreResolved([]int32{}, []int32{rawClassType}, func(classTypes []registeredType) ([]registeredType, error) { + classType := classTypes[0].(*registeredPointerType) + humanName := classType.Name() + "." + methodName + + if strings.HasPrefix(methodName, "@@") { + return nil, fmt.Errorf("could not get class function name %s: well-known symbols are not supported in Go", methodName) + } + + unboundTypesHandler := &publicSymbol{ + name: methodName, + isStatic: true, + fn: func(ctx context.Context, this any, arguments ...any) (any, error) { + return nil, engine.createUnboundTypeError(ctx, fmt.Sprintf("Cannot call %s due to unbound types", humanName), rawArgTypes) + }, + argumentTypes: createAnyTypeArray(argCount - 1), + resultType: &anyType{}, + } + + newArgCount := argCount - 1 + _, ok := classType.registeredClass.methods[methodName] + if !ok { + // This is the first function to be registered with this name. + unboundTypesHandler.argCount = &newArgCount + classType.registeredClass.methods[methodName] = unboundTypesHandler + } else { + // There was an existing function with the same name registered. Set up + // a function overload routing table. + engine.ensureOverloadTable(classType.registeredClass.methods, methodName, humanName) + classType.registeredClass.methods[methodName].overloadTable[argCount-1] = unboundTypesHandler + } + + err = engine.whenDependentTypesAreResolved([]int32{}, rawArgTypes, func(argTypes []registeredType) ([]registeredType, error) { + invokerArgsArray := []registeredType{argTypes[0], nil} + invokerArgsArray = append(invokerArgsArray, argTypes[1:]...) + + expectedParamTypes := make([]api.ValueType, len(invokerArgsArray[2:])+1) + expectedParamTypes[0] = api.ValueTypeI32 // fn + for i := range invokerArgsArray[2:] { + expectedParamTypes[i+1] = invokerArgsArray[i+2].NativeType() + } + + rawInvokerFunc, err := engine.newInvokeFunc(invokerSignature, rawInvoker, expectedParamTypes, []api.ValueType{argTypes[0].NativeType()}) + if err != nil { + panic(fmt.Errorf("could not create raw invoke func: %w", err)) + } + + fn := engine.craftInvokerFunction(humanName, invokerArgsArray, nil, rawInvokerFunc, fn, isAsync > 0) + memberFunction := &publicSymbol{ + name: methodName, + argumentTypes: argTypes[1:], + resultType: argTypes[0], + isStatic: true, + fn: fn, + } + + // Replace the initial unbound-handler-stub function with the appropriate member function, now that all types + // are resolved. If multiple overloads are registered for this function, the function goes into an overload table. + if classType.registeredClass.methods[methodName].overloadTable == nil { + // Set argCount in case an overload is registered later + memberFunction.argCount = &newArgCount + classType.registeredClass.methods[methodName] = memberFunction + } else { + memberFunction.isOverload = true + classType.registeredClass.methods[methodName].overloadTable[argCount-1] = memberFunction + } + + derivesClasses := classType.registeredClass.getDerivedClassesRecursive() + if derivesClasses != nil { + for i := range derivesClasses { + derivedMemberFunction := &publicSymbol{ + name: methodName, + argumentTypes: argTypes[1:], + resultType: argTypes[0], + isStatic: true, + fn: fn, + } + + derivedClass := derivesClasses[i] + _, ok := derivedClass.methods[methodName] + if !ok { + // This is the first function to be registered with this name. + derivedMemberFunction.argCount = &newArgCount + derivedClass.methods[methodName] = derivedMemberFunction + } else { + // There was an existing function with the same name registered. Set up + // a function overload routing table. + engine.ensureOverloadTable(derivedClass.methods, methodName, humanName) + derivedMemberFunction.isOverload = true + + // Do not override already registered methods. + _, ok := derivedClass.methods[methodName].overloadTable[argCount-1] + if !ok { + derivedClass.methods[methodName].overloadTable[argCount-1] = derivedMemberFunction + } + } + } + } + + return []registeredType{}, nil + }) + + return []registeredType{}, err + }) + if err != nil { + panic(fmt.Errorf("could not call whenDependentTypesAreResolved: %w", err)) + } +}) + +var RegisterClassClassProperty = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + rawClassType := api.DecodeI32(stack[0]) + fieldNamePtr := api.DecodeI32(stack[1]) + rawFieldType := api.DecodeI32(stack[2]) + rawFieldPtr := api.DecodeI32(stack[3]) + getterSignaturePtr := api.DecodeI32(stack[4]) + getter := api.DecodeI32(stack[5]) + setterSignaturePtr := api.DecodeI32(stack[6]) + setter := api.DecodeI32(stack[7]) + + fieldName, err := engine.readCString(uint32(fieldNamePtr)) + if err != nil { + panic(fmt.Errorf("could not read method name: %w", err)) + } + + getterFunc, err := engine.newInvokeFunc(getterSignaturePtr, getter, []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}) + if err != nil { + panic(fmt.Errorf("could not read getter: %w", err)) + } + + err = engine.whenDependentTypesAreResolved([]int32{}, []int32{rawClassType}, func(classTypes []registeredType) ([]registeredType, error) { + classType := classTypes[0].(*registeredPointerType) + + humanName := classType.Name() + "." + fieldName + + desc := &classProperty{ + name: fieldName, + isStatic: true, + get: func(ctx context.Context, this any) (any, error) { + return nil, engine.createUnboundTypeError(ctx, fmt.Sprintf("Cannot access %s due to unbound types", humanName), []int32{rawFieldType}) + }, + getterType: &anyType{}, + enumerable: true, + configurable: true, + } + + if setter > 0 { + desc.setterType = &anyType{} + desc.set = func(ctx context.Context, this any, v any) error { + return engine.createUnboundTypeError(ctx, fmt.Sprintf("Cannot access %s due to unbound types", humanName), []int32{rawFieldType}) + } + } else { + desc.readOnly = true + desc.set = func(ctx context.Context, this any, v any) error { + return fmt.Errorf("%s is a read-only property", humanName) + } + } + + classType.registeredClass.properties[fieldName] = desc + err = engine.whenDependentTypesAreResolved([]int32{}, []int32{rawFieldType}, func(fieldTypes []registeredType) ([]registeredType, error) { + fieldType := fieldTypes[0] + + desc := &classProperty{ + name: fieldName, + getterType: fieldType, + isStatic: true, + get: func(ctx context.Context, this any) (any, error) { + res, err := getterFunc.Call(ctx, api.EncodeI32(rawFieldPtr)) + if err != nil { + return nil, err + } + return fieldType.FromWireType(ctx, engine.mod, res[0]) + }, + enumerable: true, + readOnly: true, + } + + if setter > 0 { + setterFunc, err := engine.newInvokeFunc(setterSignaturePtr, setter, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}) + if err != nil { + return nil, fmt.Errorf("could not create _embind_register_class_class_property setterFunc: %w", err) + } + + desc.readOnly = false + desc.setterType = fieldType + desc.set = func(ctx context.Context, this any, v any) error { + destructors := &[]*destructorFunc{} + setterRes, err := fieldType.ToWireType(ctx, engine.mod, destructors, v) + if err != nil { + return err + } + + _, err = setterFunc.Call(ctx, api.EncodeI32(rawFieldPtr), setterRes) + if err != nil { + return err + } + + err = engine.runDestructors(ctx, *destructors) + if err != nil { + return err + } + + return nil + } + } + + classType.registeredClass.properties[fieldName] = desc + + derivesClasses := classType.registeredClass.getDerivedClassesRecursive() + if derivesClasses != nil { + for i := range derivesClasses { + derivedClass := derivesClasses[i] + + // Do not override already registered methods. + _, ok := derivedClass.properties[fieldName] + if !ok { + derivedClass.properties[fieldName] = desc + } + } + } + + return []registeredType{}, err + }) + return []registeredType{}, err + }) + + if err != nil { + panic(fmt.Errorf("could not call whenDependentTypesAreResolved: %w", err)) + } +}) + +var RegisterClassProperty = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + classType := api.DecodeI32(stack[0]) + fieldNamePtr := api.DecodeI32(stack[1]) + getterReturnType := api.DecodeI32(stack[2]) + getterSignature := api.DecodeI32(stack[3]) + getter := api.DecodeI32(stack[4]) + getterContext := api.DecodeI32(stack[5]) + setterArgumentType := api.DecodeI32(stack[6]) + setterSignature := api.DecodeI32(stack[7]) + setter := api.DecodeI32(stack[8]) + setterContext := api.DecodeI32(stack[9]) + + fieldName, err := engine.readCString(uint32(fieldNamePtr)) + if err != nil { + panic(fmt.Errorf("could not read method name: %w", err)) + } + + err = engine.whenDependentTypesAreResolved([]int32{}, []int32{classType}, func(classTypes []registeredType) ([]registeredType, error) { + classType := classTypes[0].(*registeredPointerType) + humanName := classType.Name() + "." + fieldName + + desc := &classProperty{ + name: fieldName, + get: func(ctx context.Context, this any) (any, error) { + return nil, engine.createUnboundTypeError(ctx, fmt.Sprintf("Cannot access %s due to unbound types", humanName), []int32{getterReturnType, setterArgumentType}) + }, + getterType: &anyType{}, + enumerable: true, + configurable: true, + } + + if setter > 0 { + desc.setterType = &anyType{} + desc.set = func(ctx context.Context, this any, v any) error { + return engine.createUnboundTypeError(ctx, fmt.Sprintf("Cannot access %s due to unbound types", humanName), []int32{getterReturnType, setterArgumentType}) + } + } else { + desc.readOnly = true + desc.set = func(ctx context.Context, this any, v any) error { + return fmt.Errorf("%s is a read-only property", humanName) + } + } + + classType.registeredClass.properties[fieldName] = desc + + requiredTypes := []int32{getterReturnType} + if setter > 0 { + requiredTypes = append(requiredTypes, setterArgumentType) + } + + err = engine.whenDependentTypesAreResolved([]int32{}, requiredTypes, func(types []registeredType) ([]registeredType, error) { + getterReturnType := types[0] + + getterFunc, err := engine.newInvokeFunc(getterSignature, getter, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{getterReturnType.NativeType()}) + if err != nil { + return nil, fmt.Errorf("could not create _embind_register_class_property getterFunc: %w", err) + } + + desc := &classProperty{ + name: fieldName, + getterType: getterReturnType, + get: func(ctx context.Context, this any) (any, error) { + ptr, err := engine.validateThis(ctx, this, classType, humanName+" getter") + if err != nil { + return nil, err + } + + res, err := getterFunc.Call(ctx, api.EncodeI32(getterContext), api.EncodeU32(ptr)) + if err != nil { + return nil, err + } + return getterReturnType.FromWireType(ctx, engine.mod, res[0]) + }, + enumerable: true, + readOnly: true, + } + + if setter > 0 { + setterArgumentType := types[1] + setterFunc, err := engine.newInvokeFunc(setterSignature, setter, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, setterArgumentType.NativeType()}, []api.ValueType{}) + if err != nil { + return nil, fmt.Errorf("could not create _embind_register_class_property setterFunc: %w", err) + } + + desc.readOnly = false + desc.setterType = setterArgumentType + desc.set = func(ctx context.Context, this any, v any) error { + ptr, err := engine.validateThis(ctx, this, classType, humanName+" setter") + if err != nil { + return err + } + + destructors := &[]*destructorFunc{} + setterRes, err := setterArgumentType.ToWireType(ctx, engine.mod, destructors, v) + if err != nil { + return err + } + + _, err = setterFunc.Call(ctx, api.EncodeI32(setterContext), api.EncodeU32(ptr), setterRes) + if err != nil { + return err + } + + err = engine.runDestructors(ctx, *destructors) + if err != nil { + return err + } + + return nil + } + } + + classType.registeredClass.properties[fieldName] = desc + + derivesClasses := classType.registeredClass.getDerivedClassesRecursive() + if derivesClasses != nil { + for i := range derivesClasses { + derivedClass := derivesClasses[i] + + // Do not override already registered methods. + _, ok := derivedClass.properties[fieldName] + if !ok { + derivedClass.properties[fieldName] = desc + } + } + } + + return []registeredType{}, err + }) + + return []registeredType{}, err + }) + if err != nil { + panic(fmt.Errorf("could not call whenDependentTypesAreResolved: %w", err)) + } +}) + +var RegisterSmartPtr = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + rawType := api.DecodeI32(stack[0]) + rawPointeeType := api.DecodeI32(stack[1]) + namePtr := api.DecodeI32(stack[2]) + sharingPolicy := api.DecodeI32(stack[3]) + getPointeeSignature := api.DecodeI32(stack[4]) + rawGetPointee := api.DecodeI32(stack[5]) + constructorSignature := api.DecodeI32(stack[6]) + rawConstructor := api.DecodeI32(stack[7]) + shareSignature := api.DecodeI32(stack[8]) + rawShare := api.DecodeI32(stack[9]) + destructorSignature := api.DecodeI32(stack[10]) + rawDestructor := api.DecodeI32(stack[11]) + + name, err := engine.readCString(uint32(namePtr)) + if err != nil { + panic(fmt.Errorf("could not read name: %w", err)) + } + + rawGetPointeeFunc, err := engine.newInvokeFunc(getPointeeSignature, rawGetPointee, []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}) + if err != nil { + panic(fmt.Errorf("could not read rawGetPointee: %w", err)) + } + + rawConstructorFunc, err := engine.newInvokeFunc(constructorSignature, rawConstructor, []api.ValueType{}, []api.ValueType{api.ValueTypeI32}) + if err != nil { + panic(fmt.Errorf("could not read constructorSignature: %w", err)) + } + + rawShareFunc, err := engine.newInvokeFunc(shareSignature, rawShare, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}) + specialShare := false + if err != nil { + // Some classes have a different share signature for some reason. + rawShareFunc, err = engine.newInvokeFunc(shareSignature, rawShare, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}) + if err != nil { + panic(fmt.Errorf("could not read rawShare: %w", err)) + } + specialShare = true + } + + rawDestructorFunc, err := engine.newInvokeFunc(destructorSignature, rawDestructor, []api.ValueType{api.ValueTypeI32}, []api.ValueType{}) + if err != nil { + panic(fmt.Errorf("could not read rawDestructor: %w", err)) + } + + err = engine.whenDependentTypesAreResolved([]int32{rawType}, []int32{rawPointeeType}, func(types []registeredType) ([]registeredType, error) { + pointeeType := types[0] + + smartPointerType := ®isteredPointerType{ + baseType: baseType{ + argPackAdvance: 8, + name: name, + }, + registeredClass: pointeeType.(*registeredPointerType).registeredClass, + isReference: false, + isConst: false, + isSmartPointer: true, + pointeeType: pointeeType.(*registeredPointerType), + sharingPolicy: sharingPolicy, + rawGetPointee: rawGetPointeeFunc, + rawConstructor: rawConstructorFunc, + rawShare: rawShareFunc, + rawDestructor: rawDestructorFunc, + specialShare: specialShare, + } + + return []registeredType{smartPointerType}, nil + }) + + if err != nil { + panic(fmt.Errorf("could not call whenDependentTypesAreResolved: %w", err)) + } +}) + +var CreateInheritingConstructor = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + panic(fmt.Errorf("CreateInheritingConstructor is not implemented (correctly)")) + /* + engine := MustGetEngineFromContext(ctx, mod).(*engine) + constructorNamePtr := api.DecodeI32(stack[0]) + wrapperTypePtr := api.DecodeI32(stack[1]) + propertiesId := api.DecodeI32(stack[2]) + + constructorName, err := engine.readCString(uint32(constructorNamePtr)) + if err != nil { + panic(fmt.Errorf("could not read name: %w", err)) + } + + wrapperType, err := engine.requireRegisteredType(ctx, wrapperTypePtr, "wrapper") + if err != nil { + panic(fmt.Errorf("could not require registered type: %w", err)) + } + + properties, err := engine.emvalEngine.toValue(propertiesId) + if err != nil { + panic(fmt.Errorf("could not get properties val: %w", err)) + } + + if _, ok := properties.(IClassBase); !ok { + panic(fmt.Errorf("could not register class %s with type %T, it does not embed embind.ClassBase", constructorName, properties)) + } + + reflectClassType := reflect.TypeOf(properties) + if reflectClassType.Kind() != reflect.Ptr { + panic(fmt.Errorf("could not register class %s with type %T, given value should be a pointer type", constructorName, properties)) + } + + registeredPointerType := wrapperType.(*registeredPointerType) + legalFunctionName := engine.makeLegalFunctionName(constructorName) + err = engine.exposePublicSymbol(legalFunctionName, func(ctx context.Context, this any, arguments ...any) (any, error) { + log.Println(registeredPointerType.name) + log.Println(registeredPointerType.registeredClass.name) + if registeredPointerType.registeredClass.constructors == nil { + return nil, fmt.Errorf("%s has no accessible constructor", constructorName) + } + + // @todo: create an actual instance of properties here. + + constructor, ok := registeredPointerType.registeredClass.constructors[int32(len(arguments))] + if !ok { + availableLengths := make([]string, 0) + for i := range registeredPointerType.registeredClass.constructors { + availableLengths = append(availableLengths, strconv.Itoa(int(i))) + } + sort.Strings(availableLengths) + return nil, fmt.Errorf("tried to invoke ctor of %s with invalid number of parameters (%d) - expected (%s) parameters instead", constructorName, len(arguments), strings.Join(availableLengths, " or ")) + } + + return constructor.fn(ctx, nil, arguments...) + }, nil) + if err != nil { + panic(fmt.Errorf("could not expose public symbol: %w", err)) + } + + newFn := func(ctx context.Context, arguments ...any) (any, error) { + return engine.publicSymbols[legalFunctionName].fn(ctx, nil, arguments...) + } + + stack[0] = api.EncodeI32(engine.emvalEngine.toHandle(newFn)) + */ +}) + +func (e *engine) CallStaticClassMethod(ctx context.Context, className, name string, arguments ...any) (any, error) { + _, ok := e.publicSymbols[className] + if !ok { + return nil, fmt.Errorf("could not find class %s", className) + } + + _, ok = e.registeredClasses[className].methods[name] + if !ok { + return nil, fmt.Errorf("could not find method %s on class %s", name, className) + } + + if !e.registeredClasses[className].methods[name].isStatic { + return nil, fmt.Errorf("method %s on class %s is not static", name, className) + } + + ctx = e.Attach(ctx) + res, err := e.registeredClasses[className].methods[name].fn(ctx, nil, arguments...) + if err != nil { + return nil, fmt.Errorf("error while calling embind function %s on class %s: %w", name, className, err) + } + + return res, nil +} + +func (e *engine) GetStaticClassProperty(ctx context.Context, className, name string) (any, error) { + _, ok := e.publicSymbols[className] + if !ok { + return nil, fmt.Errorf("could not find class %s", className) + } + + _, ok = e.registeredClasses[className].properties[name] + if !ok { + return nil, fmt.Errorf("could not find property %s on class %s", name, className) + } + + if !e.registeredClasses[className].properties[name].isStatic { + return nil, fmt.Errorf("property %s on class %s is not static", name, className) + } + + ctx = e.Attach(ctx) + res, err := e.registeredClasses[className].properties[name].get(ctx, nil) + if err != nil { + return nil, fmt.Errorf("error while calling embind property getter %s on class %s: %w", name, className, err) + } + + return res, nil +} + +func (e *engine) SetStaticClassProperty(ctx context.Context, className, name string, value any) error { + _, ok := e.publicSymbols[className] + if !ok { + return fmt.Errorf("could not find class %s", className) + } + + _, ok = e.registeredClasses[className].properties[name] + if !ok { + return fmt.Errorf("could not find property %s on class %s", name, className) + } + + if !e.registeredClasses[className].properties[name].isStatic { + return fmt.Errorf("property %s on class %s is not static", name, className) + } + + if e.registeredClasses[className].properties[name].readOnly { + return fmt.Errorf("property %s on class %s is read-only", name, className) + } + + ctx = e.Attach(ctx) + err := e.registeredClasses[className].properties[name].set(ctx, nil, value) + if err != nil { + return fmt.Errorf("error while calling embind property setter %s on class %s: %w", name, className, err) + } + + return nil } diff --git a/internal/constant.go b/internal/constant.go index 1fd86c7..b61a8ea 100644 --- a/internal/constant.go +++ b/internal/constant.go @@ -1,7 +1,10 @@ package embind import ( + "context" "fmt" + "github.com/tetratelabs/wazero/api" + "reflect" ) type IConstant interface { @@ -22,7 +25,10 @@ type registeredConstant struct { func (rc *registeredConstant) validate() error { if rc.hasGoValue && rc.hasCppValue { - if rc.goValue != rc.cppValue { + // Only compare when values can be compared. + goValueType := reflect.TypeOf(rc.goValue) + cppValueType := reflect.TypeOf(rc.cppValue) + if goValueType.Comparable() && cppValueType.Comparable() && rc.goValue != rc.cppValue { return fmt.Errorf("constant %s has a different value in Go than in C++ (go: %v (%T), cpp: %v (%T))", rc.name, rc.goValue, rc.goValue, rc.cppValue, rc.cppValue) } } @@ -49,3 +55,47 @@ func (e *engine) GetConstants() []IConstant { } return constants } + +var RegisterConstant = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + + name, err := engine.readCString(uint32(api.DecodeI32(stack[0]))) + if err != nil { + panic(fmt.Errorf("could not read name: %w", err)) + } + + rawType := api.DecodeI32(stack[1]) + constantValue := api.DecodeF64(stack[2]) + + err = engine.whenDependentTypesAreResolved([]int32{}, []int32{rawType}, func(argTypes []registeredType) ([]registeredType, error) { + registeredType := argTypes[0] + // We need to do this since the JS VM automatically converts between + // the float64 and other types, but we can't do this, we need to + // manually convert everything. Note that the value inside the original + // uint64 is an actual typecast F64, so it's not that the stack + // contains FromWireType'able data for the given type. + cppValue := registeredType.FromF64(constantValue) + val, err := registeredType.FromWireType(ctx, engine.mod, cppValue) + if err != nil { + return nil, fmt.Errorf("could not initialize constant %s: %w", name, err) + } + + _, ok := engine.registeredConstants[name] + if !ok { + engine.registeredConstants[name] = ®isteredConstant{ + name: name, + } + } + + engine.registeredConstants[name].registeredType = registeredType + engine.registeredConstants[name].hasCppValue = true + engine.registeredConstants[name].cppValue = val + engine.registeredConstants[name].rawCppValue = cppValue + + return nil, engine.registeredConstants[name].validate() + }) + + if err != nil { + panic(err) + } +}) diff --git a/internal/embind.go b/internal/embind.go index 837190c..599b62a 100644 --- a/internal/embind.go +++ b/internal/embind.go @@ -2,14 +2,16 @@ package embind import ( "context" + "errors" "fmt" + "reflect" + "github.com/tetratelabs/wazero/api" ) type IEngine interface { Attach(ctx context.Context) context.Context CallPublicSymbol(ctx context.Context, name string, arguments ...any) (any, error) - CallStaticClassMethod(ctx context.Context, className, name string, arguments ...any) (any, error) GetSymbols() []ISymbol RegisterConstant(name string, val any) error GetConstants() []IConstant @@ -17,11 +19,21 @@ type IEngine interface { GetEnums() []IEnumType RegisterClass(name string, class any) error GetClasses() []IClassType + CallStaticClassMethod(ctx context.Context, className, name string, arguments ...any) (any, error) + GetStaticClassProperty(ctx context.Context, className, name string) (any, error) + SetStaticClassProperty(ctx context.Context, className, name string, value any) error RegisterEmvalSymbol(name string, symbol any) error EmvalToHandle(value any) int32 EmvalToValue(handle int32) (any, error) + CountEmvalHandles() int + GetInheritedInstanceCount() int + GetLiveInheritedInstances() []IClassBase + FlushPendingDeletes(ctx context.Context) error + SetDelayFunction(fn DelayFunction) error } +type DelayFunction func(func(ctx context.Context) error) error + type IEngineConfig interface { } @@ -48,6 +60,10 @@ func MustGetEngineFromContext(ctx context.Context, mod api.Module) IEngine { panic(fmt.Errorf("could not get embind engine from context: %w, make sure to create an engine with embind.CreateEngine() and to attach it to the context with \"ctx = context.WithValue(ctx, embind.EngineKey{}, engine)\"", err)) } + if e.(*engine) == nil { + panic(fmt.Errorf("could not get embind engine from context: %w, make sure to create an engine with embind.CreateEngine() and to attach it to the context with \"ctx = context.WithValue(ctx, embind.EngineKey{}, engine)\"", errors.New("nil engine"))) + } + if e.(*engine).mod != nil { if mod != nil && e.(*engine).mod != mod { panic(fmt.Errorf("could not get embind engine from context, this engine was created for another Wazero api.Module")) @@ -79,9 +95,13 @@ func CreateEngine(config IEngineConfig) IEngine { registeredConstants: map[string]*registeredConstant{}, registeredEnums: map[string]*enumType{}, registeredClasses: map[string]*classType{}, + registeredClassTypes: map[reflect.Type]*classType{}, registeredPointers: map[int32]*registeredPointer{}, registeredTuples: map[int32]*registeredTuple{}, registeredObjects: map[int32]*registeredObject{}, + registeredInstances: map[uint32]IClassBase{}, + deletionQueue: []IClassBase{}, + delayFunction: nil, emvalEngine: createEmvalEngine(), } } diff --git a/internal/emval.go b/internal/emval.go index 5473a65..1865fe5 100644 --- a/internal/emval.go +++ b/internal/emval.go @@ -2,10 +2,15 @@ package embind import ( "context" + "errors" "fmt" "reflect" + "strconv" + "strings" "unicode" + "github.com/jerbob92/wazero-emscripten-embind/types" + "github.com/tetratelabs/wazero/api" ) @@ -49,6 +54,10 @@ func (et *emvalType) ReadValueFromPointer(ctx context.Context, mod api.Module, p return et.FromWireType(ctx, mod, api.EncodeU32(value)) } +func (et *emvalType) DestructorFunctionUndefined() bool { + return false +} + func (et *emvalType) GoType() string { return "any" } @@ -69,6 +78,10 @@ func (ea *emvalAllocator) get(id int32) (*emvalHandle, error) { return nil, fmt.Errorf("invalid id: %d", id) } + if ea.allocated[int(id)] == nil { + return nil, fmt.Errorf("invalid id: %d", id) + } + return ea.allocated[int(id)], nil } @@ -165,7 +178,7 @@ func createEmvalEngine() *emvalEngine { allocated: []*emvalHandle{ nil, // Reserve slot 0 so that 0 is always an invalid handle { - value: undefined, + value: types.Undefined, }, { value: nil, @@ -188,7 +201,7 @@ func createEmvalEngine() *emvalEngine { } func (e *emvalEngine) toHandle(value any) int32 { - if value == undefined { + if value == types.Undefined { return 1 } else if value == nil { return 2 @@ -212,7 +225,7 @@ func (e *emvalEngine) toValue(id int32) (any, error) { func (e *emvalEngine) getGlobal(name string) any { global, ok := e.globals[name] if !ok { - return undefined + return types.Undefined } return global } @@ -406,3 +419,648 @@ func (e *emvalEngine) callMethod(ctx context.Context, mod api.Module, registered return res, nil } + +var RegisterEmval = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + + rawType := api.DecodeI32(stack[0]) + name, err := engine.readCString(uint32(api.DecodeI32(stack[1]))) + if err != nil { + panic(fmt.Errorf("could not read name: %w", err)) + } + + err = engine.registerType(rawType, &emvalType{ + baseType: baseType{ + rawType: rawType, + name: name, + argPackAdvance: 8, + }, + }, ®isterTypeOptions{ + ignoreDuplicateRegistrations: true, + }) + if err != nil { + panic(fmt.Errorf("could not register: %w", err)) + } +}) + +var EmvalTakeValue = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + rawType := api.DecodeI32(stack[0]) + + registeredType, ok := engine.registeredTypes[rawType] + if !ok { + typeName, err := engine.getTypeName(ctx, rawType) + if err != nil { + panic(err) + } + panic(fmt.Errorf("_emval_take_value has unknown type %s", typeName)) + } + + arg := api.DecodeI32(stack[1]) + value, err := registeredType.ReadValueFromPointer(ctx, mod, uint32(arg)) + if err != nil { + panic(fmt.Errorf("could not take value for _emval_take_value: %w", err)) + } + + id := engine.emvalEngine.toHandle(value) + stack[0] = api.EncodeI32(id) +}) + +var EmvalIncref = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + handle := api.DecodeI32(stack[0]) + err := engine.emvalEngine.allocator.incref(handle) + if err != nil { + panic(fmt.Errorf("could not emval incref: %w", err)) + } +}) + +var EmvalDecref = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + handle := api.DecodeI32(stack[0]) + err := engine.emvalEngine.allocator.decref(handle) + if err != nil { + panic(fmt.Errorf("could not emval incref: %w", err)) + } +}) + +var EmvalRegisterSymbol = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + address := uint32(api.DecodeI32(stack[0])) + name, err := engine.readCString(address) + if err != nil { + panic(fmt.Errorf("could not get symbol name")) + } + engine.emvalEngine.symbols[address] = name +}) + +var EmvalGetGlobal = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + name := api.DecodeI32(stack[0]) + + if name == 0 { + stack[0] = api.EncodeI32(engine.emvalEngine.toHandle(engine.emvalEngine.getGlobal(""))) + } else { + name, err := engine.getStringOrSymbol(uint32(name)) + if err != nil { + panic(fmt.Errorf("could not get symbol name")) + } + stack[0] = api.EncodeI32(engine.emvalEngine.toHandle(engine.emvalEngine.getGlobal(name))) + } +}) + +var EmvalAs = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + id := api.DecodeI32(stack[0]) + handle, err := engine.emvalEngine.toValue(id) + if err != nil { + panic(fmt.Errorf("could not find handle: %w", err)) + } + + returnType, err := engine.requireRegisteredType(ctx, api.DecodeI32(stack[1]), "emval::as") + if err != nil { + panic(fmt.Errorf("could not require registered type: %w", err)) + } + + var destructors = &[]*destructorFunc{} + rd := engine.emvalEngine.toHandle(destructors) + ok := mod.Memory().WriteUint32Le(uint32(api.DecodeI32(stack[2])), uint32(rd)) + if !ok { + panic(fmt.Errorf("could not write destructor ref to memory")) + } + + returnVal, err := returnType.ToWireType(ctx, mod, destructors, handle) + if err != nil { + panic(fmt.Errorf("could not call toWireType on _emval_as: %w", err)) + } + + stack[0] = api.EncodeF64(returnType.ToF64(returnVal)) +}) + +var EmvalNew = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + id := api.DecodeI32(stack[0]) + + handle, err := engine.emvalEngine.toValue(id) + if err != nil { + panic(fmt.Errorf("could not get value of handle: %w", err)) + } + + argCount := int(api.DecodeI32(stack[1])) + argsTypeBase := uint32(api.DecodeI32(stack[2])) + argsBase := uint32(api.DecodeI32(stack[3])) + + args := make([]any, argCount) + argTypeNames := make([]string, argCount) + for i := 0; i < argCount; i++ { + argType, ok := mod.Memory().ReadUint32Le(argsTypeBase + (4 * uint32(i))) + if !ok { + panic(fmt.Errorf("could not read arg type for arg %d from memory", i)) + } + + registeredArgType, err := engine.requireRegisteredType(ctx, int32(argType), fmt.Sprintf("argument %d", i)) + if err != nil { + panic(fmt.Errorf("could not require registered type: %w", err)) + } + + args[i], err = registeredArgType.ReadValueFromPointer(ctx, mod, argsBase) + if err != nil { + panic(fmt.Errorf("could not read arg value from pointer for arg %d, %w", i, err)) + } + + argsBase += uint32(registeredArgType.ArgPackAdvance()) + + argTypeNames[i] = registeredArgType.Name() + } + + var res any + c, ok := handle.(IEmvalConstructor) + if ok { + res, err = c.New(argTypeNames, args...) + if err != nil { + panic(fmt.Errorf("could not instaniate new value on %T with New(): %w", handle, err)) + } + } else { + typeElem := reflect.TypeOf(handle) + + // If we received a pointer, resolve the struct behind it. + if typeElem.Kind() == reflect.Pointer { + typeElem = typeElem.Elem() + } + + // Make new instance of struct. + newElem := reflect.New(typeElem) + + // Set the values on the struct if we need to/can. + if argCount > 0 { + if typeElem.Kind() != reflect.Struct { + panic(fmt.Errorf("could not instaniate new value of %T: arguments required but can only be set on a struct", handle)) + } + + for i := 0; i < argCount; i++ { + argSet := false + for fieldI := 0; fieldI < typeElem.NumField(); fieldI++ { + var err error + func() { + defer func() { + if recoverErr := recover(); recoverErr != nil { + realError, ok := recoverErr.(error) + if ok { + err = fmt.Errorf("could not set arg %d with embind_arg tag on emval %T: %w", i, handle, realError) + } + err = fmt.Errorf("could not set arg %d with embind_arg tag on emval %T: %v", i, handle, recoverErr) + } + }() + + val := typeElem.Field(fieldI) + if val.Tag.Get("embind_arg") == strconv.Itoa(i) { + f := newElem.Elem().FieldByName(val.Name) + if f.IsValid() && f.CanSet() { + f.Set(reflect.ValueOf(args[i])) + argSet = true + } + } + }() + if err != nil { + panic(fmt.Errorf("could not instaniate new value of %T: %w", handle, err)) + } + } + if !argSet { + panic(fmt.Errorf("could not instaniate new value of %T: could not bind arg %d", handle, i)) + } + } + } + + if reflect.TypeOf(handle).Kind() == reflect.Pointer { + res = newElem.Interface() + } else { + res = newElem.Elem().Interface() + } + } + + stack[0] = api.EncodeI32(engine.emvalEngine.toHandle(res)) +}) + +var EmvalSetProperty = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + + handle, err := engine.emvalEngine.toValue(api.DecodeI32(stack[0])) + if err != nil { + panic(fmt.Errorf("could not find handle: %w", err)) + } + + key, err := engine.emvalEngine.toValue(api.DecodeI32(stack[1])) + if err != nil { + panic(fmt.Errorf("could not find key: %w", err)) + } + + val, err := engine.emvalEngine.toValue(api.DecodeI32(stack[2])) + if err != nil { + panic(fmt.Errorf("could not find val: %w", err)) + } + + keyString, ok := key.(string) + if !ok { + panic(fmt.Errorf("could not set property on emval %T: %w", handle, errors.New("key is not of type string"))) + } + + f, err := engine.emvalEngine.getElemField(handle, keyString) + if err != nil { + panic(fmt.Errorf("could not set property %s on emval %T: %w", keyString, handle, err)) + } + + defer func() { + if err := recover(); err != nil { + realError, ok := err.(error) + if ok { + panic(fmt.Errorf("could not set property %s on emval %T: %w", keyString, handle, realError)) + } + panic(fmt.Errorf("could not set property %s on emval %T: %v", keyString, handle, err)) + } + }() + + f.Set(reflect.ValueOf(val)) +}) + +var EmvalGetProperty = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + + handle, err := engine.emvalEngine.toValue(api.DecodeI32(stack[0])) + if err != nil { + panic(fmt.Errorf("could not find handle: %w", err)) + } + + key, err := engine.emvalEngine.toValue(api.DecodeI32(stack[1])) + if err != nil { + panic(fmt.Errorf("could not find key: %w", err)) + } + + keyString, ok := key.(string) + if !ok { + panic(fmt.Errorf("could not get property on emval %T: %w", handle, errors.New("key is not of type string"))) + } + + f, err := engine.emvalEngine.getElemField(handle, keyString) + if err != nil { + panic(fmt.Errorf("could not get property %s on emval %T: %w", keyString, handle, err)) + } + + defer func() { + if err := recover(); err != nil { + realError, ok := err.(error) + if ok { + panic(fmt.Errorf("could not get property %s on emval %T: %w", keyString, handle, realError)) + } + panic(fmt.Errorf("could not get property %s on emval %T: %v", keyString, handle, err)) + } + }() + + stack[0] = api.EncodeI32(engine.emvalEngine.toHandle(f.Interface())) +}) + +var EmvalNewCString = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + v := api.DecodeI32(stack[0]) + name, err := engine.getStringOrSymbol(uint32(v)) + if err != nil { + panic(fmt.Errorf("could not get symbol name")) + } + stack[0] = api.EncodeI32(engine.emvalEngine.toHandle(name)) +}) + +var EmvalRunDestructors = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + id := api.DecodeI32(stack[0]) + destructorsVal, err := engine.emvalEngine.toValue(id) + if err != nil { + panic(fmt.Errorf("could not find handle: %w", err)) + } + + destructors := destructorsVal.(*[]*destructorFunc) + + err = engine.runDestructors(ctx, *destructors) + if err != nil { + panic(fmt.Errorf("could not run destructors: %w", err)) + } + + err = engine.emvalEngine.allocator.decref(id) + if err != nil { + panic(fmt.Errorf("could not run decref id %d: %w", id, err)) + } +}) + +var EmvalGetMethodCaller = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + + argCount := int(api.DecodeI32(stack[0])) + argsTypeBase := uint32(api.DecodeI32(stack[1])) + + typeNames := make([]string, argCount) + argTypes := make([]registeredType, argCount) + for i := 0; i < argCount; i++ { + argType, ok := mod.Memory().ReadUint32Le(argsTypeBase + (4 * uint32(i))) + if !ok { + panic(fmt.Errorf("could not read arg type for arg %d from memory", i)) + } + + registeredType, err := engine.requireRegisteredType(ctx, int32(argType), fmt.Sprintf("argument %d", i)) + if err != nil { + panic(fmt.Errorf("could not require registered type: %w", err)) + } + + typeNames[i] = registeredType.Name() + argTypes[i] = registeredType + } + + signatureName := typeNames[0] + "_$" + strings.Join(typeNames[1:], "_") + "$" + + id, ok := engine.emvalEngine.registeredMethodIds[signatureName] + if ok { + stack[0] = api.EncodeI32(id) + return + } + + newID := engine.emvalEngine.registeredMethodCount + newRegisteredMethod := &emvalRegisteredMethod{ + id: newID, + argTypes: argTypes, + name: signatureName, + } + engine.emvalEngine.registeredMethodIds[signatureName] = newID + engine.emvalEngine.registeredMethods[newID] = newRegisteredMethod + engine.emvalEngine.registeredMethodCount++ + + stack[0] = api.EncodeI32(newID) + return +}) + +var EmvalCall = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + id := api.DecodeI32(stack[0]) + argCount := api.DecodeI32(stack[1]) + argTypes := api.DecodeI32(stack[2]) + argv := api.DecodeI32(stack[3]) + + handle, err := engine.emvalEngine.toValue(id) + if err != nil { + panic(fmt.Errorf("could not find handle: %w", err)) + } + + registeredArgTypes, err := engine.lookupTypes(ctx, argCount, argTypes) + if err != nil { + panic(fmt.Errorf("could not load required types: %w", err)) + } + + args := make([]any, argCount) + for i := 0; i < int(argCount); i++ { + requiredType := registeredArgTypes[i] + args[i], err = requiredType.ReadValueFromPointer(ctx, mod, uint32(argv)) + if err != nil { + panic(fmt.Errorf("could not load argument value: %w", err)) + } + + argv += requiredType.ArgPackAdvance() + } + + reflectValues := make([]reflect.Value, argCount) + for i := range args { + reflectValues[i] = reflect.ValueOf(args[i]) + } + + value := reflect.ValueOf(handle) + result := value.Call(reflectValues) + + var resultVal any = types.Undefined + if len(result) > 0 { + resultVal = result[0].Interface() + } + + newHandle := engine.emvalEngine.toHandle(resultVal) + stack[0] = api.EncodeI32(newHandle) +}) + +var EmvalCallMethod = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + caller := api.DecodeI32(stack[0]) + + registeredMethod, ok := engine.emvalEngine.registeredMethods[caller] + if !ok { + panic(fmt.Errorf("could not call method with ID %d", caller)) + } + + id := api.DecodeI32(stack[1]) + handle, err := engine.emvalEngine.toValue(id) + if err != nil { + panic(fmt.Errorf("could not find handle: %w", err)) + } + + methodName, err := engine.getStringOrSymbol(uint32(api.DecodeI32(stack[2]))) + if err != nil { + panic(fmt.Errorf("could not get symbol name")) + } + + argsBase := uint32(api.DecodeI32(stack[4])) + destructorsRef := uint32(api.DecodeI32(stack[3])) + + res, err := engine.emvalEngine.callMethod(ctx, mod, registeredMethod, handle, methodName, destructorsRef, argsBase) + if err != nil { + panic(fmt.Errorf("could not call %s on %T: %w", methodName, handle, err)) + } + stack[0] = api.EncodeF64(float64(res)) +}) + +var EmvalCallVoidMethod = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + caller := api.DecodeI32(stack[0]) + + registeredMethod, ok := engine.emvalEngine.registeredMethods[caller] + if !ok { + panic(fmt.Errorf("could not call method with ID %d", caller)) + } + + id := api.DecodeI32(stack[1]) + handle, err := engine.emvalEngine.toValue(id) + if err != nil { + panic(fmt.Errorf("could not find handle: %w", err)) + } + + methodName, err := engine.getStringOrSymbol(uint32(api.DecodeI32(stack[2]))) + if err != nil { + panic(fmt.Errorf("could not get symbol name")) + } + + argsBase := uint32(api.DecodeI32(stack[3])) + + _, err = engine.emvalEngine.callMethod(ctx, mod, registeredMethod, handle, methodName, 0, argsBase) + if err != nil { + panic(fmt.Errorf("could not call %s on %T: %w", methodName, handle, err)) + } +}) + +var EmvalInstanceof = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + // @todo: implement me. + panic("EmvalInstanceof call unimplemented") +}) + +var EmvalTypeof = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + id := api.DecodeI32(stack[0]) + handle, err := engine.emvalEngine.toValue(id) + if err != nil { + panic(fmt.Errorf("could not find handle: %w", err)) + } + + // Default type. + typeOf := "object" + + if handle != nil { + reflectTypeOf := reflect.TypeOf(handle) + switch reflectTypeOf.Kind() { + case reflect.Func: + typeOf = "function" + case reflect.String: + typeOf = "string" + case reflect.Bool: + typeOf = "boolean" + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, + reflect.Uintptr, reflect.Float32, reflect.Float64: + typeOf = "number" + case reflect.Int64, reflect.Uint64: + typeOf = "bigint" + } + + if handle == types.Undefined { + typeOf = "undefined" + } + } + + stack[0] = api.EncodeI32(engine.emvalEngine.toHandle(typeOf)) +}) + +var EmvalAsInt64 = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + id := api.DecodeI32(stack[0]) + handle, err := engine.emvalEngine.toValue(id) + if err != nil { + panic(fmt.Errorf("could not find handle: %w", err)) + } + + returnType, err := engine.requireRegisteredType(ctx, api.DecodeI32(stack[1]), "emval::as") + if err != nil { + panic(fmt.Errorf("could not require registered type: %w", err)) + } + + returnVal, err := returnType.ToWireType(ctx, mod, nil, handle) + if err != nil { + panic(fmt.Errorf("could not call toWireType on _emval_as: %w", err)) + } + + stack[0] = returnVal +}) + +var EmvalAsUint64 = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + id := api.DecodeI32(stack[0]) + handle, err := engine.emvalEngine.toValue(id) + if err != nil { + panic(fmt.Errorf("could not find handle: %w", err)) + } + + returnType, err := engine.requireRegisteredType(ctx, api.DecodeI32(stack[1]), "emval::as") + if err != nil { + panic(fmt.Errorf("could not require registered type: %w", err)) + } + + returnVal, err := returnType.ToWireType(ctx, mod, nil, handle) + if err != nil { + panic(fmt.Errorf("could not call toWireType on _emval_as: %w", err)) + } + + stack[0] = returnVal +}) + +var EmvalAwait = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + // @todo: implement me. + panic("EmvalAwait call unimplemented") +}) + +var EmvalDelete = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + // @todo: implement me. + panic("EmvalDelete call unimplemented") +}) + +var EmvalEquals = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + // @todo: implement me. + panic("EmvalEquals call unimplemented") +}) + +var EmvalGetModuleProperty = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + // @todo: implement me. + panic("EmvalGetModuleProperty call unimplemented") +}) + +var EmvalIn = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + // @todo: implement me. + panic("EmvalIn call unimplemented") +}) + +var EmvalIsNumber = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + // @todo: implement me. + panic("EmvalIsNumber call unimplemented") +}) + +var EmvalIsString = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + // @todo: implement me. + panic("EmvalIsString call unimplemented") +}) + +var EmvalLessThan = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + // @todo: implement me. + panic("EmvalLessThan call unimplemented") +}) + +var EmvalNewArray = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + e := MustGetEngineFromContext(ctx, mod).(*engine) + stack[0] = api.EncodeI32(e.emvalEngine.toHandle([]any{})) +}) + +var EmvalNewArrayFromMemoryView = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + // @todo: implement me. + panic("EmvalNewArrayFromMemoryView call unimplemented") +}) + +var EmvalNewObject = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + e := MustGetEngineFromContext(ctx, mod).(*engine) + stack[0] = api.EncodeI32(e.emvalEngine.toHandle(map[string]any{})) +}) + +var EmvalNewU16string = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + // @todo: implement me. + panic("EmvalNewU16string call unimplemented") +}) + +var EmvalNewU8string = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + // @todo: implement me. + panic("EmvalNewU8string call unimplemented") +}) + +var EmvalNot = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + // @todo: implement me. + panic("EmvalNot call unimplemented") +}) + +var EmvalStrictlyEquals = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + // @todo: implement me. + panic("EmvalStrictlyEquals call unimplemented") +}) + +var EmvalThrow = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + // @todo: implement me. + panic("EmvalThrow call unimplemented") +}) + +var EmvalGreaterThan = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + // @todo: implement me. + panic("EmvalGreaterThan call unimplemented") +}) diff --git a/internal/engine.go b/internal/engine.go index 8a07fc1..1824db7 100644 --- a/internal/engine.go +++ b/internal/engine.go @@ -6,6 +6,7 @@ import ( "fmt" "reflect" "regexp" + "sort" "strconv" "strings" @@ -24,9 +25,12 @@ type engine struct { registeredEnums map[string]*enumType registeredPointers map[int32]*registeredPointer registeredClasses map[string]*classType + registeredClassTypes map[reflect.Type]*classType registeredTuples map[int32]*registeredTuple registeredObjects map[int32]*registeredObject registeredInstances map[uint32]IClassBase + deletionQueue []IClassBase + delayFunction DelayFunction emvalEngine *emvalEngine } @@ -106,7 +110,8 @@ func (e *engine) RegisterClass(name string, class any) error { return fmt.Errorf("could not register class %s with type %T, it does not embed embind.ClassBase", name, class) } - if reflect.TypeOf(class).Kind() != reflect.Ptr { + reflectClassType := reflect.TypeOf(class) + if reflectClassType.Kind() != reflect.Ptr { return fmt.Errorf("could not register class %s with type %T, given value should be a pointer type", name, class) } @@ -132,6 +137,8 @@ func (e *engine) RegisterClass(name string, class any) error { e.registeredClasses[name].hasGoStruct = false } + e.registeredClassTypes[reflectClassType] = e.registeredClasses[name] + return err } @@ -161,9 +168,9 @@ func (e *engine) newInvokeFunc(signaturePtr, rawInvoker int32, expectedParamType if recoverErr := recover(); recoverErr != nil { realError, ok := recoverErr.(error) if ok { - lookupErr = fmt.Errorf("could not crate invoke func for signature %s on invoker %d: %w", signature, rawInvoker, realError) + lookupErr = fmt.Errorf("could not create invoke func for signature %s on invoker %d: %w", signature, rawInvoker, realError) } - lookupErr = fmt.Errorf("could not crate invoke func for signature %s on invoker %d: %v", signature, rawInvoker, recoverErr) + lookupErr = fmt.Errorf("could not create invoke func for signature %s on invoker %d: %v", signature, rawInvoker, recoverErr) } }() @@ -227,14 +234,17 @@ func (e *engine) ensureOverloadTable(registry map[string]*publicSymbol, methodNa prevFunc := registry[methodName].fn prevArgCount := registry[methodName].argCount + registry[methodName].isOverload = true + // Inject an overload resolver function that routes to the appropriate overload based on the number of arguments. registry[methodName].fn = func(ctx context.Context, this any, arguments ...any) (any, error) { _, ok := registry[methodName].overloadTable[int32(len(arguments))] if !ok { possibleOverloads := make([]string, len(registry[methodName].overloadTable)) for i := range registry[methodName].overloadTable { - possibleOverloads = append(possibleOverloads, strconv.Itoa(int(i))) + possibleOverloads[i] = strconv.Itoa(int(i)) } + sort.Strings(possibleOverloads) return nil, fmt.Errorf("function '%s' called with an invalid number of arguments (%d) - expects one of (%s)", humanName, len(arguments), strings.Join(possibleOverloads, ", ")) } @@ -250,6 +260,7 @@ func (e *engine) ensureOverloadTable(registry map[string]*publicSymbol, methodNa argCount: prevArgCount, fn: prevFunc, isStatic: registry[methodName].isStatic, + isOverload: true, } } } @@ -275,18 +286,23 @@ func (e *engine) exposePublicSymbol(name string, value publicSymbolFn, numArgume // Add the new function into the overload table. e.publicSymbols[name].overloadTable[*numArguments] = &publicSymbol{ - name: name, - argCount: numArguments, - fn: value, + name: name, + argCount: numArguments, + fn: value, + isOverload: true, + argumentTypes: createAnyTypeArray(*numArguments), + resultType: &anyType{}, } } else { e.publicSymbols[name] = &publicSymbol{ - name: name, - fn: value, + name: name, + fn: value, + resultType: &anyType{}, } if numArguments != nil { e.publicSymbols[name].argCount = numArguments + e.publicSymbols[name].argumentTypes = createAnyTypeArray(*numArguments) } } @@ -307,6 +323,7 @@ func (e *engine) replacePublicSymbol(name string, value func(ctx context.Context fn: value, argumentTypes: argumentTypes, resultType: resultType, + isOverload: true, } } else { e.publicSymbols[name] = &publicSymbol{ @@ -421,7 +438,7 @@ func (e *engine) craftInvokerFunction(humanName string, argTypes []registeredTyp // TODO: Remove this completely once all function invokers are being dynamically generated. needsDestructorStack := false for i := 1; i < len(argTypes); i++ { // Skip return value at index 0 - it's not deleted here. - if argTypes[i] != nil && argTypes[i].HasDestructorFunction() { // The type does not define a destructor function - must use dynamic stack + if argTypes[i] != nil && argTypes[i].DestructorFunctionUndefined() { // The type does not define a destructor function - must use dynamic stack needsDestructorStack = true break } @@ -474,6 +491,14 @@ func (e *engine) craftInvokerFunction(humanName string, argTypes []registeredTyp return nil, err } + var returnVal any + if returns { + returnVal, err = retType.FromWireType(ctx, e.mod, res[0]) + if err != nil { + return nil, fmt.Errorf("could not get wire type of return value (%s) on %T: %w", retType.Name(), retType, err) + } + } + if needsDestructorStack { err = e.runDestructors(ctx, *destructors) if err != nil { @@ -485,29 +510,24 @@ func (e *engine) craftInvokerFunction(humanName string, argTypes []registeredTyp if isClassMethodFunc { startArg = 1 } + for i := startArg; i < len(argTypes); i++ { - if argTypes[i].HasDestructorFunction() { - destructorsRef := *destructors - destructor, err := argTypes[i].DestructorFunction(ctx, e.mod, api.DecodeU32(callArgs[i])) + ptrIndex := i + if !isClassMethodFunc { + ptrIndex -= 1 + } + + argDestructorFunc := argTypes[i].DestructorFunction(ctx, e.mod, api.DecodeU32(callArgs[ptrIndex])) + if argDestructorFunc != nil { + err = argDestructorFunc.run(ctx, e.mod) if err != nil { return nil, err } - destructorsRef = append(destructorsRef, destructor) - *destructors = destructorsRef } } } - if returns { - returnVal, err := retType.FromWireType(ctx, e.mod, res[0]) - if err != nil { - return nil, fmt.Errorf("could not get wire type of return value (%s) on %T: %w", retType.Name(), retType, err) - } - - return returnVal, nil - } - - return nil, nil + return returnVal, nil } } @@ -594,7 +614,7 @@ func (e *engine) checkRegisteredTypeDependencies(typeToVisit int32, seen *map[in unboundTypes = append(unboundTypes, newUnboundTypes...) } } - return nil + return unboundTypes } unboundTypes = append(unboundTypes, typeToVisit) @@ -678,6 +698,26 @@ func (e *engine) requireRegisteredType(ctx context.Context, rawType int32, human return registeredType, nil } +func (e *engine) lookupTypes(ctx context.Context, argCount int32, argTypes int32) ([]registeredType, error) { + types := make([]registeredType, argCount) + + for i := 0; i < int(argCount); i++ { + rawType, ok := e.mod.Memory().ReadUint32Le(uint32((argTypes) + (int32(i) * 4))) + if !ok { + return nil, fmt.Errorf("could not read memory for the argument type") + } + + requiredType, err := e.requireRegisteredType(ctx, int32(rawType), fmt.Sprintf("parameter %d", i)) + if err != nil { + return nil, err + } + + types[i] = requiredType + } + + return types, nil +} + var illegalCharsRegex = regexp.MustCompile(`[^a-zA-Z0-9_]`) func (e *engine) makeLegalFunctionName(name string) string { @@ -726,6 +766,53 @@ func (e *engine) validateThis(ctx context.Context, this any, classType *register // @todo: check if based.ptrType.registeredClass is or extends classType.registeredClass - // todo: kill this + // todo: kill this (comment from Emscripten) return e.upcastPointer(ctx, based.getPtr(), based.getPtrType().registeredClass, classType.registeredClass) } + +func (e *engine) CountEmvalHandles() int { + return len(e.emvalEngine.allocator.allocated) - len(e.emvalEngine.allocator.freelist) - e.emvalEngine.allocator.reserved +} + +func (e *engine) GetInheritedInstanceCount() int { + return len(e.registeredInstances) +} + +func (e *engine) GetLiveInheritedInstances() []IClassBase { + instances := make([]IClassBase, len(e.registeredInstances)) + i := 0 + for id := range e.registeredInstances { + instances[i] = e.registeredInstances[id] + i++ + } + return instances +} + +func (e *engine) FlushPendingDeletes(ctx context.Context) error { + for len(e.deletionQueue) > 0 { + obj := e.deletionQueue[len(e.deletionQueue)-1] + e.deletionQueue = e.deletionQueue[:len(e.deletionQueue)-1] + + obj.getRegisteredPtrTypeRecord().deleteScheduled = false + err := obj.DeleteInstance(ctx, obj) + if err != nil { + return err + } + } + return nil +} + +func (e *engine) SetDelayFunction(fn DelayFunction) error { + e.delayFunction = fn + + if len(e.deletionQueue) > 0 && fn != nil { + err := fn(func(ctx context.Context) error { + return e.FlushPendingDeletes(ctx) + }) + if err != nil { + return err + } + } + + return nil +} diff --git a/internal/enum.go b/internal/enum.go index 8c0abc0..eb77243 100644 --- a/internal/enum.go +++ b/internal/enum.go @@ -97,6 +97,10 @@ func (et *enumType) mapToGoEnum(value any) (any, error) { return val.goValue, nil } +func (et *enumType) DestructorFunctionUndefined() bool { + return false +} + func (et *enumType) GoType() string { return et.name } @@ -124,3 +128,78 @@ func (e *engine) GetEnums() []IEnumType { } return enums } + +var RegisterEnum = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + + rawType := api.DecodeI32(stack[0]) + name, err := engine.readCString(uint32(api.DecodeI32(stack[1]))) + if err != nil { + panic(fmt.Errorf("could not read name: %w", err)) + } + + _, ok := engine.registeredEnums[name] + if !ok { + engine.registeredEnums[name] = &enumType{ + valuesByName: map[string]*enumValue{}, + valuesByCppValue: map[any]*enumValue{}, + valuesByGoValue: map[any]*enumValue{}, + } + } + + engine.registeredEnums[name].baseType = baseType{ + rawType: rawType, + name: name, + argPackAdvance: 8, + } + + engine.registeredEnums[name].intHelper = intType{ + size: api.DecodeI32(stack[2]), + signed: api.DecodeI32(stack[3]) > 0, + } + + err = engine.registerType(rawType, engine.registeredEnums[name], nil) + if err != nil { + panic(fmt.Errorf("could not register: %w", err)) + } +}) + +var RegisterEnumValue = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + + rawType := api.DecodeI32(stack[0]) + name, err := engine.readCString(uint32(api.DecodeI32(stack[1]))) + if err != nil { + panic(fmt.Errorf("could not read name: %w", err)) + } + + registeredType, ok := engine.registeredTypes[rawType] + if !ok { + typeName, err := engine.getTypeName(ctx, rawType) + if err != nil { + panic(err) + } + panic(fmt.Errorf("%s has unknown type %s", name, typeName)) + } + + enumType := registeredType.(*enumType) + enumWireValue, err := enumType.intHelper.FromWireType(ctx, mod, stack[2]) + if err != nil { + panic(fmt.Errorf("could not read value for enum %s", name)) + } + + _, ok = enumType.valuesByName[name] + if !ok { + enumType.valuesByName[name] = &enumValue{ + name: name, + } + } + + if enumType.valuesByName[name].hasCppValue { + panic(fmt.Errorf("enum value %s for enum %s was already registered", name, enumType.name)) + } + + enumType.valuesByName[name].hasCppValue = true + enumType.valuesByName[name].cppValue = enumWireValue + enumType.valuesByCppValue[enumWireValue] = enumType.valuesByName[name] +}) diff --git a/internal/float.go b/internal/float.go index 1121693..35bb18e 100644 --- a/internal/float.go +++ b/internal/float.go @@ -49,7 +49,7 @@ func (ft *floatType) ReadValueFromPointer(ctx context.Context, mod api.Module, p val, _ := mod.Memory().ReadFloat32Le(pointer) return val, nil } else if ft.size == 8 { - val, _ := mod.Memory().ReadUint64Le(pointer) + val, _ := mod.Memory().ReadFloat64Le(pointer) return val, nil } @@ -72,9 +72,42 @@ func (ft *floatType) GoType() string { return "float64" } +func (ft *floatType) DestructorFunctionUndefined() bool { + return false +} + func (ft *floatType) FromF64(o float64) uint64 { if ft.size == 4 { return api.EncodeF32(float32(o)) } return api.EncodeF64(o) } + +func (ft *floatType) ToF64(o uint64) float64 { + if ft.size == 4 { + return float64(api.DecodeF32(o)) + } + return api.DecodeF64(o) +} + +var RegisterFloat = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + + rawType := api.DecodeI32(stack[0]) + name, err := engine.readCString(uint32(api.DecodeI32(stack[1]))) + if err != nil { + panic(fmt.Errorf("could not read name: %w", err)) + } + + err = engine.registerType(rawType, &floatType{ + baseType: baseType{ + rawType: rawType, + name: name, + argPackAdvance: 8, + }, + size: api.DecodeI32(stack[2]), + }, nil) + if err != nil { + panic(fmt.Errorf("could not register: %w", err)) + } +}) diff --git a/internal/host_functions.go b/internal/host_functions.go deleted file mode 100644 index 2af4d16..0000000 --- a/internal/host_functions.go +++ /dev/null @@ -1,1648 +0,0 @@ -package embind - -import ( - "context" - "errors" - "fmt" - "log" - "reflect" - "strconv" - "strings" - - "github.com/tetratelabs/wazero/api" -) - -var RegisterFunction = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - namePtr := api.DecodeI32(stack[0]) - argCount := api.DecodeI32(stack[1]) - rawArgTypesAddr := api.DecodeI32(stack[2]) - signaturePtr := api.DecodeI32(stack[3]) - rawInvoker := api.DecodeI32(stack[4]) - fn := api.DecodeI32(stack[5]) - isAsync := api.DecodeI32(stack[6]) != 0 - - argTypes, err := engine.heap32VectorToArray(argCount, rawArgTypesAddr) - if err != nil { - panic(fmt.Errorf("could not read arg types: %w", err)) - } - - name, err := engine.readCString(uint32(namePtr)) - if err != nil { - panic(fmt.Errorf("could not read name: %w", err)) - } - - publicSymbolArgs := argCount - 1 - - // Set a default callback that errors out when not all types are resolved. - err = engine.exposePublicSymbol(name, func(ctx context.Context, this any, arguments ...any) (any, error) { - return nil, engine.createUnboundTypeError(ctx, fmt.Sprintf("Cannot call _embind_register_function %s due to unbound types", name), argTypes) - }, &publicSymbolArgs) - if err != nil { - panic(fmt.Errorf("could not expose public symbol: %w", err)) - } - - // When all types are resolved, replace the callback with the actual implementation. - err = engine.whenDependentTypesAreResolved([]int32{}, argTypes, func(argTypes []registeredType) ([]registeredType, error) { - invokerArgsArray := []registeredType{argTypes[0] /* return value */, nil /* no class 'this'*/} - invokerArgsArray = append(invokerArgsArray, argTypes[1:]... /* actual params */) - - expectedParamTypes := make([]api.ValueType, len(invokerArgsArray[2:])+1) - expectedParamTypes[0] = api.ValueTypeI32 // fn - for i := range invokerArgsArray[2:] { - expectedParamTypes[i+1] = invokerArgsArray[i+2].NativeType() - } - - // Create an api.Function to be able to invoke the function on the - // Emscripten side. - invokerFunc, err := engine.newInvokeFunc(signaturePtr, rawInvoker, expectedParamTypes, []api.ValueType{argTypes[0].NativeType()}) - if err != nil { - return nil, fmt.Errorf("could not create _embind_register_function invoke func: %w", err) - } - - err = engine.replacePublicSymbol(name, engine.craftInvokerFunction(name, invokerArgsArray, nil /* no class 'this'*/, invokerFunc, fn, isAsync), &publicSymbolArgs, argTypes[1:], argTypes[0]) - if err != nil { - return nil, err - } - - return []registeredType{}, nil - }) - if err != nil { - panic(fmt.Errorf("could not setup type dependenant lookup callbacks: %w", err)) - } -}) - -var RegisterVoid = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - - rawType := api.DecodeI32(stack[0]) - name, err := engine.readCString(uint32(api.DecodeI32(stack[1]))) - if err != nil { - panic(fmt.Errorf("could not read name: %w", err)) - } - - err = engine.registerType(rawType, &voidType{ - baseType: baseType{ - rawType: rawType, - name: name, - argPackAdvance: 0, - }, - }, nil) - if err != nil { - panic(fmt.Errorf("could not register: %w", err)) - } -}) - -var RegisterBool = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - - rawType := api.DecodeI32(stack[0]) - - name, err := engine.readCString(uint32(api.DecodeI32(stack[1]))) - if err != nil { - panic(fmt.Errorf("could not read name: %w", err)) - } - - err = engine.registerType(rawType, &boolType{ - baseType: baseType{ - rawType: rawType, - name: name, - argPackAdvance: 8, - }, - size: api.DecodeI32(stack[2]), - trueVal: api.DecodeI32(stack[3]), - falseVal: api.DecodeI32(stack[4]), - }, nil) - if err != nil { - panic(fmt.Errorf("could not register: %w", err)) - } -}) - -var RegisterInteger = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - - rawType := api.DecodeI32(stack[0]) - name, err := engine.readCString(uint32(api.DecodeI32(stack[1]))) - if err != nil { - panic(fmt.Errorf("could not read name: %w", err)) - } - - err = engine.registerType(rawType, &intType{ - baseType: baseType{ - rawType: rawType, - name: name, - argPackAdvance: 8, - }, - size: api.DecodeI32(stack[2]), - signed: !strings.Contains(name, "unsigned"), - }, nil) - if err != nil { - panic(fmt.Errorf("could not register: %w", err)) - } -}) - -var RegisterBigInt = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - - rawType := api.DecodeI32(stack[0]) - name, err := engine.readCString(uint32(api.DecodeI32(stack[1]))) - if err != nil { - panic(fmt.Errorf("could not read name: %w", err)) - } - - err = engine.registerType(rawType, &bigintType{ - baseType: baseType{ - rawType: rawType, - name: name, - argPackAdvance: 8, - }, - size: api.DecodeI32(stack[2]), - signed: !strings.HasPrefix(name, "u"), - }, nil) - if err != nil { - panic(fmt.Errorf("could not register: %w", err)) - } -}) - -var RegisterFloat = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - - rawType := api.DecodeI32(stack[0]) - name, err := engine.readCString(uint32(api.DecodeI32(stack[1]))) - if err != nil { - panic(fmt.Errorf("could not read name: %w", err)) - } - - err = engine.registerType(rawType, &floatType{ - baseType: baseType{ - rawType: rawType, - name: name, - argPackAdvance: 8, - }, - size: api.DecodeI32(stack[2]), - }, nil) - if err != nil { - panic(fmt.Errorf("could not register: %w", err)) - } -}) - -var RegisterStdString = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - - rawType := api.DecodeI32(stack[0]) - name, err := engine.readCString(uint32(api.DecodeI32(stack[1]))) - if err != nil { - panic(fmt.Errorf("could not read name: %w", err)) - } - - err = engine.registerType(rawType, &stdStringType{ - baseType: baseType{ - rawType: rawType, - name: name, - argPackAdvance: 8, - }, - stdStringIsUTF8: name == "std::string", - }, nil) - if err != nil { - panic(fmt.Errorf("could not register: %w", err)) - } -}) - -var RegisterStdWString = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - - rawType := api.DecodeI32(stack[0]) - name, err := engine.readCString(uint32(api.DecodeI32(stack[2]))) - if err != nil { - panic(fmt.Errorf("could not read name: %w", err)) - } - - err = engine.registerType(rawType, &stdWStringType{ - baseType: baseType{ - rawType: rawType, - name: name, - argPackAdvance: 8, - }, - charSize: api.DecodeI32(stack[1]), - }, nil) - if err != nil { - panic(fmt.Errorf("could not register: %w", err)) - } -}) - -var RegisterEmval = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - - rawType := api.DecodeI32(stack[0]) - name, err := engine.readCString(uint32(api.DecodeI32(stack[1]))) - if err != nil { - panic(fmt.Errorf("could not read name: %w", err)) - } - - err = engine.registerType(rawType, &emvalType{ - baseType: baseType{ - rawType: rawType, - name: name, - argPackAdvance: 8, - }, - }, ®isterTypeOptions{ - ignoreDuplicateRegistrations: true, - }) - if err != nil { - panic(fmt.Errorf("could not register: %w", err)) - } -}) - -var RegisterMemoryView = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - - rawType := api.DecodeI32(stack[0]) - dataTypeIndex := api.DecodeI32(stack[1]) - name, err := engine.readCString(uint32(api.DecodeI32(stack[2]))) - if err != nil { - panic(fmt.Errorf("could not read name: %w", err)) - } - - typeMapping := []any{ - int8(0), - uint8(0), - int16(0), - uint16(0), - int32(0), - uint32(0), - float32(0), - float64(0), - int64(0), - uint64(0), - } - - if dataTypeIndex < 0 || int(dataTypeIndex) >= len(typeMapping) { - panic(fmt.Errorf("invalid memory view data type index: %d", dataTypeIndex)) - } - - sizeMapping := []uint32{ - 1, // int8 - 1, // uint8 - 2, // int16 - 2, // uint16 - 4, // int32 - 4, // uint32 - 4, // float32 - 8, // float64 - 8, // int64 - 8, // uint64 - } - - err = engine.registerType(rawType, &memoryViewType{ - baseType: baseType{ - rawType: rawType, - name: name, - argPackAdvance: 8, - }, - dataTypeIndex: dataTypeIndex, - nativeSize: sizeMapping[dataTypeIndex], - nativeType: typeMapping[dataTypeIndex], - }, ®isterTypeOptions{ - ignoreDuplicateRegistrations: true, - }) - if err != nil { - panic(fmt.Errorf("could not register: %w", err)) - } -}) - -var RegisterConstant = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - - name, err := engine.readCString(uint32(api.DecodeI32(stack[0]))) - if err != nil { - panic(fmt.Errorf("could not read name: %w", err)) - } - - rawType := api.DecodeI32(stack[1]) - constantValue := api.DecodeF64(stack[2]) - - err = engine.whenDependentTypesAreResolved([]int32{}, []int32{rawType}, func(argTypes []registeredType) ([]registeredType, error) { - registeredType := argTypes[0] - // We need to do this since the JS VM automatically converts between - // the float64 and other types, but we can't do this, we need to - // manually convert everything. Note that the value inside the original - // uint64 is an actual typecast F64, so it's not that the stack - // contains FromWireType'able data for the given type. - cppValue := registeredType.FromF64(constantValue) - val, err := registeredType.FromWireType(ctx, engine.mod, cppValue) - if err != nil { - log.Println(err) - return nil, fmt.Errorf("could not initialize constant %s: %w", name, err) - } - - _, ok := engine.registeredConstants[name] - if !ok { - engine.registeredConstants[name] = ®isteredConstant{ - name: name, - } - } - - engine.registeredConstants[name].registeredType = registeredType - engine.registeredConstants[name].hasCppValue = true - engine.registeredConstants[name].cppValue = val - engine.registeredConstants[name].rawCppValue = cppValue - - return nil, engine.registeredConstants[name].validate() - }) - - if err != nil { - panic(err) - } -}) - -var RegisterEnum = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - - rawType := api.DecodeI32(stack[0]) - name, err := engine.readCString(uint32(api.DecodeI32(stack[1]))) - if err != nil { - panic(fmt.Errorf("could not read name: %w", err)) - } - - _, ok := engine.registeredEnums[name] - if !ok { - engine.registeredEnums[name] = &enumType{ - valuesByName: map[string]*enumValue{}, - valuesByCppValue: map[any]*enumValue{}, - valuesByGoValue: map[any]*enumValue{}, - } - } - - engine.registeredEnums[name].baseType = baseType{ - rawType: rawType, - name: name, - argPackAdvance: 8, - } - - engine.registeredEnums[name].intHelper = intType{ - size: api.DecodeI32(stack[2]), - signed: api.DecodeI32(stack[3]) > 0, - } - - err = engine.registerType(rawType, engine.registeredEnums[name], nil) - if err != nil { - panic(fmt.Errorf("could not register: %w", err)) - } -}) - -var RegisterEnumValue = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - - rawType := api.DecodeI32(stack[0]) - name, err := engine.readCString(uint32(api.DecodeI32(stack[1]))) - if err != nil { - panic(fmt.Errorf("could not read name: %w", err)) - } - - registeredType, ok := engine.registeredTypes[rawType] - if !ok { - typeName, err := engine.getTypeName(ctx, rawType) - if err != nil { - panic(err) - } - panic(fmt.Errorf("%s has unknown type %s", name, typeName)) - } - - enumType := registeredType.(*enumType) - enumWireValue, err := enumType.intHelper.FromWireType(ctx, mod, stack[2]) - if err != nil { - panic(fmt.Errorf("could not read value for enum %s", name)) - } - - _, ok = enumType.valuesByName[name] - if !ok { - enumType.valuesByName[name] = &enumValue{ - name: name, - } - } - - if enumType.valuesByName[name].hasCppValue { - panic(fmt.Errorf("enum value %s for enum %s was already registered", name, enumType.name)) - } - - enumType.valuesByName[name].hasCppValue = true - enumType.valuesByName[name].cppValue = enumWireValue - enumType.valuesByCppValue[enumWireValue] = enumType.valuesByName[name] -}) - -var EmvalTakeValue = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - rawType := api.DecodeI32(stack[0]) - - registeredType, ok := engine.registeredTypes[rawType] - if !ok { - typeName, err := engine.getTypeName(ctx, rawType) - if err != nil { - panic(err) - } - panic(fmt.Errorf("_emval_take_value has unknown type %s", typeName)) - } - - arg := api.DecodeI32(stack[1]) - value, err := registeredType.ReadValueFromPointer(ctx, mod, uint32(arg)) - if err != nil { - panic(fmt.Errorf("could not take value for _emval_take_value: %w", err)) - } - - id := engine.emvalEngine.toHandle(value) - stack[0] = api.EncodeI32(id) -}) - -var EmvalIncref = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - handle := api.DecodeI32(stack[0]) - err := engine.emvalEngine.allocator.incref(handle) - if err != nil { - panic(fmt.Errorf("could not emval incref: %w", err)) - } -}) - -var EmvalDecref = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - handle := api.DecodeI32(stack[0]) - err := engine.emvalEngine.allocator.decref(handle) - if err != nil { - panic(fmt.Errorf("could not emval incref: %w", err)) - } -}) - -var EmvalRegisterSymbol = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - address := uint32(api.DecodeI32(stack[0])) - name, err := engine.readCString(address) - if err != nil { - panic(fmt.Errorf("could not get symbol name")) - } - engine.emvalEngine.symbols[address] = name -}) - -var EmvalGetGlobal = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - name := api.DecodeI32(stack[0]) - - if name == 0 { - stack[0] = api.EncodeI32(engine.emvalEngine.toHandle(engine.emvalEngine.getGlobal(""))) - } else { - name, err := engine.getStringOrSymbol(uint32(name)) - if err != nil { - panic(fmt.Errorf("could not get symbol name")) - } - stack[0] = api.EncodeI32(engine.emvalEngine.toHandle(engine.emvalEngine.getGlobal(name))) - } -}) - -var EmvalAs = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - id := api.DecodeI32(stack[0]) - handle, err := engine.emvalEngine.toValue(id) - if err != nil { - panic(fmt.Errorf("could not find handle: %w", err)) - } - - returnType, err := engine.requireRegisteredType(ctx, api.DecodeI32(stack[1]), "emval::as") - if err != nil { - panic(fmt.Errorf("could not require registered type: %w", err)) - } - - var destructors = &[]*destructorFunc{} - rd := engine.emvalEngine.toHandle(destructors) - ok := mod.Memory().WriteUint32Le(uint32(api.DecodeI32(stack[2])), uint32(rd)) - if !ok { - panic(fmt.Errorf("could not write destructor ref to memory")) - } - - returnVal, err := returnType.ToWireType(ctx, mod, destructors, handle) - if err != nil { - panic(fmt.Errorf("could not call toWireType on _emval_as: %w", err)) - } - - stack[0] = returnVal -}) - -var EmvalNew = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - id := api.DecodeI32(stack[0]) - - handle, err := engine.emvalEngine.toValue(id) - if err != nil { - panic(fmt.Errorf("could not get value of handle: %w", err)) - } - - argCount := int(api.DecodeI32(stack[1])) - argsTypeBase := uint32(api.DecodeI32(stack[2])) - argsBase := uint32(api.DecodeI32(stack[3])) - - args := make([]any, argCount) - argTypeNames := make([]string, argCount) - for i := 0; i < argCount; i++ { - argType, ok := mod.Memory().ReadUint32Le(argsTypeBase + (4 * uint32(i))) - if !ok { - panic(fmt.Errorf("could not read arg type for arg %d from memory", i)) - } - - registeredArgType, err := engine.requireRegisteredType(ctx, int32(argType), fmt.Sprintf("argument %d", i)) - if err != nil { - panic(fmt.Errorf("could not require registered type: %w", err)) - } - - args[i], err = registeredArgType.ReadValueFromPointer(ctx, mod, argsBase+(8*uint32(i))) - if err != nil { - panic(fmt.Errorf("could not read arg value from pointer for arg %d, %w", i, err)) - } - - argTypeNames[i] = registeredArgType.Name() - } - - var res any - c, ok := handle.(IEmvalConstructor) - if ok { - res, err = c.New(argTypeNames, args...) - if err != nil { - panic(fmt.Errorf("could not instaniate new value on %T with New(): %w", handle, err)) - } - } else { - typeElem := reflect.TypeOf(handle) - - // If we received a pointer, resolve the struct behind it. - if typeElem.Kind() == reflect.Pointer { - typeElem = typeElem.Elem() - } - - // Make new instance of struct. - newElem := reflect.New(typeElem) - - // Set the values on the struct if we need to/can. - if argCount > 0 { - if typeElem.Kind() != reflect.Struct { - panic(fmt.Errorf("could not instaniate new value of %T: arguments required but can only be set on a struct", handle)) - } - - for i := 0; i < argCount; i++ { - for fieldI := 0; fieldI < typeElem.NumField(); fieldI++ { - var err error - func() { - defer func() { - if recoverErr := recover(); recoverErr != nil { - realError, ok := recoverErr.(error) - if ok { - err = fmt.Errorf("could not set arg %d with embind_arg tag on emval %T: %w", i, handle, realError) - } - err = fmt.Errorf("could not set arg %d with embind_arg tag on emval %T: %v", i, handle, recoverErr) - } - }() - - val := typeElem.Field(fieldI) - if val.Tag.Get("embind_arg") == strconv.Itoa(i) { - f := newElem.Elem().FieldByName(val.Name) - if f.IsValid() && f.CanSet() { - f.Set(reflect.ValueOf(args[i])) - } - } - }() - if err != nil { - panic(fmt.Errorf("could not instaniate new value of %T: %w", handle, err)) - } - } - } - } - - if reflect.TypeOf(handle).Kind() == reflect.Pointer { - res = newElem.Interface() - } else { - res = newElem.Elem().Interface() - } - } - - stack[0] = api.EncodeI32(engine.emvalEngine.toHandle(res)) -}) - -var EmvalSetProperty = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - - handle, err := engine.emvalEngine.toValue(api.DecodeI32(stack[0])) - if err != nil { - panic(fmt.Errorf("could not find handle: %w", err)) - } - - key, err := engine.emvalEngine.toValue(api.DecodeI32(stack[1])) - if err != nil { - panic(fmt.Errorf("could not find key: %w", err)) - } - - val, err := engine.emvalEngine.toValue(api.DecodeI32(stack[2])) - if err != nil { - panic(fmt.Errorf("could not find val: %w", err)) - } - - keyString, ok := key.(string) - if !ok { - panic(fmt.Errorf("could not set property on emval %T: %w", handle, errors.New("key is not of type string"))) - } - - f, err := engine.emvalEngine.getElemField(handle, keyString) - if err != nil { - panic(fmt.Errorf("could not set property %s on emval %T: %w", keyString, handle, err)) - } - - defer func() { - if err := recover(); err != nil { - realError, ok := err.(error) - if ok { - panic(fmt.Errorf("could not set property %s on emval %T: %w", keyString, handle, realError)) - } - panic(fmt.Errorf("could not set property %s on emval %T: %v", keyString, handle, err)) - } - }() - - f.Set(reflect.ValueOf(val)) -}) - -var EmvalGetProperty = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - - handle, err := engine.emvalEngine.toValue(api.DecodeI32(stack[0])) - if err != nil { - panic(fmt.Errorf("could not find handle: %w", err)) - } - - key, err := engine.emvalEngine.toValue(api.DecodeI32(stack[1])) - if err != nil { - panic(fmt.Errorf("could not find key: %w", err)) - } - - keyString, ok := key.(string) - if !ok { - panic(fmt.Errorf("could not get property on emval %T: %w", handle, errors.New("key is not of type string"))) - } - - f, err := engine.emvalEngine.getElemField(handle, keyString) - if err != nil { - panic(fmt.Errorf("could not get property %s on emval %T: %w", keyString, handle, err)) - } - - defer func() { - if err := recover(); err != nil { - realError, ok := err.(error) - if ok { - panic(fmt.Errorf("could not get property %s on emval %T: %w", keyString, handle, realError)) - } - panic(fmt.Errorf("could not get property %s on emval %T: %v", keyString, handle, err)) - } - }() - - stack[0] = api.EncodeI32(engine.emvalEngine.toHandle(f.Interface())) -}) - -var EmvalNewCString = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - v := api.DecodeI32(stack[0]) - name, err := engine.getStringOrSymbol(uint32(v)) - if err != nil { - panic(fmt.Errorf("could not get symbol name")) - } - stack[0] = api.EncodeI32(engine.emvalEngine.toHandle(name)) -}) - -var EmvalRunDestructors = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - id := api.DecodeI32(stack[0]) - destructorsVal, err := engine.emvalEngine.toValue(id) - if err != nil { - panic(fmt.Errorf("could not find handle: %w", err)) - } - - destructors := destructorsVal.(*[]*destructorFunc) - - err = engine.runDestructors(ctx, *destructors) - if err != nil { - panic(fmt.Errorf("could not run destructors: %w", err)) - } - - err = engine.emvalEngine.allocator.decref(id) - if err != nil { - panic(fmt.Errorf("could not run decref id %d: %w", id, err)) - } -}) - -var EmvalGetMethodCaller = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - - argCount := int(api.DecodeI32(stack[0])) - argsTypeBase := uint32(api.DecodeI32(stack[1])) - - typeNames := make([]string, argCount) - argTypes := make([]registeredType, argCount) - for i := 0; i < argCount; i++ { - argType, ok := mod.Memory().ReadUint32Le(argsTypeBase + (4 * uint32(i))) - if !ok { - panic(fmt.Errorf("could not read arg type for arg %d from memory", i)) - } - - registeredType, err := engine.requireRegisteredType(ctx, int32(argType), fmt.Sprintf("argument %d", i)) - if err != nil { - panic(fmt.Errorf("could not require registered type: %w", err)) - } - - typeNames[i] = registeredType.Name() - argTypes[i] = registeredType - } - - signatureName := typeNames[0] + "_$" + strings.Join(typeNames[1:], "_") + "$" - - id, ok := engine.emvalEngine.registeredMethodIds[signatureName] - if ok { - stack[0] = api.EncodeI32(id) - return - } - - newID := engine.emvalEngine.registeredMethodCount - newRegisteredMethod := &emvalRegisteredMethod{ - id: newID, - argTypes: argTypes, - name: signatureName, - } - engine.emvalEngine.registeredMethodIds[signatureName] = newID - engine.emvalEngine.registeredMethods[newID] = newRegisteredMethod - engine.emvalEngine.registeredMethodCount++ - - stack[0] = api.EncodeI32(newID) - return -}) - -var EmvalCallMethod = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - caller := api.DecodeI32(stack[0]) - - registeredMethod, ok := engine.emvalEngine.registeredMethods[caller] - if !ok { - panic(fmt.Errorf("could not call method with ID %d", caller)) - } - - id := api.DecodeI32(stack[1]) - handle, err := engine.emvalEngine.toValue(id) - if err != nil { - panic(fmt.Errorf("could not find handle: %w", err)) - } - - methodName, err := engine.getStringOrSymbol(uint32(api.DecodeI32(stack[2]))) - if err != nil { - panic(fmt.Errorf("could not get symbol name")) - } - - argsBase := uint32(api.DecodeI32(stack[4])) - destructorsRef := uint32(api.DecodeI32(stack[3])) - - res, err := engine.emvalEngine.callMethod(ctx, mod, registeredMethod, handle, methodName, destructorsRef, argsBase) - if err != nil { - panic(fmt.Errorf("could not call %s on %T: %w", methodName, handle, err)) - } - stack[0] = api.EncodeF64(float64(res)) -}) - -var EmvalCallVoidMethod = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - caller := api.DecodeI32(stack[0]) - - registeredMethod, ok := engine.emvalEngine.registeredMethods[caller] - if !ok { - panic(fmt.Errorf("could not call method with ID %d", caller)) - } - - id := api.DecodeI32(stack[1]) - handle, err := engine.emvalEngine.toValue(id) - if err != nil { - panic(fmt.Errorf("could not find handle: %w", err)) - } - - methodName, err := engine.getStringOrSymbol(uint32(api.DecodeI32(stack[2]))) - if err != nil { - panic(fmt.Errorf("could not get symbol name")) - } - - argsBase := uint32(api.DecodeI32(stack[3])) - - _, err = engine.emvalEngine.callMethod(ctx, mod, registeredMethod, handle, methodName, 0, argsBase) - if err != nil { - panic(fmt.Errorf("could not call %s on %T: %w", methodName, handle, err)) - } -}) - -var RegisterClass = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - rawType := api.DecodeI32(stack[0]) - rawPointerType := api.DecodeI32(stack[1]) - rawConstPointerType := api.DecodeI32(stack[2]) - baseClassRawType := api.DecodeI32(stack[3]) - getActualTypeSignature := api.DecodeI32(stack[4]) - getActualType := api.DecodeI32(stack[5]) - upcastSignature := api.DecodeI32(stack[6]) - upcast := api.DecodeI32(stack[7]) - downcastSignature := api.DecodeI32(stack[8]) - downcast := api.DecodeI32(stack[9]) - namePtr := api.DecodeI32(stack[10]) - destructorSignature := api.DecodeI32(stack[11]) - rawDestructor := api.DecodeI32(stack[12]) - - name, err := engine.readCString(uint32(namePtr)) - if err != nil { - panic(fmt.Errorf("could not read name: %w", err)) - } - - getActualTypeFunc, err := engine.newInvokeFunc(getActualTypeSignature, getActualType, []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}) - if err != nil { - panic(fmt.Errorf("could not read getActualType: %w", err)) - } - - var upcastFunc api.Function - if upcast > 0 { - upcastFunc, err = engine.newInvokeFunc(upcastSignature, upcast, []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}) - if err != nil { - panic(fmt.Errorf("could not read upcast: %w", err)) - } - } - - var downcastFunc api.Function - if downcast > 0 { - downcastFunc, err = engine.newInvokeFunc(downcastSignature, downcast, []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}) - if err != nil { - panic(fmt.Errorf("could not read downcast: %w", err)) - } - } - - rawDestructorFunc, err := engine.newInvokeFunc(destructorSignature, rawDestructor, []api.ValueType{api.ValueTypeI32}, []api.ValueType{}) - if err != nil { - panic(fmt.Errorf("could not read rawDestructor: %w", err)) - } - - legalFunctionName := engine.makeLegalFunctionName(name) - - // Set a default callback that errors out when not all types are resolved. - err = engine.exposePublicSymbol(legalFunctionName, func(ctx context.Context, this any, arguments ...any) (any, error) { - return nil, engine.createUnboundTypeError(ctx, fmt.Sprintf("Cannot call %s due to unbound types", name), []int32{baseClassRawType}) - }, nil) - if err != nil { - panic(fmt.Errorf("could not expose public symbol: %w", err)) - } - - dependentTypes := make([]int32, 0) - if baseClassRawType > 0 { - dependentTypes = append(dependentTypes, baseClassRawType) - } - - err = engine.whenDependentTypesAreResolved([]int32{rawType, rawPointerType, rawConstPointerType}, dependentTypes, func(resolvedTypes []registeredType) ([]registeredType, error) { - existingClass, ok := engine.registeredClasses[name] - if ok { - if existingClass.baseType.rawType != 0 { - return nil, fmt.Errorf("could not register class %s, already registered as raw type %d", name, existingClass.baseType.rawType) - } - } else { - engine.registeredClasses[name] = &classType{ - baseType: baseType{ - rawType: rawType, - name: name, - }, - pureVirtualFunctions: []string{}, - methods: map[string]*publicSymbol{}, - properties: map[string]*classProperty{}, - } - } - - engine.registeredClasses[name].hasCppClass = true - engine.registeredClasses[name].legalFunctionName = legalFunctionName - engine.registeredClasses[name].rawDestructor = rawDestructorFunc - engine.registeredClasses[name].getActualType = getActualTypeFunc - engine.registeredClasses[name].upcast = upcastFunc - engine.registeredClasses[name].downcast = downcastFunc - - if baseClassRawType > 0 { - engine.registeredClasses[name].baseClass = resolvedTypes[0].(*registeredPointerType).registeredClass - if engine.registeredClasses[name].baseClass.derivedClasses == nil { - engine.registeredClasses[name].baseClass.derivedClasses = []*classType{engine.registeredClasses[name]} - } else { - engine.registeredClasses[name].baseClass.derivedClasses = append(engine.registeredClasses[name].baseClass.derivedClasses, engine.registeredClasses[name]) - } - } - - referenceConverter := ®isteredPointerType{ - baseType: baseType{ - argPackAdvance: 8, - name: name, - }, - registeredClass: engine.registeredClasses[name], - isReference: true, - isConst: false, - isSmartPointer: false, - } - - pointerConverter := ®isteredPointerType{ - baseType: baseType{ - argPackAdvance: 8, - name: name + "*", - }, - registeredClass: engine.registeredClasses[name], - isReference: false, - isConst: false, - isSmartPointer: false, - } - - constPointerConverter := ®isteredPointerType{ - baseType: baseType{ - argPackAdvance: 8, - name: name + " const*", - }, - registeredClass: engine.registeredClasses[name], - isReference: false, - isConst: true, - isSmartPointer: false, - } - - engine.registeredPointers[rawType] = ®isteredPointer{ - pointerType: pointerConverter, - constPointerType: constPointerConverter, - } - - err := engine.registeredClasses[name].validate() - if err != nil { - return nil, err - } - - err = engine.replacePublicSymbol(legalFunctionName, func(ctx context.Context, _ any, arguments ...any) (any, error) { - if engine.registeredClasses[name].constructors == nil { - return nil, fmt.Errorf("%s has no accessible constructor", name) - } - - constructor, ok := engine.registeredClasses[name].constructors[int32(len(arguments))] - if !ok { - availableLengths := make([]string, 0) - for i := range engine.registeredClasses[name].constructors { - availableLengths = append(availableLengths, strconv.Itoa(int(i))) - } - return nil, fmt.Errorf("tried to invoke ctor of %s with invalid number of parameters (%d) - expected (%s) parameters instead", name, len(arguments), strings.Join(availableLengths, " or ")) - } - - return constructor.fn(ctx, nil, arguments...) - }, nil, nil, referenceConverter) - - if err != nil { - panic(fmt.Errorf("could not replace public symbol: %w", err)) - } - - return []registeredType{referenceConverter, pointerConverter, constPointerConverter}, nil - }) - - if err != nil { - panic(fmt.Errorf("could not call whenDependentTypesAreResolved: %w", err)) - } -}) - -var RegisterClassConstructor = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - rawClassType := api.DecodeI32(stack[0]) - argCount := api.DecodeI32(stack[1]) - rawArgTypesAddr := api.DecodeI32(stack[2]) - invokerSignature := api.DecodeI32(stack[3]) - invoker := api.DecodeI32(stack[4]) - rawConstructor := api.DecodeI32(stack[5]) - - rawArgTypes, err := engine.heap32VectorToArray(argCount, rawArgTypesAddr) - if err != nil { - panic(fmt.Errorf("could not read arg types: %w", err)) - } - - err = engine.whenDependentTypesAreResolved([]int32{}, []int32{rawClassType}, func(resolvedTypes []registeredType) ([]registeredType, error) { - classType := resolvedTypes[0].(*registeredPointerType) - humanName := "constructor " + classType.name - - if classType.registeredClass.constructors == nil { - classType.registeredClass.constructors = map[int32]*classConstructor{} - } - - if _, ok := classType.registeredClass.constructors[argCount-1]; ok { - return nil, fmt.Errorf("cannot register multiple constructors with identical number of parameters (%d) for class '%s'! Overload resolution is currently only performed using the parameter count, not actual type info", argCount-1, classType.name) - } - - classType.registeredClass.constructors[argCount-1] = &classConstructor{ - fn: func(ctx context.Context, this any, arguments ...any) (any, error) { - return nil, engine.createUnboundTypeError(ctx, fmt.Sprintf("Cannot call %s due to unbound types", classType.name), rawArgTypes) - }, - } - - err := engine.whenDependentTypesAreResolved([]int32{}, rawArgTypes, func(argTypes []registeredType) ([]registeredType, error) { - // Insert empty slot for context type (argTypes[1]). - newArgTypes := []registeredType{argTypes[0], nil} - if len(argTypes) > 1 { - newArgTypes = append(newArgTypes, argTypes[1:]...) - } - - expectedParamTypes := make([]api.ValueType, len(newArgTypes[2:])+1) - expectedParamTypes[0] = api.ValueTypeI32 // fn - for i := range newArgTypes[2:] { - expectedParamTypes[i+1] = newArgTypes[i+2].NativeType() - } - - invokerFunc, err := engine.newInvokeFunc(invokerSignature, invoker, expectedParamTypes, []api.ValueType{argTypes[0].NativeType()}) - if err != nil { - return nil, fmt.Errorf("could not create invoke func: %w", err) - } - - classType.registeredClass.constructors[argCount-1].resultType = argTypes[0] - classType.registeredClass.constructors[argCount-1].argumentTypes = argTypes[1:] - classType.registeredClass.constructors[argCount-1].fn = engine.craftInvokerFunction(humanName, newArgTypes, nil, invokerFunc, rawConstructor, false) - return []registeredType{}, err - }) - - return []registeredType{}, err - }) - - if err != nil { - panic(fmt.Errorf("could not call whenDependentTypesAreResolved: %w", err)) - } -}) - -var RegisterClassFunction = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - rawClassType := api.DecodeI32(stack[0]) - methodNamePtr := api.DecodeI32(stack[1]) - argCount := api.DecodeI32(stack[2]) - rawArgTypesAddr := api.DecodeI32(stack[3]) - invokerSignature := api.DecodeI32(stack[4]) - rawInvoker := api.DecodeI32(stack[5]) - contextPtr := api.DecodeI32(stack[6]) - isPureVirtual := api.DecodeI32(stack[7]) - isAsync := api.DecodeI32(stack[8]) - - rawArgTypes, err := engine.heap32VectorToArray(argCount, rawArgTypesAddr) - if err != nil { - panic(fmt.Errorf("could not read arg types: %w", err)) - } - - methodName, err := engine.readCString(uint32(methodNamePtr)) - if err != nil { - panic(fmt.Errorf("could not read method name: %w", err)) - } - - err = engine.whenDependentTypesAreResolved([]int32{}, []int32{rawClassType}, func(classTypes []registeredType) ([]registeredType, error) { - classType := classTypes[0].(*registeredPointerType) - humanName := classType.Name() + "." + methodName - - if strings.HasPrefix(methodName, "@@") { - methodName = engine.emvalEngine.globals[strings.TrimPrefix(methodName, "@@")].(string) - } - - if isPureVirtual > 0 { - classType.registeredClass.pureVirtualFunctions = append(classType.registeredClass.pureVirtualFunctions, methodName) - } - - unboundTypesHandler := &publicSymbol{ - fn: func(ctx context.Context, this any, arguments ...any) (any, error) { - return nil, engine.createUnboundTypeError(ctx, fmt.Sprintf("Cannot call %s due to unbound types", humanName), rawArgTypes) - }, - } - - newMethodArgCount := argCount - 2 - existingMethod, ok := classType.registeredClass.methods[methodName] - if !ok || (existingMethod.overloadTable == nil && existingMethod.className != classType.name && *existingMethod.argCount == newMethodArgCount) { - // This is the first overload to be registered, OR we are replacing a - // function in the base class with a function in the derived class. - unboundTypesHandler.argCount = &newMethodArgCount - unboundTypesHandler.className = classType.name - classType.registeredClass.methods[methodName] = unboundTypesHandler - } else { - // There was an existing function with the same name registered. Set up - // a function overload routing table. - engine.ensureOverloadTable(classType.registeredClass.methods, methodName, humanName) - classType.registeredClass.methods[methodName].overloadTable[argCount-2] = unboundTypesHandler - } - - err = engine.whenDependentTypesAreResolved([]int32{}, rawArgTypes, func(argTypes []registeredType) ([]registeredType, error) { - expectedResultTypes := make([]api.ValueType, len(argTypes)) - expectedResultTypes[0] = api.ValueTypeI32 // contextPtr - for i := range argTypes[1:] { - expectedResultTypes[i+1] = argTypes[i+1].NativeType() - } - - rawInvokerFunc, err := engine.newInvokeFunc(invokerSignature, rawInvoker, expectedResultTypes, []api.ValueType{argTypes[0].NativeType()}) - if err != nil { - panic(fmt.Errorf("could not create _embind_register_class_function raw invoke func: %w", err)) - } - - memberFunction := &publicSymbol{ - name: methodName, - resultType: argTypes[0], - argumentTypes: argTypes[2:], - fn: engine.craftInvokerFunction(humanName, argTypes, classType, rawInvokerFunc, contextPtr, isAsync > 0), - } - - // Replace the initial unbound-handler-stub function with the appropriate member function, now that all types - // are resolved. If multiple overloads are registered for this function, the function goes into an overload table. - if classType.registeredClass.methods[methodName].overloadTable == nil { - // Set argCount in case an overload is registered later - memberFunction.argCount = &newMethodArgCount - classType.registeredClass.methods[methodName] = memberFunction - } else { - classType.registeredClass.methods[methodName].overloadTable[argCount-2] = memberFunction - } - - return []registeredType{}, nil - }) - - return []registeredType{}, err - }) - - if err != nil { - panic(fmt.Errorf("could not call whenDependentTypesAreResolved: %w", err)) - } -}) - -var RegisterClassClassFunction = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - rawClassType := api.DecodeI32(stack[0]) - methodNamePtr := api.DecodeI32(stack[1]) - argCount := api.DecodeI32(stack[2]) - rawArgTypesAddr := api.DecodeI32(stack[3]) - invokerSignature := api.DecodeI32(stack[4]) - rawInvoker := api.DecodeI32(stack[5]) - fn := api.DecodeI32(stack[6]) - isAsync := api.DecodeI32(stack[7]) - - rawArgTypes, err := engine.heap32VectorToArray(argCount, rawArgTypesAddr) - if err != nil { - panic(fmt.Errorf("could not read arg types: %w", err)) - } - - methodName, err := engine.readCString(uint32(methodNamePtr)) - if err != nil { - panic(fmt.Errorf("could not read method name: %w", err)) - } - - err = engine.whenDependentTypesAreResolved([]int32{}, []int32{rawClassType}, func(classTypes []registeredType) ([]registeredType, error) { - classType := classTypes[0].(*registeredPointerType) - humanName := classType.Name() + "." + methodName - - if strings.HasPrefix(methodName, "@@") { - methodName = engine.emvalEngine.globals[strings.TrimPrefix(methodName, "@@")].(string) - } - - unboundTypesHandler := &publicSymbol{ - fn: func(ctx context.Context, this any, arguments ...any) (any, error) { - return nil, engine.createUnboundTypeError(ctx, fmt.Sprintf("Cannot call %s due to unbound types", humanName), rawArgTypes) - }, - } - - newArgCount := argCount - 1 - _, ok := classType.registeredClass.methods[methodName] - if !ok { - // This is the first function to be registered with this name. - unboundTypesHandler.argCount = &newArgCount - classType.registeredClass.methods[methodName] = unboundTypesHandler - } else { - // There was an existing function with the same name registered. Set up - // a function overload routing table. - engine.ensureOverloadTable(classType.registeredClass.methods, methodName, humanName) - classType.registeredClass.methods[methodName].overloadTable[argCount-1] = unboundTypesHandler - } - - err = engine.whenDependentTypesAreResolved([]int32{}, rawArgTypes, func(argTypes []registeredType) ([]registeredType, error) { - invokerArgsArray := []registeredType{argTypes[0], nil} - invokerArgsArray = append(invokerArgsArray, argTypes[1:]...) - - expectedParamTypes := make([]api.ValueType, len(invokerArgsArray[2:])+1) - expectedParamTypes[0] = api.ValueTypeI32 // fn - for i := range invokerArgsArray[2:] { - expectedParamTypes[i+1] = invokerArgsArray[i+2].NativeType() - } - - rawInvokerFunc, err := engine.newInvokeFunc(invokerSignature, rawInvoker, expectedParamTypes, []api.ValueType{argTypes[0].NativeType()}) - if err != nil { - panic(fmt.Errorf("could not create raw invoke func: %w", err)) - } - - memberFunction := &publicSymbol{ - name: methodName, - argumentTypes: argTypes[1:], - resultType: argTypes[0], - isStatic: true, - fn: engine.craftInvokerFunction(humanName, invokerArgsArray, nil, rawInvokerFunc, fn, isAsync > 0), - } - - // Replace the initial unbound-handler-stub function with the appropriate member function, now that all types - // are resolved. If multiple overloads are registered for this function, the function goes into an overload table. - if classType.registeredClass.methods[methodName].overloadTable == nil { - // Set argCount in case an overload is registered later - memberFunction.argCount = &newArgCount - classType.registeredClass.methods[methodName] = memberFunction - } else { - classType.registeredClass.methods[methodName].overloadTable[argCount-1] = memberFunction - } - - if classType.registeredClass.derivedClasses != nil { - for i := range classType.registeredClass.derivedClasses { - derivedClass := classType.registeredClass.derivedClasses[i] - _, ok := derivedClass.methods[methodName] - if !ok { - // TODO: Add support for overloads (comment from Emscripten) - derivedClass.methods[methodName] = memberFunction - } - } - } - - return []registeredType{}, nil - }) - - return []registeredType{}, err - }) - if err != nil { - panic(fmt.Errorf("could not call whenDependentTypesAreResolved: %w", err)) - } -}) - -var RegisterClassProperty = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - classType := api.DecodeI32(stack[0]) - fieldNamePtr := api.DecodeI32(stack[1]) - getterReturnType := api.DecodeI32(stack[2]) - getterSignature := api.DecodeI32(stack[3]) - getter := api.DecodeI32(stack[4]) - getterContext := api.DecodeI32(stack[5]) - setterArgumentType := api.DecodeI32(stack[6]) - setterSignature := api.DecodeI32(stack[7]) - setter := api.DecodeI32(stack[8]) - setterContext := api.DecodeI32(stack[9]) - - fieldName, err := engine.readCString(uint32(fieldNamePtr)) - if err != nil { - panic(fmt.Errorf("could not read method name: %w", err)) - } - - err = engine.whenDependentTypesAreResolved([]int32{}, []int32{classType}, func(classTypes []registeredType) ([]registeredType, error) { - classType := classTypes[0].(*registeredPointerType) - humanName := classType.Name() + "." + fieldName - - desc := &classProperty{ - name: fieldName, - get: func(ctx context.Context, this any) (any, error) { - return nil, engine.createUnboundTypeError(ctx, fmt.Sprintf("Cannot access %s due to unbound types", humanName), []int32{getterReturnType, setterArgumentType}) - }, - enumerable: true, - configurable: true, - } - - if setter > 0 { - desc.set = func(ctx context.Context, this any, v any) error { - return engine.createUnboundTypeError(ctx, fmt.Sprintf("Cannot access %s due to unbound types", humanName), []int32{getterReturnType, setterArgumentType}) - } - } else { - desc.readOnly = true - desc.set = func(ctx context.Context, this any, v any) error { - return fmt.Errorf("%s is a read-only property", humanName) - } - } - - classType.registeredClass.properties[fieldName] = desc - - requiredTypes := []int32{getterReturnType} - if setter > 0 { - requiredTypes = append(requiredTypes, setterArgumentType) - } - - err = engine.whenDependentTypesAreResolved([]int32{}, requiredTypes, func(types []registeredType) ([]registeredType, error) { - getterReturnType := types[0] - - getterFunc, err := engine.newInvokeFunc(getterSignature, getter, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{getterReturnType.NativeType()}) - if err != nil { - return nil, fmt.Errorf("could not create _embind_register_class_property getterFunc: %w", err) - } - - desc := &classProperty{ - name: fieldName, - getterType: getterReturnType, - get: func(ctx context.Context, this any) (any, error) { - ptr, err := engine.validateThis(ctx, this, classType, humanName+" getter") - if err != nil { - return nil, err - } - - res, err := getterFunc.Call(ctx, api.EncodeI32(getterContext), api.EncodeU32(ptr)) - if err != nil { - return nil, err - } - return getterReturnType.FromWireType(ctx, engine.mod, res[0]) - }, - enumerable: true, - } - - if setter > 0 { - setterArgumentType := types[1] - setterFunc, err := engine.newInvokeFunc(setterSignature, setter, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, setterArgumentType.NativeType()}, []api.ValueType{}) - if err != nil { - return nil, fmt.Errorf("could not create _embind_register_class_property setterFunc: %w", err) - } - - desc.setterType = setterArgumentType - desc.set = func(ctx context.Context, this any, v any) error { - ptr, err := engine.validateThis(ctx, this, classType, humanName+" setter") - if err != nil { - return err - } - - destructors := &[]*destructorFunc{} - setterRes, err := setterArgumentType.ToWireType(ctx, engine.mod, destructors, v) - if err != nil { - return err - } - - _, err = setterFunc.Call(ctx, api.EncodeI32(setterContext), api.EncodeU32(ptr), setterRes) - if err != nil { - return err - } - - err = engine.runDestructors(ctx, *destructors) - if err != nil { - return err - } - - return nil - } - } - - classType.registeredClass.properties[fieldName] = desc - - return []registeredType{}, err - }) - - return []registeredType{}, err - }) - if err != nil { - panic(fmt.Errorf("could not call whenDependentTypesAreResolved: %w", err)) - } -}) - -var RegisterValueArray = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - rawType := api.DecodeI32(stack[0]) - namePtr := api.DecodeI32(stack[1]) - constructorSignature := api.DecodeI32(stack[2]) - rawConstructor := api.DecodeI32(stack[3]) - destructorSignature := api.DecodeI32(stack[4]) - rawDestructor := api.DecodeI32(stack[5]) - - name, err := engine.readCString(uint32(namePtr)) - if err != nil { - panic(fmt.Errorf("could not read name: %w", err)) - } - - rawConstructorFunc, err := engine.newInvokeFunc(constructorSignature, rawConstructor, []api.ValueType{}, []api.ValueType{api.ValueTypeI32}) - if err != nil { - panic(fmt.Errorf("could not create rawConstructorFunc: %w", err)) - } - - rawDestructorFunc, err := engine.newInvokeFunc(destructorSignature, rawDestructor, []api.ValueType{api.ValueTypeI32}, []api.ValueType{}) - if err != nil { - panic(fmt.Errorf("could not create rawDestructorFunc: %w", err)) - } - - engine.registeredTuples[rawType] = ®isteredTuple{ - name: name, - rawConstructor: rawConstructorFunc, - rawDestructor: rawDestructorFunc, - elements: []*registeredTupleElement{}, - } -}) - -var RegisterValueArrayElement = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - rawTupleType := api.DecodeI32(stack[0]) - getterReturnType := api.DecodeI32(stack[1]) - getterSignature := api.DecodeI32(stack[2]) - getter := api.DecodeI32(stack[3]) - getterContext := api.DecodeI32(stack[4]) - setterArgumentType := api.DecodeI32(stack[5]) - setterSignature := api.DecodeI32(stack[6]) - setter := api.DecodeI32(stack[7]) - setterContext := api.DecodeI32(stack[8]) - - engine.registeredTuples[rawTupleType].elements = append(engine.registeredTuples[rawTupleType].elements, ®isteredTupleElement{ - getter: getter, - getterSignature: getterSignature, - getterReturnType: getterReturnType, - getterContext: getterContext, - setter: setter, - setterSignature: setterSignature, - setterArgumentType: setterArgumentType, - setterContext: setterContext, - }) -}) - -var FinalizeValueArray = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - rawTupleType := api.DecodeI32(stack[0]) - reg := engine.registeredTuples[rawTupleType] - delete(engine.registeredTuples, rawTupleType) - elements := reg.elements - elementsLength := len(elements) - - elementTypes := make([]int32, len(elements)*2) - for i := range elements { - elementTypes[i] = elements[i].getterReturnType - elementTypes[i+len(elements)] = elements[i].setterArgumentType - } - - err := engine.whenDependentTypesAreResolved([]int32{rawTupleType}, elementTypes, func(types []registeredType) ([]registeredType, error) { - for i := range elements { - getterReturnType := types[i] - - getterFunc, err := engine.newInvokeFunc(elements[i].getterSignature, elements[i].getter, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{getterReturnType.NativeType()}) - if err != nil { - return nil, fmt.Errorf("could not create getterFunc: %w", err) - } - - setterArgumentType := types[i+len(elements)] - setterFunc, err := engine.newInvokeFunc(elements[i].setterSignature, elements[i].setter, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, setterArgumentType.NativeType()}, []api.ValueType{}) - if err != nil { - return nil, fmt.Errorf("could not create setterFunc: %w", err) - } - - elements[i].read = func(ctx context.Context, mod api.Module, ptr int32) (any, error) { - res, err := getterFunc.Call(ctx, api.EncodeI32(elements[i].getterContext), api.EncodeI32(ptr)) - if err != nil { - return nil, err - } - return getterReturnType.FromWireType(ctx, mod, res[0]) - } - elements[i].write = func(ctx context.Context, mod api.Module, ptr int32, o any) error { - destructors := &[]*destructorFunc{} - res, err := setterArgumentType.ToWireType(ctx, mod, destructors, o) - if err != nil { - return err - } - - _, err = setterFunc.Call(ctx, api.EncodeI32(elements[i].setterContext), api.EncodeI32(ptr), res) - if err != nil { - return err - } - - err = engine.runDestructors(ctx, *destructors) - if err != nil { - return err - } - - return nil - } - } - - return []registeredType{ - &arrayType{ - baseType: baseType{ - rawType: rawTupleType, - name: reg.name, - argPackAdvance: 8, - }, - reg: reg, - elementsLength: elementsLength, - }, - }, nil - }) - if err != nil { - panic(fmt.Errorf("could not call whenDependentTypesAreResolved: %w", err)) - } -}) - -var RegisterValueObject = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - rawType := api.DecodeI32(stack[0]) - namePtr := api.DecodeI32(stack[1]) - constructorSignature := api.DecodeI32(stack[2]) - rawConstructor := api.DecodeI32(stack[3]) - destructorSignature := api.DecodeI32(stack[4]) - rawDestructor := api.DecodeI32(stack[5]) - - name, err := engine.readCString(uint32(namePtr)) - if err != nil { - panic(fmt.Errorf("could not read name: %w", err)) - } - - rawConstructorFunc, err := engine.newInvokeFunc(constructorSignature, rawConstructor, []api.ValueType{}, []api.ValueType{api.ValueTypeI32}) - if err != nil { - panic(fmt.Errorf("could not create rawConstructorFunc: %w", err)) - } - - rawDestructorFunc, err := engine.newInvokeFunc(destructorSignature, rawDestructor, []api.ValueType{api.ValueTypeI32}, []api.ValueType{}) - if err != nil { - panic(fmt.Errorf("could not create rawDestructorFunc: %w", err)) - } - - engine.registeredObjects[rawType] = ®isteredObject{ - name: name, - rawConstructor: rawConstructorFunc, - rawDestructor: rawDestructorFunc, - fields: []*registeredObjectField{}, - } -}) - -var RegisterValueObjectField = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - structType := api.DecodeI32(stack[0]) - fieldNamePtr := api.DecodeI32(stack[1]) - getterReturnType := api.DecodeI32(stack[2]) - getterSignature := api.DecodeI32(stack[3]) - getter := api.DecodeI32(stack[4]) - getterContext := api.DecodeI32(stack[5]) - setterArgumentType := api.DecodeI32(stack[6]) - setterSignature := api.DecodeI32(stack[7]) - setter := api.DecodeI32(stack[8]) - setterContext := api.DecodeI32(stack[9]) - - fieldName, err := engine.readCString(uint32(fieldNamePtr)) - if err != nil { - panic(fmt.Errorf("could not read field name: %w", err)) - } - - engine.registeredObjects[structType].fields = append(engine.registeredObjects[structType].fields, ®isteredObjectField{ - fieldName: fieldName, - getterReturnType: getterReturnType, - getter: getter, - getterSignature: getterSignature, - getterContext: getterContext, - setterArgumentType: setterArgumentType, - setter: setter, - setterSignature: setterSignature, - setterContext: setterContext, - }) -}) - -var FinalizeValueObject = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - structType := api.DecodeI32(stack[0]) - reg := engine.registeredObjects[structType] - delete(engine.registeredObjects, structType) - fieldRecords := reg.fields - - fieldTypes := make([]int32, len(fieldRecords)*2) - for i := range fieldRecords { - fieldTypes[i] = fieldRecords[i].getterReturnType - fieldTypes[i+len(fieldRecords)] = fieldRecords[i].setterArgumentType - } - - err := engine.whenDependentTypesAreResolved([]int32{structType}, fieldTypes, func(types []registeredType) ([]registeredType, error) { - for i := range fieldRecords { - getterReturnType := types[i] - getterFunc, err := engine.newInvokeFunc(fieldRecords[i].getterSignature, fieldRecords[i].getter, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{getterReturnType.NativeType()}) - if err != nil { - panic(fmt.Errorf("could not create getterFunc: %w", err)) - } - - fieldRecords[i].read = func(ctx context.Context, mod api.Module, ptr int32) (any, error) { - res, err := getterFunc.Call(ctx, api.EncodeI32(fieldRecords[i].getterContext), api.EncodeI32(ptr)) - if err != nil { - return nil, err - } - return getterReturnType.FromWireType(ctx, mod, res[0]) - } - - setterArgumentType := types[i+len(fieldRecords)] - setterFunc, err := engine.newInvokeFunc(fieldRecords[i].setterSignature, fieldRecords[i].setter, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, setterArgumentType.NativeType()}, []api.ValueType{}) - if err != nil { - panic(fmt.Errorf("could not create setterFunc: %w", err)) - } - - fieldRecords[i].write = func(ctx context.Context, mod api.Module, ptr int32, o any) error { - destructors := &[]*destructorFunc{} - res, err := setterArgumentType.ToWireType(ctx, mod, destructors, o) - if err != nil { - return err - } - - _, err = setterFunc.Call(ctx, api.EncodeI32(fieldRecords[i].setterContext), api.EncodeI32(ptr), res) - if err != nil { - return err - } - - err = engine.runDestructors(ctx, *destructors) - if err != nil { - return err - } - - return nil - } - } - - return []registeredType{ - &objectType{ - baseType: baseType{ - rawType: structType, - name: reg.name, - argPackAdvance: 8, - }, - reg: reg, - }, - }, nil - }) - if err != nil { - panic(fmt.Errorf("could not call whenDependentTypesAreResolved: %w", err)) - } -}) diff --git a/internal/int.go b/internal/int.go index 3a136e6..4cbfa9a 100644 --- a/internal/int.go +++ b/internal/int.go @@ -3,6 +3,7 @@ package embind import ( "context" "fmt" + "strings" "github.com/tetratelabs/wazero/api" ) @@ -136,6 +137,10 @@ func (it *intType) GoType() string { return "int32" } +func (it *intType) DestructorFunctionUndefined() bool { + return false +} + func (it *intType) FromF64(o float64) uint64 { if it.size == 1 { if !it.signed { @@ -154,3 +159,26 @@ func (it *intType) FromF64(o float64) uint64 { } return api.EncodeI32(int32(o)) } + +var RegisterInteger = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + + rawType := api.DecodeI32(stack[0]) + name, err := engine.readCString(uint32(api.DecodeI32(stack[1]))) + if err != nil { + panic(fmt.Errorf("could not read name: %w", err)) + } + + err = engine.registerType(rawType, &intType{ + baseType: baseType{ + rawType: rawType, + name: name, + argPackAdvance: 8, + }, + size: api.DecodeI32(stack[2]), + signed: !strings.Contains(name, "unsigned"), + }, nil) + if err != nil { + panic(fmt.Errorf("could not register: %w", err)) + } +}) diff --git a/internal/memory_view.go b/internal/memory_view.go index a74e13c..44a91eb 100644 --- a/internal/memory_view.go +++ b/internal/memory_view.go @@ -33,25 +33,25 @@ func (mvt *memoryViewType) FromWireType(ctx context.Context, mod api.Module, val var typedMemoryView any if mvt.dataTypeIndex == 0 { - typedMemoryView, ok = memoryAs[int8](mod.Memory(), pointer, size, size*mvt.nativeSize) + typedMemoryView, ok = memoryAs[int8](mod.Memory(), pointer, mvt.nativeSize, size) } else if mvt.dataTypeIndex == 1 { - typedMemoryView, ok = memoryAs[uint8](mod.Memory(), pointer, size, size*mvt.nativeSize) + typedMemoryView, ok = memoryAs[uint8](mod.Memory(), pointer, mvt.nativeSize, size) } else if mvt.dataTypeIndex == 2 { - typedMemoryView, ok = memoryAs[int16](mod.Memory(), pointer, size, size*mvt.nativeSize) + typedMemoryView, ok = memoryAs[int16](mod.Memory(), pointer, mvt.nativeSize, size) } else if mvt.dataTypeIndex == 3 { - typedMemoryView, ok = memoryAs[uint16](mod.Memory(), pointer, size, size*mvt.nativeSize) + typedMemoryView, ok = memoryAs[uint16](mod.Memory(), pointer, mvt.nativeSize, size) } else if mvt.dataTypeIndex == 4 { - typedMemoryView, ok = memoryAs[int32](mod.Memory(), pointer, size, size*mvt.nativeSize) + typedMemoryView, ok = memoryAs[int32](mod.Memory(), pointer, mvt.nativeSize, size) } else if mvt.dataTypeIndex == 5 { - typedMemoryView, ok = memoryAs[uint8](mod.Memory(), pointer, size, size*mvt.nativeSize) + typedMemoryView, ok = memoryAs[uint32](mod.Memory(), pointer, mvt.nativeSize, size) } else if mvt.dataTypeIndex == 6 { - typedMemoryView, ok = memoryAs[float32](mod.Memory(), pointer, size, size*mvt.nativeSize) + typedMemoryView, ok = memoryAs[float32](mod.Memory(), pointer, mvt.nativeSize, size) } else if mvt.dataTypeIndex == 7 { - typedMemoryView, ok = memoryAs[float64](mod.Memory(), pointer, size, size*mvt.nativeSize) + typedMemoryView, ok = memoryAs[float64](mod.Memory(), pointer, mvt.nativeSize, size) } else if mvt.dataTypeIndex == 8 { - typedMemoryView, ok = memoryAs[int64](mod.Memory(), pointer, size, size*mvt.nativeSize) + typedMemoryView, ok = memoryAs[int64](mod.Memory(), pointer, mvt.nativeSize, size) } else if mvt.dataTypeIndex == 9 { - typedMemoryView, ok = memoryAs[uint64](mod.Memory(), pointer, size, size*mvt.nativeSize) + typedMemoryView, ok = memoryAs[uint64](mod.Memory(), pointer, mvt.nativeSize, size) } else { return nil, fmt.Errorf("unknown memory view type %s", mvt.name) } @@ -63,13 +63,13 @@ func (mvt *memoryViewType) FromWireType(ctx context.Context, mod api.Module, val return typedMemoryView, nil } -func memoryAs[T any](memory api.Memory, offset uint32, size uint32, length uint32) ([]T, bool) { - memoryView, ok := memory.Read(offset, length) +func memoryAs[T any](memory api.Memory, offset uint32, elementSize uint32, length uint32) ([]T, bool) { + memoryView, ok := memory.Read(offset, elementSize*length) if !ok { return nil, ok } - return unsafe.Slice((*T)(unsafe.Pointer(&memoryView[0])), size), true + return unsafe.Slice((*T)(unsafe.Pointer(&memoryView[0])), length), true } func (mvt *memoryViewType) ToWireType(ctx context.Context, mod api.Module, destructors *[]*destructorFunc, o any) (uint64, error) { @@ -92,7 +92,7 @@ func (mvt *memoryViewType) GoType() string { } else if mvt.dataTypeIndex == 4 { return "[]int32" } else if mvt.dataTypeIndex == 5 { - return "[]uint8" + return "[]uint32" } else if mvt.dataTypeIndex == 6 { return "[]float32" } else if mvt.dataTypeIndex == 7 { @@ -105,3 +105,60 @@ func (mvt *memoryViewType) GoType() string { return "[]uint64" } + +var RegisterMemoryView = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + + rawType := api.DecodeI32(stack[0]) + dataTypeIndex := api.DecodeI32(stack[1]) + name, err := engine.readCString(uint32(api.DecodeI32(stack[2]))) + if err != nil { + panic(fmt.Errorf("could not read name: %w", err)) + } + + typeMapping := []any{ + int8(0), + uint8(0), + int16(0), + uint16(0), + int32(0), + uint32(0), + float32(0), + float64(0), + int64(0), + uint64(0), + } + + if dataTypeIndex < 0 || int(dataTypeIndex) >= len(typeMapping) { + panic(fmt.Errorf("invalid memory view data type index: %d", dataTypeIndex)) + } + + sizeMapping := []uint32{ + 1, // int8 + 1, // uint8 + 2, // int16 + 2, // uint16 + 4, // int32 + 4, // uint32 + 4, // float32 + 8, // float64 + 8, // int64 + 8, // uint64 + } + + err = engine.registerType(rawType, &memoryViewType{ + baseType: baseType{ + rawType: rawType, + name: name, + argPackAdvance: 8, + }, + dataTypeIndex: dataTypeIndex, + nativeSize: sizeMapping[dataTypeIndex], + nativeType: typeMapping[dataTypeIndex], + }, ®isterTypeOptions{ + ignoreDuplicateRegistrations: true, + }) + if err != nil { + panic(fmt.Errorf("could not register: %w", err)) + } +}) diff --git a/internal/object.go b/internal/object.go index 1330265..f7864dc 100644 --- a/internal/object.go +++ b/internal/object.go @@ -19,6 +19,9 @@ func (ot *objectType) FromWireType(ctx context.Context, mod api.Module, ptr uint for i := range ot.reg.fields { rv[ot.reg.fields[i].fieldName], err = ot.reg.fields[i].read(ctx, mod, api.DecodeI32(ptr)) + if err != nil { + return nil, err + } } _, err = ot.reg.rawDestructor.Call(ctx, ptr) @@ -32,7 +35,7 @@ func (ot *objectType) FromWireType(ctx context.Context, mod api.Module, ptr uint func (ot *objectType) ToWireType(ctx context.Context, mod api.Module, destructors *[]*destructorFunc, o any) (uint64, error) { obj, ok := o.(map[string]any) if !ok { - return 0, fmt.Errorf("incorrect input, not an string map") + return 0, fmt.Errorf("incorrect input, not a map[string]any") } for i := range ot.reg.fields { @@ -46,10 +49,10 @@ func (ot *objectType) ToWireType(ctx context.Context, mod api.Module, destructor return 0, err } - ptr := res[0] + ptr := api.DecodeU32(res[0]) for i := range ot.reg.fields { - err = ot.reg.fields[i].write(ctx, mod, api.DecodeI32(ptr), obj[ot.reg.fields[i].fieldName]) + err = ot.reg.fields[i].write(ctx, mod, int32(ptr), obj[ot.reg.fields[i].fieldName]) if err != nil { return 0, err } @@ -57,13 +60,11 @@ func (ot *objectType) ToWireType(ctx context.Context, mod api.Module, destructor if destructors != nil { destructorsRef := *destructors - destructorsRef = append(destructorsRef, &destructorFunc{ - apiFunction: ot.reg.rawDestructor, - args: []uint64{ptr}, - }) + destructorsRef = append(destructorsRef, ot.DestructorFunction(ctx, mod, ptr)) *destructors = destructorsRef } - return ptr, nil + + return api.EncodeU32(ptr), nil } func (ot *objectType) ReadValueFromPointer(ctx context.Context, mod api.Module, pointer uint32) (any, error) { @@ -74,17 +75,157 @@ func (ot *objectType) ReadValueFromPointer(ctx context.Context, mod api.Module, return ot.FromWireType(ctx, mod, api.EncodeU32(ptr)) } -func (ot *objectType) HasDestructorFunction() bool { - return true +func (ot *objectType) DestructorFunctionUndefined() bool { + return false } -func (ot *objectType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) (*destructorFunc, error) { +func (ot *objectType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) *destructorFunc { return &destructorFunc{ apiFunction: ot.reg.rawDestructor, args: []uint64{api.EncodeU32(pointer)}, - }, nil + } } func (ot *objectType) GoType() string { return "map[string]any" } + +func (ot *objectType) FromF64(o float64) uint64 { + return uint64(o) +} + +var RegisterValueObject = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + rawType := api.DecodeI32(stack[0]) + namePtr := api.DecodeI32(stack[1]) + constructorSignature := api.DecodeI32(stack[2]) + rawConstructor := api.DecodeI32(stack[3]) + destructorSignature := api.DecodeI32(stack[4]) + rawDestructor := api.DecodeI32(stack[5]) + + name, err := engine.readCString(uint32(namePtr)) + if err != nil { + panic(fmt.Errorf("could not read name: %w", err)) + } + + rawConstructorFunc, err := engine.newInvokeFunc(constructorSignature, rawConstructor, []api.ValueType{}, []api.ValueType{api.ValueTypeI32}) + if err != nil { + panic(fmt.Errorf("could not create rawConstructorFunc: %w", err)) + } + + rawDestructorFunc, err := engine.newInvokeFunc(destructorSignature, rawDestructor, []api.ValueType{api.ValueTypeI32}, []api.ValueType{}) + if err != nil { + panic(fmt.Errorf("could not create rawDestructorFunc: %w", err)) + } + + engine.registeredObjects[rawType] = ®isteredObject{ + name: name, + rawConstructor: rawConstructorFunc, + rawDestructor: rawDestructorFunc, + fields: []*registeredObjectField{}, + } +}) + +var RegisterValueObjectField = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + structType := api.DecodeI32(stack[0]) + fieldNamePtr := api.DecodeI32(stack[1]) + getterReturnType := api.DecodeI32(stack[2]) + getterSignature := api.DecodeI32(stack[3]) + getter := api.DecodeI32(stack[4]) + getterContext := api.DecodeI32(stack[5]) + setterArgumentType := api.DecodeI32(stack[6]) + setterSignature := api.DecodeI32(stack[7]) + setter := api.DecodeI32(stack[8]) + setterContext := api.DecodeI32(stack[9]) + + fieldName, err := engine.readCString(uint32(fieldNamePtr)) + if err != nil { + panic(fmt.Errorf("could not read field name: %w", err)) + } + + engine.registeredObjects[structType].fields = append(engine.registeredObjects[structType].fields, ®isteredObjectField{ + fieldName: fieldName, + getterReturnType: getterReturnType, + getter: getter, + getterSignature: getterSignature, + getterContext: getterContext, + setterArgumentType: setterArgumentType, + setter: setter, + setterSignature: setterSignature, + setterContext: setterContext, + }) +}) + +var FinalizeValueObject = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + structType := api.DecodeI32(stack[0]) + reg := engine.registeredObjects[structType] + delete(engine.registeredObjects, structType) + fieldRecords := reg.fields + + fieldTypes := make([]int32, len(fieldRecords)*2) + for i := range fieldRecords { + fieldTypes[i] = fieldRecords[i].getterReturnType + fieldTypes[i+len(fieldRecords)] = fieldRecords[i].setterArgumentType + } + + err := engine.whenDependentTypesAreResolved([]int32{structType}, fieldTypes, func(types []registeredType) ([]registeredType, error) { + for i := range fieldRecords { + fieldRecord := fieldRecords[i] + getterReturnType := types[i] + getterFunc, err := engine.newInvokeFunc(fieldRecord.getterSignature, fieldRecord.getter, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{getterReturnType.NativeType()}) + if err != nil { + panic(fmt.Errorf("could not create getterFunc: %w", err)) + } + + fieldRecord.read = func(ctx context.Context, mod api.Module, ptr int32) (any, error) { + res, err := getterFunc.Call(ctx, api.EncodeI32(fieldRecord.getterContext), api.EncodeI32(ptr)) + if err != nil { + return nil, err + } + return getterReturnType.FromWireType(ctx, mod, res[0]) + } + + setterArgumentType := types[i+len(fieldRecords)] + setterFunc, err := engine.newInvokeFunc(fieldRecord.setterSignature, fieldRecord.setter, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, setterArgumentType.NativeType()}, []api.ValueType{}) + if err != nil { + panic(fmt.Errorf("could not create setterFunc: %w", err)) + } + + fieldRecord.write = func(ctx context.Context, mod api.Module, ptr int32, o any) error { + destructors := &[]*destructorFunc{} + res, err := setterArgumentType.ToWireType(ctx, mod, destructors, o) + if err != nil { + return err + } + + _, err = setterFunc.Call(ctx, api.EncodeI32(fieldRecord.setterContext), api.EncodeI32(ptr), res) + if err != nil { + return err + } + + err = engine.runDestructors(ctx, *destructors) + if err != nil { + return err + } + + return nil + } + } + + return []registeredType{ + &objectType{ + baseType: baseType{ + rawType: structType, + name: reg.name, + argPackAdvance: 8, + }, + reg: reg, + }, + }, nil + }) + if err != nil { + panic(fmt.Errorf("could not call whenDependentTypesAreResolved: %w", err)) + } +}) diff --git a/internal/registered_pointer.go b/internal/registered_pointer.go index 083c492..d6e8566 100644 --- a/internal/registered_pointer.go +++ b/internal/registered_pointer.go @@ -17,11 +17,13 @@ type registeredPointerType struct { // smart pointer properties isSmartPointer bool pointeeType *registeredPointerType - sharingPolicy any + sharingPolicy int32 rawGetPointee api.Function rawConstructor api.Function rawShare api.Function rawDestructor api.Function + + specialShare bool // Whether the rawShare is special for this class (no return param) } type registeredPointerTypeRecordCount struct { @@ -85,16 +87,10 @@ func (rpt *registeredPointerType) FromWireType(ctx context.Context, mod api.Modu } if rawPointer == 0 { - destrFun, err := rpt.DestructorFunction(ctx, mod, ptr) + err = rpt.Destructor(ctx, ptr) if err != nil { return nil, err } - if destrFun != nil { - err = destrFun.run(ctx, mod) - if err != nil { - return nil, err - } - } return nil, nil } @@ -108,19 +104,16 @@ func (rpt *registeredPointerType) FromWireType(ctx context.Context, mod api.Modu if registeredInstance.getRegisteredPtrTypeRecord().count.value == 0 { registeredInstance.getRegisteredPtrTypeRecord().ptr = rawPointer registeredInstance.getRegisteredPtrTypeRecord().smartPtr = ptr - return registeredInstance.getClassType().clone(registeredInstance) + return registeredInstance.getClassType().clone(ctx, registeredInstance) } else { // else, just increment reference count on existing object // it already has a reference to the smart pointer - rv, err := registeredInstance.getClassType().clone(registeredInstance) + rv, err := registeredInstance.getClassType().clone(ctx, registeredInstance) if err != nil { return nil, err } - destructor, err := rpt.DestructorFunction(ctx, mod, ptr) - if err != nil { - return nil, err - } - err = destructor.run(ctx, mod) + + err = rpt.Destructor(ctx, ptr) if err != nil { return nil, err } @@ -131,14 +124,14 @@ func (rpt *registeredPointerType) FromWireType(ctx context.Context, mod api.Modu makeDefaultHandle := func() (any, error) { if rpt.isSmartPointer { - return rpt.makeClassHandle(rpt.registeredClass, ®isteredPointerTypeRecord{ + return rpt.makeClassHandle(ctx, rpt.registeredClass, ®isteredPointerTypeRecord{ ptrType: rpt.pointeeType, ptr: rawPointer, smartPtrType: rpt, smartPtr: ptr, }) } else { - return rpt.makeClassHandle(rpt.registeredClass, ®isteredPointerTypeRecord{ + return rpt.makeClassHandle(ctx, rpt.registeredClass, ®isteredPointerTypeRecord{ ptrType: rpt, ptr: ptr, }) @@ -185,14 +178,14 @@ func (rpt *registeredPointerType) FromWireType(ctx context.Context, mod api.Modu } if rpt.isSmartPointer { - return rpt.makeClassHandle(toType.registeredClass, ®isteredPointerTypeRecord{ + return rpt.makeClassHandle(ctx, toType.registeredClass, ®isteredPointerTypeRecord{ ptrType: toType, ptr: dp, smartPtrType: rpt, smartPtr: ptr, }) } else { - return rpt.makeClassHandle(toType.registeredClass, ®isteredPointerTypeRecord{ + return rpt.makeClassHandle(ctx, toType.registeredClass, ®isteredPointerTypeRecord{ ptrType: toType, ptr: dp, }) @@ -229,7 +222,11 @@ func (rpt *registeredPointerType) constNoSmartPtrRawPointerToWireType(ctx contex return 0, nil } - handle := o.(IClassBase) + handle, ok := o.(IClassBase) + if !ok { + return 0, fmt.Errorf("invalid %s, check whether you constructed it properly through embind, the given value is a %T", rpt.name, o) + } + _, isBaseClass := o.(*ClassBase) if !isBaseClass { // @todo: can we do this without reflection? @@ -266,7 +263,11 @@ func (rpt *registeredPointerType) nonConstNoSmartPtrRawPointerToWireType(ctx con return 0, nil } - handle := o.(IClassBase) + handle, ok := o.(IClassBase) + if !ok { + return 0, fmt.Errorf("invalid %s, check whether you constructed it properly through embind, the given value is a %T", rpt.name, o) + } + _, isBaseClass := o.(*ClassBase) if !isBaseClass { // @todo: can we do this without reflection? @@ -307,22 +308,30 @@ func (rpt *registeredPointerType) genericPointerToWireType(ctx context.Context, if rpt.isSmartPointer { res, err := rpt.rawConstructor.Call(ctx) if err != nil { - ptr = api.DecodeU32(res[0]) + return 0, err } + + ptr = api.DecodeU32(res[0]) if destructors != nil { destructorsRef := *destructors destructorsRef = append(destructorsRef, &destructorFunc{ apiFunction: rpt.rawDestructor, args: []uint64{api.EncodeU32(ptr)}, }) + *destructors = destructorsRef } + return api.EncodeU32(ptr), nil } else { return 0, nil } } - handle := o.(IClassBase) + handle, ok := o.(IClassBase) + if !ok { + return 0, fmt.Errorf("invalid %s, check whether you constructed it properly through embind, the given value is a %T", rpt.name, o) + } + _, isBaseClass := o.(*ClassBase) if !isBaseClass { // @todo: can we do this without reflection? @@ -385,7 +394,7 @@ func (rpt *registeredPointerType) genericPointerToWireType(ctx context.Context, ptr = registeredPtrTypeRecord.smartPtr } else { e := MustGetEngineFromContext(ctx, nil) - clonedHandle, err := handle.getClassType().clone(handle) + clonedHandle, err := handle.getClassType().clone(ctx, handle) if err != nil { return 0, err } @@ -395,6 +404,7 @@ func (rpt *registeredPointerType) genericPointerToWireType(ctx context.Context, _ = clonedHandle.getClassType().delete(ctx, clonedHandle) }) + // @todo: what to do with rpt.specialShare? res, err := rpt.rawShare.Call(ctx, api.EncodeU32(ptr), api.EncodeI32(deleteCallbackHandle)) if err != nil { return 0, err @@ -426,28 +436,31 @@ func (rpt *registeredPointerType) ReadValueFromPointer(ctx context.Context, mod return rpt.FromWireType(ctx, mod, api.EncodeU32(value)) } -func (rpt *registeredPointerType) HasDestructorFunction() bool { +func (rpt *registeredPointerType) DestructorFunctionUndefined() bool { if !rpt.isSmartPointer && rpt.registeredClass.baseClass == nil { return false } return true } -func (rpt *registeredPointerType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) (*destructorFunc, error) { - if rpt.rawDestructor != nil { - return &destructorFunc{ - apiFunction: rpt.rawDestructor, - args: []uint64{api.EncodeU32(pointer)}, - }, nil - } - - return nil, nil +func (rpt *registeredPointerType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) *destructorFunc { + return nil } func (rpt *registeredPointerType) HasDeleteObject() bool { return true } +func (rpt *registeredPointerType) Destructor(ctx context.Context, pointer uint32) error { + if rpt.rawDestructor != nil { + _, err := rpt.rawDestructor.Call(ctx, api.EncodeU32(pointer)) + if err != nil { + return err + } + } + return nil +} + func (rpt *registeredPointerType) DeleteObject(ctx context.Context, mod api.Module, handle any) error { if handle != nil { casted := handle.(IClassBase) @@ -523,7 +536,7 @@ func (rpt *registeredPointerType) downcastPointer(ctx context.Context, ptr uint3 return api.DecodeU32(downcastRes[0]), nil } -func (rpt *registeredPointerType) makeClassHandle(class *classType, record *registeredPointerTypeRecord) (IClassBase, error) { +func (rpt *registeredPointerType) makeClassHandle(ctx context.Context, class *classType, record *registeredPointerTypeRecord) (IClassBase, error) { if record.ptrType == nil || record.ptr == 0 { return nil, fmt.Errorf("makeClassHandle requires ptr and ptrType") } @@ -536,7 +549,7 @@ func (rpt *registeredPointerType) makeClassHandle(class *classType, record *regi value: 1, } - classHandle, err := class.getNewInstance(record) + classHandle, err := class.getNewInstance(ctx, record) if err != nil { return nil, err } diff --git a/internal/std_string.go b/internal/std_string.go index 12ce0a5..3a63a8f 100644 --- a/internal/std_string.go +++ b/internal/std_string.go @@ -3,7 +3,6 @@ package embind import ( "context" "fmt" - "github.com/tetratelabs/wazero/api" ) @@ -53,6 +52,7 @@ func (sst *stdStringType) ToWireType(ctx context.Context, mod api.Module, destru if err != nil { return 0, err } + base := api.DecodeU32(mallocRes[0]) ptr := base + 4 @@ -73,12 +73,7 @@ func (sst *stdStringType) ToWireType(ctx context.Context, mod api.Module, destru if destructors != nil { destructorsRef := *destructors - destructorsRef = append(destructorsRef, &destructorFunc{ - function: "free", - args: []uint64{ - api.EncodeU32(base), - }, - }) + destructorsRef = append(destructorsRef, sst.DestructorFunction(ctx, mod, base)) *destructors = destructorsRef } @@ -93,15 +88,15 @@ func (sst *stdStringType) ReadValueFromPointer(ctx context.Context, mod api.Modu return sst.FromWireType(ctx, mod, api.EncodeU32(ptr)) } -func (sst *stdStringType) HasDestructorFunction() bool { - return true +func (sst *stdStringType) DestructorFunctionUndefined() bool { + return false } -func (sst *stdStringType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) (*destructorFunc, error) { +func (sst *stdStringType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) *destructorFunc { return &destructorFunc{ apiFunction: mod.ExportedFunction("free"), args: []uint64{api.EncodeU32(pointer)}, - }, nil + } } func (sst *stdStringType) GoType() string { @@ -111,3 +106,25 @@ func (sst *stdStringType) GoType() string { func (sst *stdStringType) FromF64(o float64) uint64 { return api.EncodeU32(uint32(o)) } + +var RegisterStdString = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + + rawType := api.DecodeI32(stack[0]) + name, err := engine.readCString(uint32(api.DecodeI32(stack[1]))) + if err != nil { + panic(fmt.Errorf("could not read name: %w", err)) + } + + err = engine.registerType(rawType, &stdStringType{ + baseType: baseType{ + rawType: rawType, + name: name, + argPackAdvance: 8, + }, + stdStringIsUTF8: name == "std::string", + }, nil) + if err != nil { + panic(fmt.Errorf("could not register: %w", err)) + } +}) diff --git a/internal/std_wstring.go b/internal/std_wstring.go index 61652d0..200c829 100644 --- a/internal/std_wstring.go +++ b/internal/std_wstring.go @@ -81,40 +81,34 @@ func (swst *stdWStringType) ToWireType(ctx context.Context, mod api.Module, dest return 0, err } - mallocRes, err := mod.ExportedFunction("malloc").Call(ctx, api.EncodeI32(4+int32(output.Len())+1)) + mallocRes, err := mod.ExportedFunction("malloc").Call(ctx, api.EncodeI32(4+int32(output.Len())+swst.charSize)) if err != nil { return 0, err } base := api.DecodeU32(mallocRes[0]) - ptr := base + 4 - ok = mod.Memory().WriteUint32Le(base, uint32(output.Len())) + ok = mod.Memory().WriteUint32Le(base, uint32(len(stringVal))) if !ok { return 0, fmt.Errorf("could not write length to memory") } - ok = mod.Memory().Write(ptr, output.Bytes()) + ok = mod.Memory().Write(base+4, output.Bytes()) if !ok { return 0, fmt.Errorf("could not write string to memory") } - ok = mod.Memory().Write(ptr+uint32(output.Len())+1, make([]byte, swst.charSize)) + ok = mod.Memory().Write(base+4+uint32(output.Len()), make([]byte, swst.charSize)) if !ok { return 0, fmt.Errorf("could not write NULL terminator to memory") } if destructors != nil { destructorsRef := *destructors - destructorsRef = append(destructorsRef, &destructorFunc{ - function: "free", - args: []uint64{ - api.EncodeU32(base), - }, - }) + destructorsRef = append(destructorsRef, swst.DestructorFunction(ctx, mod, base)) *destructors = destructorsRef } - return 0, nil + return api.EncodeU32(base), nil } func (swst *stdWStringType) ReadValueFromPointer(ctx context.Context, mod api.Module, pointer uint32) (any, error) { @@ -125,15 +119,15 @@ func (swst *stdWStringType) ReadValueFromPointer(ctx context.Context, mod api.Mo return swst.FromWireType(ctx, mod, api.EncodeU32(ptr)) } -func (swst *stdWStringType) HasDestructorFunction() bool { - return true +func (swst *stdWStringType) DestructorFunctionUndefined() bool { + return false } -func (swst *stdWStringType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) (*destructorFunc, error) { +func (swst *stdWStringType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) *destructorFunc { return &destructorFunc{ apiFunction: mod.ExportedFunction("free"), args: []uint64{api.EncodeU32(pointer)}, - }, nil + } } func (swst *stdWStringType) GoType() string { @@ -143,3 +137,25 @@ func (swst *stdWStringType) GoType() string { func (swst *stdWStringType) FromF64(o float64) uint64 { return api.EncodeU32(uint32(o)) } + +var RegisterStdWString = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + + rawType := api.DecodeI32(stack[0]) + name, err := engine.readCString(uint32(api.DecodeI32(stack[2]))) + if err != nil { + panic(fmt.Errorf("could not read name: %w", err)) + } + + err = engine.registerType(rawType, &stdWStringType{ + baseType: baseType{ + rawType: rawType, + name: name, + argPackAdvance: 8, + }, + charSize: api.DecodeI32(stack[1]), + }, nil) + if err != nil { + panic(fmt.Errorf("could not register: %w", err)) + } +}) diff --git a/internal/symbol.go b/internal/symbol.go index 2cc5d8e..17c322f 100644 --- a/internal/symbol.go +++ b/internal/symbol.go @@ -3,12 +3,15 @@ package embind import ( "context" "fmt" + "github.com/tetratelabs/wazero/api" ) type ISymbol interface { Symbol() string ReturnType() IType ArgumentTypes() []IType + IsOverload() bool + OverloadCount() int } type publicSymbol struct { @@ -20,6 +23,8 @@ type publicSymbol struct { argumentTypes []registeredType resultType registeredType isStatic bool + isOverload bool + overloadCount int } func (ps *publicSymbol) Symbol() string { @@ -27,9 +32,20 @@ func (ps *publicSymbol) Symbol() string { } func (ps *publicSymbol) ReturnType() IType { + if ps.resultType == nil { + return nil + } return &exposedType{ps.resultType} } +func (ps *publicSymbol) IsOverload() bool { + return ps.isOverload +} + +func (ps *publicSymbol) OverloadCount() int { + return ps.overloadCount +} + func (ps *publicSymbol) ArgumentTypes() []IType { exposedTypes := make([]IType, len(ps.argumentTypes)) for i := range ps.argumentTypes { @@ -57,32 +73,13 @@ func (e *engine) CallPublicSymbol(ctx context.Context, name string, arguments .. return res, nil } -func (e *engine) CallStaticClassMethod(ctx context.Context, className, name string, arguments ...any) (any, error) { - _, ok := e.publicSymbols[className] - if !ok { - return nil, fmt.Errorf("could not find class %s", className) - } - - _, ok = e.registeredClasses[className].methods[name] - if !ok { - return nil, fmt.Errorf("could not find method %s on class %s", name, className) - } - - ctx = e.Attach(ctx) - res, err := e.registeredClasses[className].methods[name].fn(ctx, nil, arguments...) - if err != nil { - return nil, fmt.Errorf("error while calling embind function %s on class %s: %w", name, className, err) - } - - return res, nil -} - func (e *engine) GetSymbols() []ISymbol { symbols := make([]ISymbol, 0) for i := range e.publicSymbols { if e.publicSymbols[i].overloadTable != nil { for argCount := range e.publicSymbols[i].overloadTable { + e.publicSymbols[i].overloadTable[argCount].overloadCount = len(e.publicSymbols[i].overloadTable) symbols = append(symbols, e.publicSymbols[i].overloadTable[argCount]) } } else { @@ -92,3 +89,63 @@ func (e *engine) GetSymbols() []ISymbol { return symbols } + +var RegisterFunction = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + namePtr := api.DecodeI32(stack[0]) + argCount := api.DecodeI32(stack[1]) + rawArgTypesAddr := api.DecodeI32(stack[2]) + signaturePtr := api.DecodeI32(stack[3]) + rawInvoker := api.DecodeI32(stack[4]) + fn := api.DecodeI32(stack[5]) + isAsync := api.DecodeI32(stack[6]) != 0 + + argTypes, err := engine.heap32VectorToArray(argCount, rawArgTypesAddr) + if err != nil { + panic(fmt.Errorf("could not read arg types: %w", err)) + } + + name, err := engine.readCString(uint32(namePtr)) + if err != nil { + panic(fmt.Errorf("could not read name: %w", err)) + } + + publicSymbolArgs := argCount - 1 + + // Set a default callback that errors out when not all types are resolved. + err = engine.exposePublicSymbol(name, func(ctx context.Context, this any, arguments ...any) (any, error) { + return nil, engine.createUnboundTypeError(ctx, fmt.Sprintf("Cannot call _embind_register_function %s due to unbound types", name), argTypes) + }, &publicSymbolArgs) + if err != nil { + panic(fmt.Errorf("could not expose public symbol: %w", err)) + } + + // When all types are resolved, replace the callback with the actual implementation. + err = engine.whenDependentTypesAreResolved([]int32{}, argTypes, func(argTypes []registeredType) ([]registeredType, error) { + invokerArgsArray := []registeredType{argTypes[0] /* return value */, nil /* no class 'this'*/} + invokerArgsArray = append(invokerArgsArray, argTypes[1:]... /* actual params */) + + expectedParamTypes := make([]api.ValueType, len(invokerArgsArray[2:])+1) + expectedParamTypes[0] = api.ValueTypeI32 // fn + for i := range invokerArgsArray[2:] { + expectedParamTypes[i+1] = invokerArgsArray[i+2].NativeType() + } + + // Create an api.Function to be able to invoke the function on the + // Emscripten side. + invokerFunc, err := engine.newInvokeFunc(signaturePtr, rawInvoker, expectedParamTypes, []api.ValueType{argTypes[0].NativeType()}) + if err != nil { + return nil, fmt.Errorf("could not create _embind_register_function invoke func: %w", err) + } + + err = engine.replacePublicSymbol(name, engine.craftInvokerFunction(name, invokerArgsArray, nil /* no class 'this'*/, invokerFunc, fn, isAsync), &publicSymbolArgs, argTypes[1:], argTypes[0]) + if err != nil { + return nil, err + } + + return []registeredType{}, nil + }) + if err != nil { + panic(fmt.Errorf("could not setup type dependenant lookup callbacks: %w", err)) + } +}) diff --git a/internal/types.go b/internal/types.go index 7d7d0d6..f2998e4 100644 --- a/internal/types.go +++ b/internal/types.go @@ -25,12 +25,12 @@ func (bt *baseType) ArgPackAdvance() int32 { return bt.argPackAdvance } -func (bt *baseType) HasDestructorFunction() bool { - return false +func (bt *baseType) DestructorFunctionUndefined() bool { + return true } -func (bt *baseType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) (*destructorFunc, error) { - return nil, nil +func (bt *baseType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) *destructorFunc { + return nil } func (bt *baseType) ReadValueFromPointer(ctx context.Context, mod api.Module, pointer uint32) (any, error) { @@ -53,12 +53,16 @@ func (bt *baseType) FromF64(o float64) uint64 { return api.EncodeF64(o) } +func (bt *baseType) ToF64(o uint64) float64 { + return float64(o) +} + type registeredType interface { RawType() int32 Name() string ArgPackAdvance() int32 - HasDestructorFunction() bool - DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) (*destructorFunc, error) + DestructorFunctionUndefined() bool + DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) *destructorFunc FromWireType(ctx context.Context, mod api.Module, wt uint64) (any, error) ToWireType(ctx context.Context, mod api.Module, destructors *[]*destructorFunc, o any) (uint64, error) ReadValueFromPointer(ctx context.Context, mod api.Module, pointer uint32) (any, error) @@ -67,6 +71,7 @@ type registeredType interface { NativeType() api.ValueType GoType() string FromF64(o float64) uint64 + ToF64(o uint64) float64 } type IType interface { @@ -151,7 +156,3 @@ type registeredObjectField struct { read func(ctx context.Context, mod api.Module, ptr int32) (any, error) write func(ctx context.Context, mod api.Module, ptr int32, o any) error } - -type undefinedType int8 - -var undefined = undefinedType(0) diff --git a/internal/void.go b/internal/void.go index 9508ac3..c49bf4c 100644 --- a/internal/void.go +++ b/internal/void.go @@ -2,6 +2,10 @@ package embind import ( "context" + "fmt" + + "github.com/jerbob92/wazero-emscripten-embind/types" + "github.com/tetratelabs/wazero/api" ) @@ -10,7 +14,7 @@ type voidType struct { } func (vt *voidType) FromWireType(ctx context.Context, mod api.Module, value uint64) (any, error) { - return undefined, nil + return types.Undefined, nil } func (vt *voidType) ToWireType(ctx context.Context, mod api.Module, destructors *[]*destructorFunc, o any) (uint64, error) { @@ -25,3 +29,24 @@ func (vt *voidType) NativeType() api.ValueType { func (vt *voidType) GoType() string { return "" } + +var RegisterVoid = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + + rawType := api.DecodeI32(stack[0]) + name, err := engine.readCString(uint32(api.DecodeI32(stack[1]))) + if err != nil { + panic(fmt.Errorf("could not read name: %w", err)) + } + + err = engine.registerType(rawType, &voidType{ + baseType: baseType{ + rawType: rawType, + name: name, + argPackAdvance: 0, + }, + }, nil) + if err != nil { + panic(fmt.Errorf("could not register: %w", err)) + } +}) diff --git a/testdata/wasm/classes.cpp b/testdata/wasm/classes.cpp new file mode 100644 index 0000000..6a46ba8 --- /dev/null +++ b/testdata/wasm/classes.cpp @@ -0,0 +1,105 @@ +#include + +using namespace emscripten; + +class MyClass { +public: + MyClass(int x, std::string y) + : x(x) + , y(y) + {} + + MyClass(int x) + : x(x) + {} + + void incrementX() { + ++x; + } + + void incrementX(int multiplier) { + x = x + (1 * multiplier); + } + + int getX() const { return x; } + void setX(int x_) { x = x_; } + + std::string getY() const { return y; } + + std::string combineY(std::string in) const { return in + y; } + + static std::string getStringFromInstance(const MyClass& instance) { + return instance.y; + } + +protected: + int x; + std::string y; +}; + +MyClass* passThrough(MyClass* ptr) { return ptr; } + +struct Interface { + virtual void invoke(const std::string& str) = 0; +}; + +struct InterfaceWrapper : public wrapper { + EMSCRIPTEN_WRAPPER(InterfaceWrapper); + void invoke(const std::string& str) { + return call("invoke", str); + } +}; + +class C {}; + +struct BaseClass { + virtual void invoke(const std::string& str) { + // default implementation + } +}; + +struct BaseClassWrapper : public wrapper { + EMSCRIPTEN_WRAPPER(BaseClassWrapper); + void invoke(const std::string& str) { + return call("invoke", str); + } +}; + +class DerivedClass : public BaseClass {}; +BaseClass* getDerivedInstance() { + return new DerivedClass; +} + +EMSCRIPTEN_BINDINGS(classes) { + class_("MyClass") + .constructor() + .constructor() + .function("incrementX", select_overload(&MyClass::incrementX)) + .function("incrementX", select_overload(&MyClass::incrementX)) + .function("combineY", &MyClass::combineY) + .property("x", &MyClass::getX, &MyClass::setX) + .property("y", &MyClass::getY) + .class_function("getStringFromInstance", &MyClass::getStringFromInstance) + ; + + function("passThrough", &passThrough, allow_raw_pointers()); + + class_("Interface") + .function("invoke", &Interface::invoke, pure_virtual()) + .allow_subclass("InterfaceWrapper") + ; + + class_("C") + .smart_ptr_constructor("C", &std::make_shared) + ; + + class_("BaseClass") + .allow_subclass("BaseClassWrapper") + .function("invoke", optional_override([](BaseClass& self, const std::string& str) { + return self.BaseClass::invoke(str); + })) + ; + + class_>("DerivedClass"); + function("getDerivedClassInstance", &getDerivedInstance, allow_raw_pointers()); +} diff --git a/testdata/wasm/compile.sh b/testdata/wasm/compile.sh new file mode 100755 index 0000000..ec6c69c --- /dev/null +++ b/testdata/wasm/compile.sh @@ -0,0 +1 @@ +emcc -sERROR_ON_UNDEFINED_SYMBOLS=0 -sEXPORTED_FUNCTIONS="_free,_malloc" -g classes.cpp functions.cpp constants.cpp enums.cpp structs.cpp emval.cpp embind_test.cpp test_custom_marshal.cpp test_finalization.cpp test_unsigned.cpp -o tests.wasm -lembind --no-entry diff --git a/testdata/wasm/constants.cpp b/testdata/wasm/constants.cpp new file mode 100644 index 0000000..5b742a9 --- /dev/null +++ b/testdata/wasm/constants.cpp @@ -0,0 +1,37 @@ +#include + +using namespace emscripten; + +const bool SOME_CONSTANT_1 = false; +const float SOME_CONSTANT_2 = 2; +const double SOME_CONSTANT_3 = 3; +const int SOME_CONSTANT_4 = 4; +const std::string SOME_CONSTANT_5 = "TestString"; +const char SOME_CONSTANT_6 = 'C'; +const long long SOME_CONSTANT_7 = 7; +const unsigned short SOME_CONSTANT_8 = 8; +const unsigned int SOME_CONSTANT_9 = 9; +const unsigned short SOME_CONSTANT_10 = 10; +const unsigned char SOME_CONSTANT_11 = 11; +const unsigned long SOME_CONSTANT_12 = 12; +const std::wstring SOME_CONSTANT_13 = L"TestWideString"; +const bool SOME_CONSTANT_14 = true; +const unsigned long long SOME_CONSTANT_15 = 15; + +EMSCRIPTEN_BINDINGS(constants_tests) { + constant("SOME_CONSTANT_1", SOME_CONSTANT_1); + constant("SOME_CONSTANT_2", SOME_CONSTANT_2); + constant("SOME_CONSTANT_3", SOME_CONSTANT_3); + constant("SOME_CONSTANT_4", SOME_CONSTANT_4); + constant("SOME_CONSTANT_5", SOME_CONSTANT_5); + constant("SOME_CONSTANT_6", SOME_CONSTANT_6); + constant("SOME_CONSTANT_7", SOME_CONSTANT_7); + constant("SOME_CONSTANT_8", SOME_CONSTANT_8); + constant("SOME_CONSTANT_9", SOME_CONSTANT_9); + constant("SOME_CONSTANT_10", SOME_CONSTANT_10); + constant("SOME_CONSTANT_11", SOME_CONSTANT_11); + constant("SOME_CONSTANT_12", SOME_CONSTANT_12); + constant("SOME_CONSTANT_13", SOME_CONSTANT_13); + constant("SOME_CONSTANT_14", SOME_CONSTANT_14); + constant("SOME_CONSTANT_15", SOME_CONSTANT_15); +} \ No newline at end of file diff --git a/testdata/wasm/embind_test.cpp b/testdata/wasm/embind_test.cpp new file mode 100644 index 0000000..bd36c52 --- /dev/null +++ b/testdata/wasm/embind_test.cpp @@ -0,0 +1,3093 @@ +// Copyright 2012 The Emscripten Authors. All rights reserved. +// Emscripten is available under two separate licenses, the MIT license and the +// University of Illinois/NCSA Open Source License. Both these licenses can be +// found in the LICENSE file. + +#include +#include +#include +#include +#include + +using namespace emscripten; + +val emval_test_mallinfo() { + const auto& i = mallinfo(); + val rv(val::object()); + rv.set("arena", val(i.arena)); + rv.set("ordblks", val(i.ordblks)); + rv.set("smblks", val(i.smblks)); + rv.set("hblks", val(i.hblks)); + rv.set("usmblks", val(i.usmblks)); + rv.set("fsmblks", val(i.fsmblks)); + rv.set("uordblks", val(i.uordblks)); + rv.set("fordblks", val(i.fordblks)); + rv.set("keepcost", val(i.keepcost)); + return rv; +} + +val emval_test_new_integer() { + return val(15); +} + +val emval_test_new_string() { + return val("Hello everyone"); +} + +std::string emval_test_get_string_from_val(val v) { + return v["key"].as(); +} + +val emval_test_new_object() { + val rv(val::object()); + rv.set("foo", val("bar")); + rv.set("baz", val(1)); + return rv; +} + +struct DummyForPointer { + int value; + DummyForPointer(const int v) : value(v) {} +}; + +static DummyForPointer emval_pointer_dummy(42); + +val emval_test_instance_pointer() { + DummyForPointer* p = &emval_pointer_dummy; + return val(p); +} + +int emval_test_value_from_instance_pointer(val v) { + DummyForPointer * p = v.as(allow_raw_pointers()); + return p->value; +} + +unsigned emval_test_passthrough_unsigned(unsigned v) { + return v; +} + +val emval_test_passthrough(val v) { + return v; +} + +void emval_test_return_void() { +} + +bool emval_test_not(bool b) { + return !b; +} + +bool emval_test_is_true(val v) { + return v.isTrue(); +} + +bool emval_test_is_false(val v) { + return v.isFalse(); +} + +bool emval_test_is_null(val v) { + return v.isNull(); +} + +bool emval_test_is_undefined(val v) { + return v.isUndefined(); +} + +bool emval_test_equals(val v1,val v2) { + return v1.equals(v2); +} + +bool emval_test_strictly_equals(val v1, val v2) { + return v1.strictlyEquals(v2); +} + +unsigned emval_test_as_unsigned(val v) { + return v.as(); +} + +unsigned emval_test_get_length(val v) { + return v["length"].as(); +} + +double emval_test_add(char c, signed char sc, unsigned char uc, signed short ss, unsigned short us, signed int si, unsigned int ui, signed long sl, unsigned long ul, float f, double d) { + return c + sc + uc + ss + us + si + ui + sl + ul + f + d; +} + +float const_ref_adder(const int& i, const float& f) { + return i + f; +} + +unsigned emval_test_sum(val v) { + unsigned length = v["length"].as(); + double rv = 0; + for (unsigned i = 0; i < length; ++i) { + rv += v[i].as(); + } + return rv; +} + +std::string get_non_ascii_string(bool embindStdStringUTF8Support) { + if(embindStdStringUTF8Support) { + //ASCII + std::string testString{"aei"}; + //Latin-1 Supplement + testString += "\u00E1\u00E9\u00ED"; + //Greek + testString += "\u03B1\u03B5\u03B9"; + //Cyrillic + testString += "\u0416\u041B\u0424"; + //CJK + testString += "\u5F9E\u7345\u5B50"; + //Euro sign + testString += "\u20AC"; + return testString; + } else { + char c[128 + 1]; + c[128] = 0; + for (int i = 0; i < 128; ++i) { + c[i] = 128 + i; + } + return c; + } +} + +std::wstring get_non_ascii_wstring() { + std::wstring ws(4, 0); + ws[0] = 10; + ws[1] = 1234; + ws[2] = 2345; + ws[3] = 65535; + return ws; +} + +std::u16string get_non_ascii_u16string() { + std::u16string u16s(4, 0); + u16s[0] = 10; + u16s[1] = 1234; + u16s[2] = 2345; + u16s[3] = 65535; + return u16s; +} + +std::u32string get_non_ascii_u32string() { + std::u32string u32s(5, 0); + u32s[0] = 10; + u32s[1] = 1234; + u32s[2] = 2345; + u32s[3] = 128513; + u32s[4] = 128640; + return u32s; +} + +std::wstring get_literal_wstring() { + return L"get_literal_wstring"; +} + +std::u16string get_literal_u16string() { + return u"get_literal_u16string"; +} + +std::u32string get_literal_u32string() { + return U"get_literal_u32string"; +} + +void force_memory_growth() { + std::size_t old_size = emscripten_get_heap_size(); + assert(val::global("oldheap")["byteLength"].as() == old_size); + emscripten_resize_heap(old_size + EMSCRIPTEN_PAGE_SIZE); + assert(emscripten_get_heap_size() > old_size); + // HEAPU8 on the module should now be rebound, and our oldheap should be detached + assert(val::module_property("HEAPU8")["byteLength"].as() > old_size); + assert(val::global("oldheap")["byteLength"].as() == 0); +} + +std::string emval_test_take_and_return_const_char_star(const char* str) { + return str; +} + +std::string emval_test_take_and_return_std_string(std::string str) { + return str; +} + +std::string emval_test_take_and_return_std_string_const_ref(const std::string& str) { + return str; +} + +std::basic_string emval_test_take_and_return_std_basic_string_unsigned_char(std::basic_string str) { + return str; +} + +std::wstring take_and_return_std_wstring(std::wstring str) { + return str; +} + +std::u16string take_and_return_std_u16string(std::u16string str) { + return str; +} + +std::u32string take_and_return_std_u32string(std::u32string str) { + return str; +} + +std::function emval_test_get_function_ptr() { + return emval_test_take_and_return_std_string; +} + +std::string emval_test_take_and_call_functor(std::function func) { + return func("asdf"); +} + +class ValHolder { +public: + ValHolder(val v) + : v_(v) + {} + + val getVal() const { + return v_; + } + + val getValNonConst() { + return v_; + } + + const val getConstVal() const { + return v_; + } + + const val& getValConstRef() const { + return v_; + } + + void setVal(val v) { + this->v_ = v; + } + + static int some_class_method(int i) { + return i; + } + + static const ValHolder* makeConst(val v) { + return new ValHolder(v); + } + + static ValHolder makeValHolder(val v) { + return ValHolder(v); + } + + static void set_via_raw_pointer(ValHolder* vh, val v) { + vh->setVal(v); + } + + static val get_via_raw_pointer(const ValHolder* vh) { + return vh->getVal(); + } + + static void transfer_via_raw_pointer(ValHolder* target, const ValHolder* source) { + target->setVal(source->getVal()); + } + + static val getValNonMember(const ValHolder& target) { + return target.getVal(); + } + +private: + val v_; +}; + +ValHolder emval_test_return_ValHolder() { + return val::object(); +} + +val valholder_get_value_mixin(const ValHolder& target) { + return target.getVal(); +} + +void valholder_set_value_mixin(ValHolder& target, const val& value) { + target.setVal(value); +} + +void emval_test_set_ValHolder_to_empty_object(ValHolder& vh) { + vh.setVal(val::object()); +} + +class StringHolder { +public: + StringHolder(const std::string& s) + : str_(s) + {} + + void set(const std::string& s) { + str_ = s; + } + + std::string get() const { + return str_; + } + + std::string& get_ref() { + return str_; + } + + const std::string& get_const_ref() const { + return str_; + } + +private: + std::string str_; +}; + +class SharedPtrHolder { +public: + SharedPtrHolder() + : ptr_(new StringHolder("a string")) + {} + + std::shared_ptr get() const { + return ptr_; + } + + void set(std::shared_ptr p) { + ptr_ = p; + } +private: + std::shared_ptr ptr_; +}; + +class VectorHolder { +public: + VectorHolder() { + v_.push_back(StringHolder("string #1")); + v_.push_back(StringHolder("string #2")); + } + + std::vector get() const { + return v_; + } + + void set(std::vector vec) { + v_ = vec; + } + +private: + std::vector v_; +}; + +class SmallClass { +public: + SmallClass(): member(7) {}; + int member; +}; + +class BigClass { +public: + BigClass(): member(11) {}; + int member; + int otherMember; + int yetAnotherMember; + + int getMember() { + return member; + } +}; + +class NoExceptClass { +public: + int getValue() noexcept { + return 42; + } + int getValueConst() const noexcept { + return 43; + } + int getX() const noexcept { return x; } + void setX(int x_) noexcept { x = x_; } +private: + int x; +}; + +void embind_test_no_except_function(NoExceptClass&) noexcept {} + +class ParentClass { +public: + ParentClass(): bigClass() {}; + + BigClass bigClass; + + const BigClass& getBigClass() { + return bigClass; + }; +}; + +template +class TemplateClass { +public: + TemplateClass(T a, T b, T c) { + members[0] = a; + members[1] = b; + members[2] = c; + }; + + const T getMember(int n) { + return members[n]; + } + +protected: + T members[3]; +}; + +class ContainsTemplatedMemberClass { +public: + ContainsTemplatedMemberClass(): testTemplate(86, 87, 88) {}; + + TemplateClass testTemplate; + + const TemplateClass& getTestTemplate() { + return testTemplate; + }; +}; + +class SymbolNameClass { +public: + std::string iterator() { + return "Iterator"; + } + + static std::string species() { + return "Species"; + } +}; + +// Begin Inheritance Hierarchy Class Definitions + +class Base { +public: + Base(): name("Base"), + member(0), + baseMember(0) + {} + + std::string getClassName() const { + return name; + } + std::string getClassNameFromBase() const { + return name; + } + std::string getClassNameNotAvailableInDerivedClasses() { + // but wait -- if you act now we will throw in a SECOND base class method ABSOLUTELY FREE!! + return name; + } + void setMember(int value) { + member = value; + } + int getMember() { + return member; + } + void setBaseMember(int value) { + baseMember = value; + } + int getBaseMember() { + return baseMember; + } + static std::string classFunction() { + return "Base"; + }; + std::string name; + int member; + int baseMember; +}; + +class SecondBase { +public: + SecondBase() + : name("SecondBase"), + member(0), + secondBaseMember(0) + {} + + std::string getClassName() const { + return name; + } + std::string getClassNameNotAvailableInDerivedClasses() { + return name; + } + std::string getClassNameFromSecondBase() const { + return name; + } + void setMember(int value) { + member = value; + } + int getMember() { + return member; + } + void setSecondBaseMember(int value) { + secondBaseMember = value; + } + int getSecondBaseMember() { + return secondBaseMember; + } + std::string name; + int member; + int secondBaseMember; +}; + +class Derived : public Base{ +public: + Derived() + : Base() + , member(0) + , name_("Derived") + {} + + std::string getClassName() const { + return name_; + } + void setMember(int value) { + member = value; + } + int getMember() { + return member; + } + static std::string classFunction() { + return "Derived"; + } + int member; +private: + std::string name_; +}; + +class DerivedHolder { +public: + DerivedHolder() { + derived_.reset(); + } + void newDerived() { + deleteDerived(); + derived_ = std::shared_ptr(new Derived()); + } + void deleteDerived() { + derived_.reset(); + } + std::shared_ptr getDerived() { + return derived_; + } + std::string getDerivedClassName() { + return derived_->getClassName(); + } +private: + std::shared_ptr derived_; +}; + +class SiblingDerived : public Base { +public: + SiblingDerived() + : Base(), + name_("SiblingDerived") + {} + + std::string getClassName() const { + return name_; + } + +private: + std::string name_; +}; + +class MultiplyDerived : public Base, public SecondBase { +public: + MultiplyDerived() + : Base(), SecondBase(), + name_("MultiplyDerived") + { instanceCount_ ++; } + + ~MultiplyDerived() + { instanceCount_ --; } + + std::string getClassName() const { + return name_; + } + + static int getInstanceCount() { + return instanceCount_; + } +private: + std::string name_; + static int instanceCount_; +}; +int MultiplyDerived::instanceCount_ = 0; + +class DerivedTwice : public Derived { +public: + DerivedTwice() + : Derived(), + name_("DerivedTwice") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class DerivedTwiceNotBound : public Derived { +public: + DerivedTwiceNotBound() + : Derived(), + name_("DerivedTwiceNotBound") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class DerivedThrice: public DerivedTwiceNotBound { +public: + DerivedThrice() + : DerivedTwiceNotBound(), + name_("DerivedThrice") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class DerivedFourTimesNotBound: public DerivedThrice { +public: + DerivedFourTimesNotBound() + : DerivedThrice(), + name_("DerivedFourTimesNotBound") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyBase { +public: + PolyBase(const std::string& s) + : str_(s), + name_("PolyBase") + {} + + PolyBase(): name_("PolyBase") {} + + virtual ~PolyBase() {} + + virtual std::string virtualGetClassName() const { + return name_; + } + + std::string getClassName() const { + return name_; + } + +private: + std::string str_; + std::string name_; +}; + +class PolySecondBase { +public: + PolySecondBase(): name_("PolySecondBase") + {} + + virtual ~PolySecondBase() {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyDerived : public PolyBase{ +public: + PolyDerived() + : PolyBase("PolyDerived"), + name_("PolyDerived") + {} + + std::string virtualGetClassName() const { + return name_; + } + + std::string getClassName() const { + return name_; + } + + static void setPtrDerived() { + ptr_ = std::shared_ptr(new PolyDerived()); + } + + static void releasePtr() { + ptr_.reset(); + } + + static std::string getPtrClassName() { + return ptr_->getClassName(); + } + + static std::shared_ptr getPtr() { + return ptr_; + } + +private: + std::string name_; + static std::shared_ptr ptr_; +}; +std::shared_ptr PolyDerived::ptr_; + +class PolySiblingDerived : public PolyBase { +public: + PolySiblingDerived() + : PolyBase(), + name_("PolySiblingDerived") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyMultiplyDerived : public PolyBase, public PolySecondBase { +public: + PolyMultiplyDerived() + : PolyBase(), PolySecondBase(), + name_("PolyMultiplyDerived") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyDerivedTwiceWithoutSmartPointer: public PolyDerived { +public: + PolyDerivedTwiceWithoutSmartPointer() + : PolyDerived(), + name_("PolyDerivedTwiceWithoutSmartPointer") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyDerivedTwiceNotBound : public PolyDerived { +public: + PolyDerivedTwiceNotBound() + : PolyDerived(), + name_("PolyDerivedTwiceNotBound") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyDerivedThrice: public PolyDerivedTwiceNotBound { +public: + PolyDerivedThrice() + : PolyDerivedTwiceNotBound(), + name_("PolyDerivedThrice") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyDerivedFourTimesNotBound: public PolyDerivedThrice { +public: + PolyDerivedFourTimesNotBound() + : PolyDerivedThrice(), + name_("PolyDerivedFourTimesNotBound") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyDiamondBase { +public: + PolyDiamondBase(): + name_("PolyBase") + {} + ~PolyDiamondBase() {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyDiamondDerived: public PolyDiamondBase { +public: + PolyDiamondDerived() + : PolyDiamondBase(), + name_("PolyDiamondDerived") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyDiamondSiblingDerived: public PolyDiamondBase { +public: + PolyDiamondSiblingDerived() + : PolyDiamondBase(), + name_("PolyDiamondSiblingDerived") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyDiamondMultiplyDerived: public PolyDiamondDerived, public PolyDiamondSiblingDerived { +public: + PolyDiamondMultiplyDerived() + : PolyDiamondDerived(), PolyDiamondSiblingDerived(), + name_("PolyDiamondMultiplyDerived") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +// End Inheritance Hierarchy Class Definitions + +std::map embind_test_get_string_int_map() { + std::map m; + + m["one"] = 1; + m["two"] = 2; + + return m; +}; + +struct Vector { + Vector() = delete; + + Vector(float x_, float y_, float z_, float w_) + : x(x_) + , y(y_) + , z(z_) + , w(w_) + {} + + float x, y, z, w; + + float& operator[](int i) { + return (&x)[i]; + } + + const float& operator[](int i) const { + return (&x)[i]; + } + + float getY() const { + return y; + } + void setY(float _y) { + y = _y; + } +}; + +struct DummyDataToTestPointerAdjustment { + std::string dummy; +}; + +struct TupleVector : DummyDataToTestPointerAdjustment, Vector { + TupleVector(): Vector(0, 0, 0, 0) {} + TupleVector(float x, float y, float z, float w): Vector(x, y, z, w) {} +}; + +struct StructVector : DummyDataToTestPointerAdjustment, Vector { + StructVector(): Vector(0, 0, 0, 0) {} + StructVector(float x, float y, float z, float w): Vector(x, y, z, w) {} +}; + +float readVectorZ(const Vector& v) { + return v.z; +} + +void writeVectorZ(Vector& v, float z) { + v.z = z; +} + +struct TupleVectorTuple { + TupleVector v = TupleVector(0, 0, 0, 0); +}; + +TupleVector emval_test_return_TupleVector() { + return TupleVector(1, 2, 3, 4); +} + +TupleVector emval_test_take_and_return_TupleVector(TupleVector v) { + return v; +} + +TupleVectorTuple emval_test_return_TupleVectorTuple() { + TupleVectorTuple cvt; + cvt.v = emval_test_return_TupleVector(); + return cvt; +} + +StructVector emval_test_return_StructVector() { + return StructVector(1, 2, 3, 4); +} + +StructVector emval_test_take_and_return_StructVector(StructVector v) { + return v; +} + +struct CustomStruct { + CustomStruct() + : field(10) + {} + + const int& getField() const { + return field; + } + + int field; +}; + +struct TupleInStruct { + TupleVector field; +}; + +TupleInStruct emval_test_take_and_return_TupleInStruct(TupleInStruct cs) { + return cs; +} + +struct NestedStruct { + int x; + int y; +}; +struct ArrayInStruct { + int field1[2]; + NestedStruct field2[2]; +}; +ArrayInStruct emval_test_take_and_return_ArrayInStruct(ArrayInStruct cs) { + return cs; +} + +enum Enum { ONE, TWO }; + +Enum emval_test_take_and_return_Enum(Enum e) { + return e; +} + +enum class EnumClass : char { ONE, TWO }; + +EnumClass emval_test_take_and_return_EnumClass(EnumClass e) { + return e; +} + +void emval_test_call_function(val v, int i, float f, TupleVector tv, StructVector sv) { + v(i, f, tv, sv); +} + +class UniquePtrToConstructor { +public: + UniquePtrToConstructor(std::unique_ptr p) + : value(*p) + {} + + int getValue() const { + return value; + } + +private: + int value; +}; + +std::unique_ptr embind_test_return_unique_ptr(int v) { + return std::unique_ptr(new int(v)); +} + +UniquePtrToConstructor* embind_test_construct_class_with_unique_ptr(int v) { + return new UniquePtrToConstructor(embind_test_return_unique_ptr(v)); +} + +int embind_test_accept_unique_ptr(std::unique_ptr p) { + return *p.get(); +} + +std::unique_ptr emval_test_return_unique_ptr() { + return std::unique_ptr(new ValHolder(val::object())); +} + +class UniquePtrLifetimeMock { +public: + UniquePtrLifetimeMock(val l) : logger(l) { + logger(std::string("(constructor)")); + } + ~UniquePtrLifetimeMock() { + logger(std::string("(destructor)")); + } + +private: + val logger; +}; + +std::unique_ptr emval_test_return_unique_ptr_lifetime(val logger) { + return std::unique_ptr(new UniquePtrLifetimeMock(logger)); +} + +std::shared_ptr emval_test_return_shared_ptr() { + return std::shared_ptr(new ValHolder(val::object())); +} + +std::shared_ptr emval_test_return_empty_shared_ptr() { + return std::shared_ptr(); +} + +bool emval_test_is_shared_ptr_null(std::shared_ptr p) { + return !p; +} + +static SmallClass smallClass; +static BigClass bigClass; + +SmallClass embind_test_return_small_class_instance() { + return smallClass; +} + +BigClass embind_test_return_big_class_instance() { + return bigClass; +} + +int embind_test_accept_small_class_instance(SmallClass c) { + return c.member; +} + +int embind_test_accept_big_class_instance(BigClass c) { + return c.member; +} + +// Begin Inheritance Hierarchy Test Wrappers + +Base* embind_test_return_raw_base_ptr() { + return new Base(); +} + +Base* embind_test_return_raw_derived_ptr_as_base() { + return new Derived(); +} + +Base* embind_test_return_raw_sibling_derived_ptr_as_base() { + return new SiblingDerived(); +} + +PolyBase* embind_test_return_raw_polymorphic_derived_ptr_as_base() { + return new PolyDerived(); +} + +PolyBase* embind_test_return_raw_polymorphic_sibling_derived_ptr_as_base() { + return new PolySiblingDerived(); +} + +PolyBase* embind_test_return_raw_polymorphic_multiply_derived_ptr_as_base() { + return new PolyMultiplyDerived(); +} + +PolySecondBase* embind_test_return_raw_polymorphic_multiply_derived_ptr_as_second_base() { + return new PolyMultiplyDerived(); +} + +PolyBase* embind_test_return_raw_polymorphic_derived_four_times_not_bound_as_base() { + return new PolyDerivedFourTimesNotBound(); +} + +std::shared_ptr embind_test_return_smart_base_ptr() { + return std::shared_ptr(new Base()); +} + +std::shared_ptr embind_test_return_smart_polymorphic_base_ptr() { + return std::shared_ptr(new PolyBase("PolyBase")); +} + +std::shared_ptr embind_test_return_smart_derived_ptr() { + return std::shared_ptr(new Derived()); +} + +std::shared_ptr embind_test_return_smart_sibling_derived_ptr() { + return std::shared_ptr(new SiblingDerived()); +} + +std::shared_ptr embind_test_return_smart_multiply_derived_ptr() { + return std::shared_ptr(new MultiplyDerived()); +} + +std::shared_ptr embind_test_return_smart_derived_thrice_ptr() { + return std::shared_ptr(new DerivedThrice()); +} + +std::shared_ptr embind_test_return_smart_polymorphic_derived_ptr() { + return std::shared_ptr(new PolyDerived()); +} + +std::shared_ptr embind_test_return_smart_polymorphic_sibling_derived_ptr() { + return std::shared_ptr(new PolySiblingDerived()); +} + +std::shared_ptr embind_test_return_smart_polymorphic_multiply_derived_ptr() { + return std::shared_ptr(new PolyMultiplyDerived()); +} + +std::shared_ptr embind_test_return_poly_derived_twice_without_smart_pointer_as_poly_base() { + return std::shared_ptr(new PolyDerivedTwiceWithoutSmartPointer()); +} + +std::shared_ptr embind_test_return_smart_poly_derived_thrice_ptr() { + return std::shared_ptr(new PolyDerivedThrice()); +} + +std::shared_ptr embind_test_return_smart_derived_ptr_as_base() { + return std::shared_ptr(new PolyDerived()); +} + +val embind_test_return_smart_derived_ptr_as_val() { + return val(std::shared_ptr(new PolyDerived())); +} + +std::shared_ptr embind_test_return_smart_polymorphic_derived_ptr_as_base() { + return std::shared_ptr(new PolyDerived()); +} + +std::shared_ptr embind_test_return_smart_polymorphic_sibling_derived_ptr_as_base() { + return std::shared_ptr(new PolySiblingDerived()); +} + +std::string embind_test_get_class_name_via_base_ptr(Base *p) { + return p->getClassName(); +} + +std::string embind_test_get_class_name_via_second_base_ptr(SecondBase *p) { + return p->getClassName(); +} + +std::string embind_test_get_class_name_via_polymorphic_base_ptr(PolyBase *p) { + return p->getClassName(); +} + +std::string embind_test_get_class_name_via_polymorphic_second_base_ptr(PolySecondBase *p) { + return p->getClassName(); +} + +std::string embind_test_get_class_name_via_smart_base_ptr(std::shared_ptr p) { + return p->getClassName(); +} + +std::string embind_test_get_class_name_via_reference_to_smart_base_ptr(std::shared_ptr& p) { + return p->getClassName(); +} + +std::string embind_test_get_class_name_via_smart_second_base_ptr(std::shared_ptr p) { + return p->getClassName(); +} + +std::string embind_test_get_class_name_via_smart_polymorphic_base_ptr(std::shared_ptr p) { + return p->getClassName(); +} + +std::string embind_test_get_virtual_class_name_via_smart_polymorphic_base_ptr(std::shared_ptr p) { + return p->virtualGetClassName(); +} + +std::string embind_test_get_class_name_via_smart_polymorphic_second_base_ptr(std::shared_ptr p) { + return p->getClassName(); +} + +void embind_modify_smart_pointer_passed_by_reference(std::shared_ptr& p) { + p = std::shared_ptr(new Base()); + p->name = "Changed"; +} + +void embind_attempt_to_modify_smart_pointer_when_passed_by_value(std::shared_ptr p) { + p = std::shared_ptr(new Base()); + p->name = "Changed"; +} + +static std::shared_ptr savedBasePointer; + +void embind_save_smart_base_pointer(std::shared_ptr p) { + savedBasePointer = p; +} + +// End Inheritance Hierarchy Test Wrappers + +std::vector emval_test_return_vector() { + int myints[] = { 10, 20, 30 }; + return std::vector(myints, myints + sizeof(myints) / sizeof(int)); +} + +std::vector > emval_test_return_vector_of_vectors() { + int myints1[] = { 10, 20, 30 }; + int myints2[] = { 40, 50, 60 }; + std::vector vec1(myints1, myints1 + sizeof(myints1) / sizeof(int)); + std::vector vec2(myints2, myints2 + sizeof(myints2) / sizeof(int)); + std::vector>vec3; + vec3.emplace_back(vec1); + vec3.emplace_back(vec2); + return vec3; +} + +std::vector> emval_test_return_shared_ptr_vector() { + std::vector> sharedStrVector; + sharedStrVector.push_back(std::shared_ptr(new StringHolder("string #1"))); + sharedStrVector.push_back(std::shared_ptr(new StringHolder("string #2"))); + + return sharedStrVector; +} + +void test_string_with_vec(const std::string& p1, std::vector& v1) { + // THIS DOES NOT WORK -- need to get as val and then call vecFromJSArray + printf("%s\n", p1.c_str()); +} + +val embind_test_getglobal() { + return val::global(); +} + +val embind_test_new_Object() { + return val::global("Object").new_(); +} + +val embind_test_new_factory(val factory, val argument) { + return factory.new_(10, std::string("hello"), argument); +} + +class AbstractClass { +public: + virtual ~AbstractClass() {} + virtual std::string abstractMethod() const = 0; + virtual std::string optionalMethod(std::string s) const { + return "optional" + s; + } + + virtual std::shared_ptr returnsSharedPtr() = 0; + virtual void differentArguments(int i, double d, unsigned char f, double q, std::string) = 0; + + std::string concreteMethod() const { + return "concrete"; + } + + virtual void passShared(const std::shared_ptr&) { + } + + virtual void passVal(const val& v) { + } +}; + +EMSCRIPTEN_SYMBOL(optionalMethod); + +class AbstractClassWrapper : public wrapper { +public: + EMSCRIPTEN_WRAPPER(AbstractClassWrapper); + + std::string abstractMethod() const override { + return call("abstractMethod"); + } + + std::string optionalMethod(std::string s) const override { + return call("optionalMethod", s); + } + + std::shared_ptr returnsSharedPtr() override { + return call >("returnsSharedPtr"); + } + + void differentArguments(int i, double d, unsigned char f, double q, std::string s) override { + return call("differentArguments", i, d, f, q, s); + } + + virtual void passShared(const std::shared_ptr& p) override { + return call("passShared", p); + } + + virtual void passVal(const val& v) override { + return call("passVal", v); + } +}; + +class ConcreteClass : public AbstractClass { + std::string abstractMethod() const { + return "from concrete"; + } + + void differentArguments(int i, double d, unsigned char f, double q, std::string s) { + } + + std::shared_ptr returnsSharedPtr() { + return std::shared_ptr(); + } +}; + +std::shared_ptr getAbstractClass() { + return std::make_shared(); +} + +std::string callAbstractMethod(AbstractClass& ac) { + return ac.abstractMethod(); +} + +std::string callOptionalMethod(AbstractClass& ac, std::string s) { + return ac.optionalMethod(s); +} + +void callReturnsSharedPtrMethod(AbstractClass& ac) { + std::shared_ptr sp = ac.returnsSharedPtr(); + // unused: sp +} + +void callDifferentArguments(AbstractClass& ac, int i, double d, unsigned char f, double q, std::string s) { + return ac.differentArguments(i, d, f, q, s); +} + +struct AbstractClassWithConstructor { + explicit AbstractClassWithConstructor(std::string s) + : s(s) + {} + + virtual ~AbstractClassWithConstructor() {}; + + virtual std::string abstractMethod() = 0; + std::string concreteMethod() { + return s; + } + + std::string s; +}; + +struct AbstractClassWithConstructorWrapper : public wrapper { + EMSCRIPTEN_WRAPPER(AbstractClassWithConstructorWrapper); + + virtual std::string abstractMethod() override { + return call("abstractMethod"); + } +}; + +std::string callAbstractMethod2(AbstractClassWithConstructor& ac) { + return ac.abstractMethod(); +} + +struct HeldAbstractClass : public PolyBase, public PolySecondBase { + virtual void method() = 0; +}; +struct HeldAbstractClassWrapper : wrapper { + EMSCRIPTEN_WRAPPER(HeldAbstractClassWrapper); + + virtual void method() override { + return call("method"); + } +}; + +std::shared_ptr passHeldAbstractClass(std::shared_ptr p) { + return p; +} + +void passShared(AbstractClass& ac) { + auto p = std::make_shared(); + ac.passShared(p); +} + +void passVal(AbstractClass& ac, val v) { + return ac.passVal(v); +} + +EMSCRIPTEN_BINDINGS(interface_tests) { + class_("AbstractClass") + .smart_ptr>("shared_ptr") + .allow_subclass("AbstractClassWrapper") + .function("abstractMethod", &AbstractClass::abstractMethod, pure_virtual()) + // The optional_override is necessary because, otherwise, the C++ compiler + // cannot deduce the signature of the lambda function. + .function("optionalMethod", optional_override( + [](AbstractClass& this_, const std::string& s) { + return this_.AbstractClass::optionalMethod(s); + } + )) + .function("concreteMethod", &AbstractClass::concreteMethod) + .function("passShared", select_overload&)>([](AbstractClass& self, const std::shared_ptr& derived) { + self.AbstractClass::passShared(derived); + })) + .function("passVal", select_overload([](AbstractClass& self, const val& v) { + self.AbstractClass::passVal(v); + })) + ; + + function("getAbstractClass", &getAbstractClass); + function("callAbstractMethod", &callAbstractMethod); + function("callOptionalMethod", &callOptionalMethod); + function("callReturnsSharedPtrMethod", &callReturnsSharedPtrMethod); + function("callDifferentArguments", &callDifferentArguments); + function("passShared", &passShared); + function("passVal", &passVal); + + class_("AbstractClassWithConstructor") + .allow_subclass("AbstractClassWithConstructorWrapper", constructor()) + .function("abstractMethod", &AbstractClassWithConstructor::abstractMethod, pure_virtual()) + .function("concreteMethod", &AbstractClassWithConstructor::concreteMethod) + ; + function("callAbstractMethod2", &callAbstractMethod2); + + class_>("HeldAbstractClass") + .smart_ptr>("shared_ptr") + .allow_subclass>("HeldAbstractClassWrapper", "HeldAbstractClassWrapperPtr") + .function("method", &HeldAbstractClass::method, pure_virtual()) + ; + function("passHeldAbstractClass", &passHeldAbstractClass); +} + +template +constexpr size_t getElementCount(T (&)[sizeOfArray]) { + return sizeOfArray; +} + +static void callWithMemoryView(val v) { + // static so the JS test can read the memory after callTakeMemoryView runs + static unsigned char data[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + v(typed_memory_view(getElementCount(data), data)); + static float f[] = { 1.5f, 2.5f, 3.5f, 4.5f }; + v(typed_memory_view(getElementCount(f), f)); + static short s[] = { 1000, 100, 10, 1 }; + v(typed_memory_view(getElementCount(s), s)); +} + +EMSCRIPTEN_BINDINGS(memory_view_tests) { + function("callWithMemoryView", &callWithMemoryView); +} + +class HasExternalConstructor { +public: + HasExternalConstructor(const std::string& str) + : m(str) + {} + + std::string getString() const { + return m; + } + + std::string m; +}; + +HasExternalConstructor* createHasExternalConstructor(const std::string& str) { + return new HasExternalConstructor(str); +} + +template +class CustomSmartPtr { +public: + CustomSmartPtr() + : CustomSmartPtr(nullptr) + { + std::fill(d_, d_ + N_, Valid); + } + + explicit CustomSmartPtr(T* t) + : ptr_(t) + { + std::fill(d_, d_ + N_, Valid); + } + + CustomSmartPtr(const CustomSmartPtr& other) + : ptr_(other.ptr_) + { + other.verify(); + std::fill(d_, d_ + N_, Valid); + if (ptr_) { + ++(ptr_->refcount); + } + } + + ~CustomSmartPtr() { + verify(); + std::fill(d_, d_ + N_, Deleted); + + if (ptr_ && --ptr_->refcount == 0) { + delete ptr_; + } + } + + T* get_raw() const { + return ptr_; + } + +private: + void verify() const { + for (size_t i = 0; i < N_; ++i) { + if (d_[i] != Valid) { + abort(); + } + } + } + + enum { + Valid = 255, + Deleted = 127, + }; + static constexpr size_t N_ = 1000000; + unsigned char d_[N_]; + T* ptr_; + + CustomSmartPtr& operator=(const CustomSmartPtr&) = delete; +}; + +class HeldBySmartPtr { +public: + HeldBySmartPtr(int i, const std::string& s) + : i(i) + , s(s) + {} + + static CustomSmartPtr newCustomPtr(int i, const std::string& s) { + return CustomSmartPtr(new HeldBySmartPtr(i, s)); + } + + int refcount = 1; + int i; + std::string s; +}; + +HeldBySmartPtr takesHeldBySmartPtr(HeldBySmartPtr p) { + return p; +} +std::shared_ptr takesHeldBySmartPtrSharedPtr(std::shared_ptr p) { + return p; +} + +namespace emscripten { + template + struct smart_ptr_trait> { + typedef CustomSmartPtr pointer_type; + typedef T element_type; + + static sharing_policy get_sharing_policy() { + return sharing_policy::NONE; + } + + static T* get(const CustomSmartPtr& p) { + return p.get_raw(); + } + + static CustomSmartPtr share(const CustomSmartPtr& r, T* ptr) { + ++ptr->refcount; // implement an adopt API? + return CustomSmartPtr(ptr); + } + + static pointer_type* construct_null() { + return new pointer_type; + } + }; +} + +typedef CustomSmartPtr HeldByCustomSmartPtrPtr; + +class HeldByCustomSmartPtr { +public: + HeldByCustomSmartPtr(int i, const std::string& s) + : i(i) + , s(s) + {} + + static HeldByCustomSmartPtrPtr create(int i, const std::string& s) { + return HeldByCustomSmartPtrPtr(new HeldByCustomSmartPtr(i, s)); + } + + static std::shared_ptr createSharedPtr(int i, const std::string& s) { + return std::make_shared(i, s); + }; + + int refcount = 1; + int i; + std::string s; +}; + +HeldByCustomSmartPtr* passThroughRawPtr(HeldByCustomSmartPtr* p) { + return p; +} +HeldByCustomSmartPtrPtr passThroughCustomSmartPtr(HeldByCustomSmartPtrPtr p) { + return p; +} + +struct Base1 { +public: + Base1(): field1("Base1") {} + std::string field1; + + std::string getField() const { + return field1; + } +}; + +struct Base2 { +public: + Base2(): field2("Base2") {} + std::string field2; + + std::string getField() const { + return field2; + } +}; + +struct HasTwoBases : public Base1, public Base2 { +}; + +val get_module_property(const std::string& s) { + return val::module_property(s.c_str()); +} + +std::string char_to_string(char ch) { + char str[256]; + sprintf(str, "%d", (int)ch); + return str; +} + +std::string signed_char_to_string(signed char ch) { + char str[256]; + sprintf(str, "%hhd", ch); + return str; +} + +std::string unsigned_char_to_string(unsigned char ch) { + char str[256]; + sprintf(str, "%hhu", ch); + return str; +} + +std::string short_to_string(short val) { + char str[256]; + sprintf(str, "%hd", val); + return str; +} + +std::string unsigned_short_to_string(unsigned short val) { + char str[256]; + sprintf(str, "%hu", val); + return str; +} + +std::string int_to_string(int val) { + char str[256]; + sprintf(str, "%d", val); + return str; +} + +std::string unsigned_int_to_string(unsigned int val) { + char str[256]; + sprintf(str, "%u", val); + return str; +} + +std::string long_to_string(long val) { + char str[256]; + sprintf(str, "%ld", val); + return str; +} + +std::string unsigned_long_to_string(unsigned long val) { + char str[256]; + sprintf(str, "%lu", val); + return str; +} + +//test loading unsigned value from memory +static unsigned char uchar; +void store_unsigned_char(unsigned char arg) { + uchar = arg; +} + +unsigned char load_unsigned_char() { + return uchar; +} + +static unsigned short ushort; +void store_unsigned_short(unsigned short arg) { + ushort = arg; +} + +unsigned short load_unsigned_short() { + return ushort; +} + +static unsigned int uint; +void store_unsigned_int(unsigned int arg) { + uint = arg; +} + +unsigned int load_unsigned_int() { + return uint; +} + +static unsigned long ulong; +void store_unsigned_long(unsigned long arg) { + ulong = arg; +} + +unsigned long load_unsigned_long() { + return ulong; +} + +template +class ConstructFromFunctor { +public: + ConstructFromFunctor(const val& v, int a) + : v_(v), a_(a) + {} + + val getVal() const { + return v_; + } + + int getA() const { + return a_; + } + +private: + val v_; + int a_; +}; + +template +ConstructFromFunctor construct_from_functor_mixin(const val& v, int i) +{ + return {v, i}; +} + +EMSCRIPTEN_BINDINGS(tests) { + register_vector("IntegerVector"); + register_vector("CharVector"); + register_vector("VectorUnsigned"); + register_vector("VectorUnsignedChar"); + register_vector("StringVector"); + register_vector("EmValVector"); + register_vector("FloatVector"); + register_vector>("IntegerVectorVector"); + + class_("DummyForPointer"); + + function("mallinfo", &emval_test_mallinfo); + function("emval_test_new_integer", &emval_test_new_integer); + function("emval_test_new_string", &emval_test_new_string); + function("emval_test_get_string_from_val", &emval_test_get_string_from_val); + function("emval_test_new_object", &emval_test_new_object); + function("emval_test_instance_pointer", &emval_test_instance_pointer); + function("emval_test_value_from_instance_pointer", &emval_test_value_from_instance_pointer); + function("emval_test_passthrough_unsigned", &emval_test_passthrough_unsigned); + function("emval_test_passthrough", &emval_test_passthrough); + function("emval_test_return_void", &emval_test_return_void); + function("emval_test_not", &emval_test_not); + + function("emval_test_is_true", &emval_test_is_true); + function("emval_test_is_false", &emval_test_is_false); + function("emval_test_is_null", &emval_test_is_null); + function("emval_test_is_undefined", &emval_test_is_undefined); + function("emval_test_equals", &emval_test_equals); + function("emval_test_strictly_equals", &emval_test_strictly_equals); + + function("emval_test_as_unsigned", &emval_test_as_unsigned); + function("emval_test_get_length", &emval_test_get_length); + function("emval_test_add", &emval_test_add); + function("const_ref_adder", &const_ref_adder); + function("emval_test_sum", &emval_test_sum); + + function("get_non_ascii_string", &get_non_ascii_string); + function("get_non_ascii_wstring", &get_non_ascii_wstring); + function("get_literal_wstring", &get_literal_wstring); + function("force_memory_growth", &force_memory_growth); + + //function("emval_test_take_and_return_const_char_star", &emval_test_take_and_return_const_char_star); + function("emval_test_take_and_return_std_string", &emval_test_take_and_return_std_string); + function("emval_test_take_and_return_std_string_const_ref", &emval_test_take_and_return_std_string_const_ref); + function("emval_test_take_and_return_std_basic_string_unsigned_char", &emval_test_take_and_return_std_basic_string_unsigned_char); + function("take_and_return_std_wstring", &take_and_return_std_wstring); + function("take_and_return_std_u16string", &take_and_return_std_u16string); + function("take_and_return_std_u32string", &take_and_return_std_u32string); + function("get_non_ascii_u16string", &get_non_ascii_u16string); + function("get_non_ascii_u32string", &get_non_ascii_u32string); + function("get_literal_u16string", &get_literal_u16string); + function("get_literal_u32string", &get_literal_u32string); + + //function("emval_test_take_and_return_CustomStruct", &emval_test_take_and_return_CustomStruct); + + value_array("TupleVector") + .element(&TupleVector::x) + .element(&Vector::getY, &Vector::setY) + .element(&readVectorZ, &writeVectorZ) + .element(emscripten::index<3>()) + ; + + function("emval_test_return_TupleVector", &emval_test_return_TupleVector); + function("emval_test_take_and_return_TupleVector", &emval_test_take_and_return_TupleVector); + + value_array("TupleVectorTuple") + .element(&TupleVectorTuple::v) + ; + + function("emval_test_return_TupleVectorTuple", &emval_test_return_TupleVectorTuple); + + value_object("StructVector") + .field("x", &StructVector::x) + .field("y", &Vector::getY, &Vector::setY) + .field("z", &readVectorZ, &writeVectorZ) + .field("w", emscripten::index<3>()) + ; + + function("emval_test_return_StructVector", &emval_test_return_StructVector); + function("emval_test_take_and_return_StructVector", &emval_test_take_and_return_StructVector); + + value_object("TupleInStruct") + .field("field", &TupleInStruct::field) + ; + + function("emval_test_take_and_return_TupleInStruct", &emval_test_take_and_return_TupleInStruct); + + + value_array>("array_int_2") + .element(emscripten::index<0>()) + .element(emscripten::index<1>()) + ; + value_array>("array_NestedStruct_2") + .element(emscripten::index<0>()) + .element(emscripten::index<1>()) + ; + value_object("NestedStruct") + .field("x", &NestedStruct::x) + .field("y", &NestedStruct::y) + ; + + value_object("ArrayInStruct") + .field("field1", &ArrayInStruct::field1) + .field("field2", &ArrayInStruct::field2) + ; + function("emval_test_take_and_return_ArrayInStruct", &emval_test_take_and_return_ArrayInStruct); + + using namespace std::placeholders; + + class_>("ConstructFromStdFunction") + .constructor(std::function(const val&, int)>(&construct_from_functor_mixin<1>)) + .function("getVal", &ConstructFromFunctor<1>::getVal) + .function("getA", &ConstructFromFunctor<1>::getA) + ; + + class_>("ConstructFromFunctionObject") + .constructor(const val&, int)>(std::bind(&construct_from_functor_mixin<2>, _1, _2)) + .function("getVal", &ConstructFromFunctor<2>::getVal) + .function("getA", &ConstructFromFunctor<2>::getA) + ; + + class_("ValHolder") + .smart_ptr>("std::shared_ptr") + .constructor() + .function("getVal", &ValHolder::getVal) + .function("getValNonConst", &ValHolder::getValNonConst) + .function("getConstVal", &ValHolder::getConstVal) + .function("getValConstRef", &ValHolder::getValConstRef) + .function("setVal", &ValHolder::setVal) + .function("getValFunction", std::function(&valholder_get_value_mixin)) + .function("setValFunction", std::function(&valholder_set_value_mixin)) + .function("getValFunctor", std::bind(&valholder_get_value_mixin, _1)) + .function("setValFunctor", std::bind(&valholder_set_value_mixin, _1, _2)) + .property("val", &ValHolder::getVal, &ValHolder::setVal) + .property("val_readonly", &ValHolder::getVal) + .property("readonly_function_val", std::function(&valholder_get_value_mixin)) + .property("function_val", std::function(&valholder_get_value_mixin), + std::function(&valholder_set_value_mixin)) + .property("readonly_functor_val", std::bind(&valholder_get_value_mixin, _1)) + .property("functor_val", std::bind(&valholder_get_value_mixin, _1), + std::bind(&valholder_set_value_mixin, _1, _2)) + .class_function("makeConst", &ValHolder::makeConst, allow_raw_pointer()) + .class_function("makeValHolder", &ValHolder::makeValHolder) + .class_function("some_class_method", &ValHolder::some_class_method) + .class_function("set_via_raw_pointer", + &ValHolder::set_via_raw_pointer, + allow_raw_pointer>()) + .class_function("get_via_raw_pointer", + &ValHolder::get_via_raw_pointer, + allow_raw_pointer>()) + .class_function("transfer_via_raw_pointer", + &ValHolder::transfer_via_raw_pointer, + allow_raw_pointers()) + + // non-member method + .function("setEmpty", &emval_test_set_ValHolder_to_empty_object) + .function("getValNonMember", &ValHolder::getValNonMember) + ; + + function("emval_test_return_ValHolder", &emval_test_return_ValHolder); + function("emval_test_set_ValHolder_to_empty_object", &emval_test_set_ValHolder_to_empty_object); + + class_>("StringFunctorString") + .constructor<>() + .function("opcall", &std::function::operator()) + ; + + function("emval_test_get_function_ptr", &emval_test_get_function_ptr); + function("emval_test_take_and_call_functor", &emval_test_take_and_call_functor); + + class_("StringHolder") + .smart_ptr>("shared_ptr") + .constructor() + .function("set", &StringHolder::set) + .function("get", &StringHolder::get) + .function("get_const_ref", &StringHolder::get_const_ref) + ; + + class_("SharedPtrHolder") + .constructor<>() + .function("get", &SharedPtrHolder::get) + .function("set", &SharedPtrHolder::set) + ; + + class_("SmallClass") + .constructor<>() + .property("member", &SmallClass::member) + ; + + class_("BigClass") + .constructor<>() + .property("member", &BigClass::member) + .property("otherMember", &BigClass::otherMember) + .property("yetAnotherMember", &BigClass::yetAnotherMember) + .function("getMember", &BigClass::getMember) + ; + + class_("ParentClass") + .constructor<>() + .function("getBigClass", &ParentClass::getBigClass) + ; + + class_>("IntTemplateClass") + .constructor() + .function("getMember", &TemplateClass::getMember) + ; + + class_("NoExceptClass") + .function("embind_test_no_except_function", &embind_test_no_except_function) + .function("getValue", &NoExceptClass::getValue) + .function("getValueConst", &NoExceptClass::getValueConst) + .property("x", &NoExceptClass::getX, &NoExceptClass::setX); + + class_("ContainsTemplatedMemberClass") + .constructor<>() + .function("getTestTemplate", &ContainsTemplatedMemberClass::getTestTemplate) + ; + + // Not supported in Go. + //class_("SymbolNameClass") + // .constructor<>() + // .function("@@iterator", &SymbolNameClass::iterator) + // .class_function("@@species", &SymbolNameClass::species) + // ; + + // register Derived before Base as a test that it's possible to + // register base classes afterwards + class_>("Derived") + .smart_ptr>("shared_ptr") + .constructor<>() + .function("getClassName", &Derived::getClassName) + .function("getMember", &Derived::getMember) + .function("setMember", &Derived::setMember) + .property("member", &Derived::member) + .class_function("classFunction", &Derived::classFunction) + ; + + class_("Base") + .smart_ptr>("shared_ptr() + .function("getClassName", &Base::getClassName) + .function("getClassNameFromBase", &Base::getClassNameFromBase) + .function("getClassNameNotAvailableInDerivedClasses", &Base::getClassNameNotAvailableInDerivedClasses) + .function("getMember", &Base::getMember) + .function("setMember", &Base::setMember) + .function("getBaseMember", &Base::getBaseMember) + .function("setBaseMember", &Base::setBaseMember) + .property("member", &Base::member) + .property("baseMember", &Base::baseMember) + .class_function("classFunction", &Base::classFunction) + ; + + class_("SecondBase") + .smart_ptr>("shared_ptr") + .constructor<>() + .function("getClassName", &SecondBase::getClassName) + .function("getClassNameFromSecondBase", &SecondBase::getClassNameFromSecondBase) + .function("getClassNameNotAvailableInDerivedClasses", &SecondBase::getClassNameNotAvailableInDerivedClasses) + .function("getMember", &SecondBase::getMember) + .function("setMember", &SecondBase::setMember) + .function("getSecondBaseMember", &SecondBase::getSecondBaseMember) + .function("setSecondBaseMember", &SecondBase::setSecondBaseMember) + .property("member", &SecondBase::member) + .property("secondBaseMember", &SecondBase::secondBaseMember) + ; + + + class_("DerivedHolder") + .constructor<>() + .function("newDerived", &DerivedHolder::newDerived) + .function("deleteDerived", &DerivedHolder::deleteDerived) + .function("getDerived", &DerivedHolder::getDerived) + .function("getDerivedClassName", &DerivedHolder::getDerivedClassName) + ; + + class_("SiblingDerived") + .smart_ptr>("shared_ptr") + .constructor<>() + .function("getClassName", &SiblingDerived::getClassName) + ; + + class_>("MultiplyDerived") + .smart_ptr>("shared_ptr") + .constructor<>() + .function("getClassName", &MultiplyDerived::getClassName) + .class_function("getInstanceCount", &MultiplyDerived::getInstanceCount) + ; + + class_ >("DerivedTwice") + .constructor<>() + .function("getClassName", &DerivedTwice::getClassName) + ; + + class_ >("DerivedThrice") + .smart_ptr>("shared_ptr") + .constructor<>() + .function("getClassName", &DerivedThrice::getClassName) + ; + + class_("PolyBase") + .smart_ptr>("shared_ptr") + .constructor<>() + .function("virtualGetClassName", &PolyBase::virtualGetClassName) + .function("getClassName", &PolyBase::getClassName) + ; + + class_("PolySecondBase") + .smart_ptr>("shared_ptr") + .constructor<>() + .function("getClassName", &PolySecondBase::getClassName) + ; + + class_>("PolyDerived") + .smart_ptr>("shared_ptr") + .constructor<>() + .function("virtualGetClassName", &PolyDerived::virtualGetClassName) + .function("getClassName", &PolyDerived::getClassName) + .class_function("setPtrDerived", &PolyDerived::setPtrDerived) + .class_function("releasePtr", &PolyDerived::releasePtr) + .class_function("getPtrClassName", &PolyDerived::getPtrClassName) + .class_function("getPtr", &PolyDerived::getPtr) + ; +// static void setPtrDerived() { +// ptr = std::shared_ptr(new PolyDerived()); +// } +// +// static std::string getPtrClassName() { +// return ptr->getClassName(); +// } +// +// static std::shared_ptr getPtr() { +// return ptr; +// } + + class_>("PolySiblingDerived") + .smart_ptr>("shared_ptr") + .constructor<>() + .function("getClassName", &PolySiblingDerived::getClassName) + ; + + class_>("PolyMultiplyDerived") + .smart_ptr>("shared_ptr") + .constructor<>() + .function("getClassName", &PolyMultiplyDerived::getClassName) + ; + + class_>("PolyDerivedThrice") + .smart_ptr>("shared_ptr") + .constructor<>() + .function("getClassName", &PolyDerivedThrice::getClassName) + ; + + class_("PolyDiamondBase") + .smart_ptr>("shared_ptr") + .constructor<>() + .function("getClassName", &PolyDiamondBase::getClassName) + ; + + class_("PolyDiamondDerived") + .smart_ptr>("shared_ptr") + .constructor<>() + .function("getClassName", &PolyDiamondDerived::getClassName) + ; + + class_("PolyDiamondSiblingDerived") + .smart_ptr>("shared_ptr") + .constructor<>() + .function("getClassName", &PolyDiamondSiblingDerived::getClassName) + ; + + class_("PolyDiamondMultiplyDerived") + .smart_ptr>("shared_ptr") + .constructor<>() + .function("getClassName", &PolyDiamondMultiplyDerived::getClassName) + ; + + function("embind_test_return_small_class_instance", &embind_test_return_small_class_instance); + function("embind_test_return_big_class_instance", &embind_test_return_big_class_instance); + function("embind_test_accept_small_class_instance", &embind_test_accept_small_class_instance); + function("embind_test_accept_big_class_instance", &embind_test_accept_big_class_instance); + + class_("UniquePtrToConstructor") + .function("getValue", &UniquePtrToConstructor::getValue) + ; + + function("embind_test_construct_class_with_unique_ptr", embind_test_construct_class_with_unique_ptr, allow_raw_pointer()); + function("embind_test_return_unique_ptr", embind_test_return_unique_ptr); + function("embind_test_accept_unique_ptr", embind_test_accept_unique_ptr); + + function("embind_test_return_raw_base_ptr", embind_test_return_raw_base_ptr, allow_raw_pointer()); + function("embind_test_return_raw_derived_ptr_as_base", embind_test_return_raw_derived_ptr_as_base, allow_raw_pointer()); + function("embind_test_return_raw_sibling_derived_ptr_as_base", embind_test_return_raw_sibling_derived_ptr_as_base, allow_raw_pointer()); + function("embind_test_return_raw_polymorphic_derived_ptr_as_base", embind_test_return_raw_polymorphic_derived_ptr_as_base, allow_raw_pointer()); + function("embind_test_return_raw_polymorphic_sibling_derived_ptr_as_base", embind_test_return_raw_polymorphic_sibling_derived_ptr_as_base, allow_raw_pointer()); + function("embind_test_return_raw_polymorphic_multiply_derived_ptr_as_base", embind_test_return_raw_polymorphic_multiply_derived_ptr_as_base, allow_raw_pointer()); + function("embind_test_return_raw_polymorphic_multiply_derived_ptr_as_second_base", embind_test_return_raw_polymorphic_multiply_derived_ptr_as_second_base, allow_raw_pointer()); + function("embind_test_return_raw_polymorphic_derived_four_times_not_bound_as_base", embind_test_return_raw_polymorphic_derived_four_times_not_bound_as_base, allow_raw_pointer()); + function("embind_test_return_smart_derived_ptr", embind_test_return_smart_derived_ptr); + function("embind_test_return_smart_sibling_derived_ptr", embind_test_return_smart_sibling_derived_ptr); + function("embind_test_return_smart_multiply_derived_ptr", embind_test_return_smart_multiply_derived_ptr); + function("embind_test_return_smart_derived_thrice_ptr", embind_test_return_smart_derived_thrice_ptr); + function("embind_test_return_smart_base_ptr", embind_test_return_smart_base_ptr); + function("embind_test_return_smart_polymorphic_base_ptr", embind_test_return_smart_polymorphic_base_ptr); + function("embind_test_return_smart_polymorphic_derived_ptr", embind_test_return_smart_polymorphic_derived_ptr); + function("embind_test_return_smart_polymorphic_sibling_derived_ptr", embind_test_return_smart_polymorphic_sibling_derived_ptr); + function("embind_test_return_smart_polymorphic_multiply_derived_ptr", embind_test_return_smart_polymorphic_multiply_derived_ptr); + function("embind_test_return_poly_derived_twice_without_smart_pointer_as_poly_base", embind_test_return_poly_derived_twice_without_smart_pointer_as_poly_base); + function("embind_test_return_smart_poly_derived_thrice_ptr", embind_test_return_smart_poly_derived_thrice_ptr); + function("embind_test_return_smart_derived_ptr_as_base", embind_test_return_smart_derived_ptr_as_base); + function("embind_test_return_smart_derived_ptr_as_val", embind_test_return_smart_derived_ptr_as_val); + function("embind_test_return_smart_polymorphic_derived_ptr_as_base", embind_test_return_smart_polymorphic_derived_ptr_as_base); + function("embind_test_return_smart_polymorphic_sibling_derived_ptr_as_base", embind_test_return_smart_polymorphic_sibling_derived_ptr_as_base); + function("embind_test_get_class_name_via_base_ptr", embind_test_get_class_name_via_base_ptr, allow_raw_pointer>()); + function("embind_test_get_class_name_via_second_base_ptr", embind_test_get_class_name_via_second_base_ptr, allow_raw_pointer>()); + function("embind_test_get_class_name_via_polymorphic_base_ptr", embind_test_get_class_name_via_polymorphic_base_ptr, allow_raw_pointer>()); + function("embind_test_get_class_name_via_polymorphic_second_base_ptr", embind_test_get_class_name_via_polymorphic_second_base_ptr, allow_raw_pointer>()); + // todo: allow_raw_pointer should fail earlier if argument is not a pointer + function("embind_test_get_class_name_via_smart_base_ptr", embind_test_get_class_name_via_smart_base_ptr); + function("embind_test_get_class_name_via_reference_to_smart_base_ptr", embind_test_get_class_name_via_reference_to_smart_base_ptr); + function("embind_test_get_class_name_via_smart_second_base_ptr", embind_test_get_class_name_via_smart_second_base_ptr); + function("embind_test_get_class_name_via_smart_polymorphic_base_ptr", embind_test_get_class_name_via_smart_polymorphic_base_ptr); + function("embind_test_get_virtual_class_name_via_smart_polymorphic_base_ptr", embind_test_get_virtual_class_name_via_smart_polymorphic_base_ptr); + function("embind_test_get_class_name_via_smart_polymorphic_second_base_ptr", embind_test_get_class_name_via_smart_polymorphic_second_base_ptr); + function("embind_modify_smart_pointer_passed_by_reference", embind_modify_smart_pointer_passed_by_reference); + function("embind_attempt_to_modify_smart_pointer_when_passed_by_value", embind_attempt_to_modify_smart_pointer_when_passed_by_value); + function("embind_save_smart_base_pointer", embind_save_smart_base_pointer); + + class_("Base1") + .constructor() + .function("getField", &Base1::getField) + ; + + class_("Base2") + .function("getField", &Base2::getField) + .property("field", &Base2::field2) + ; + + class_>("HasTwoBases") + .constructor() + ; + + class_("CustomStruct") + .constructor<>() + .property("field", &CustomStruct::field) + .function("getField", &CustomStruct::getField) + ; + + enum_("Enum") + .value("ONE", ONE) + .value("TWO", TWO) + ; + function("emval_test_take_and_return_Enum", &emval_test_take_and_return_Enum); + + enum_("EnumClass") + .value("ONE", EnumClass::ONE) + .value("TWO", EnumClass::TWO) + ; + function("emval_test_take_and_return_EnumClass", &emval_test_take_and_return_EnumClass); + + function("emval_test_call_function", &emval_test_call_function); + + function("emval_test_return_unique_ptr", &emval_test_return_unique_ptr); + + class_("UniquePtrLifetimeMock"); + function("emval_test_return_unique_ptr_lifetime", &emval_test_return_unique_ptr_lifetime); + + function("emval_test_return_shared_ptr", &emval_test_return_shared_ptr); + function("emval_test_return_empty_shared_ptr", &emval_test_return_empty_shared_ptr); + function("emval_test_is_shared_ptr_null", &emval_test_is_shared_ptr_null); + + function("emval_test_return_vector", &emval_test_return_vector); + function("emval_test_return_vector_of_vectors", &emval_test_return_vector_of_vectors); + + register_vector>("SharedPtrVector"); + function("emval_test_return_shared_ptr_vector", &emval_test_return_shared_ptr_vector); + + function("get_module_property", &get_module_property); + + register_vector("StringHolderVector"); + class_("VectorHolder") + .constructor<>() + .function("get", &VectorHolder::get) + .function("set", &VectorHolder::set) + ; + + function("test_string_with_vec", &test_string_with_vec); + + register_map("StringIntMap"); + function("embind_test_get_string_int_map", embind_test_get_string_int_map); + + function("embind_test_getglobal", &embind_test_getglobal); + + function("embind_test_new_Object", &embind_test_new_Object); + function("embind_test_new_factory", &embind_test_new_factory); + + class_("HasExternalConstructor") + .constructor(&createHasExternalConstructor) + .function("getString", &HasExternalConstructor::getString) + ; + + auto HeldBySmartPtr_class = class_("HeldBySmartPtr"); + HeldBySmartPtr_class + .smart_ptr>("CustomSmartPtr") + .smart_ptr_constructor("shared_ptr", &std::make_shared) + .class_function("newCustomPtr", HeldBySmartPtr::newCustomPtr) + .function("returnThis", &takesHeldBySmartPtrSharedPtr) + .property("i", &HeldBySmartPtr::i) + .property("s", &HeldBySmartPtr::s) + ; + function("takesHeldBySmartPtr", &takesHeldBySmartPtr); + function("takesHeldBySmartPtrSharedPtr", &takesHeldBySmartPtrSharedPtr); + + class_("HeldByCustomSmartPtr") + .smart_ptr>("shared_ptr") + .smart_ptr_constructor("CustomSmartPtr", &HeldByCustomSmartPtr::create) + .class_function("createSharedPtr", &HeldByCustomSmartPtr::createSharedPtr) + .property("i", &HeldByCustomSmartPtr::i) + .property("s", &HeldByCustomSmartPtr::s) + ; + + function("passThroughRawPtr", &passThroughRawPtr, allow_raw_pointers()); + function("passThroughCustomSmartPtr", &passThroughCustomSmartPtr); + + function("char_to_string", &char_to_string); + function("signed_char_to_string", &signed_char_to_string); + function("unsigned_char_to_string", &unsigned_char_to_string); + function("short_to_string", &short_to_string); + function("unsigned_short_to_string", &unsigned_short_to_string); + function("int_to_string", &int_to_string); + function("unsigned_int_to_string", &unsigned_int_to_string); + function("long_to_string", &long_to_string); + function("unsigned_long_to_string", &unsigned_long_to_string); + + function("store_unsigned_char", &store_unsigned_char); + function("load_unsigned_char", &load_unsigned_char); + function("store_unsigned_short", &store_unsigned_short); + function("load_unsigned_short", &load_unsigned_short); + function("store_unsigned_int", &store_unsigned_int); + function("load_unsigned_int", &load_unsigned_int); + function("store_unsigned_long", &store_unsigned_long); + function("load_unsigned_long", &load_unsigned_long); +} + +int overloaded_function(int i) { + assert(i == 10); + return 1; +} + +int overloaded_function(int i, int j) { + assert(i == 20); + assert(j == 20); + return 2; +} + +class MultipleCtors { +public: + int value = 0; + + MultipleCtors(int i) { + value = 1; + assert(i == 10); + } + MultipleCtors(int i, int j) { + value = 2; + assert(i == 20); + assert(j == 20); + } + MultipleCtors(int i, int j, int k) { + value = 3; + assert(i == 30); + assert(j == 30); + assert(k == 30); + } + + int WhichCtorCalled() const { + return value; + } +}; + +class MultipleSmartCtors { +public: + int value = 0; + + MultipleSmartCtors(int i) { + value = 1; + assert(i == 10); + } + MultipleSmartCtors(int i, int j) { + value = 2; + assert(i == 20); + assert(j == 20); + } + + int WhichCtorCalled() const { + return value; + } +}; + +class MultipleOverloads { +public: + MultipleOverloads() {} + + int value; + static int staticValue; + + int Func(int i) { + assert(i == 10); + value = 1; + return 1; + } + int Func(int i, int j) { + assert(i == 20); + assert(j == 20); + value = 2; + return 2; + } + + int WhichFuncCalled() const { + return value; + } + + static int StaticFunc(int i) { + assert(i == 10); + staticValue = 1; + return 1; + } + static int StaticFunc(int i, int j) { + assert(i == 20); + assert(j == 20); + staticValue = 2; + return 2; + } + + static int WhichStaticFuncCalled() { + return staticValue; + } +}; + +int MultipleOverloads::staticValue = 0; + +class MultipleOverloadsDerived : public MultipleOverloads { +public: + MultipleOverloadsDerived() {} + + int Func(int i, int j, int k) { + assert(i == 30); + assert(j == 30); + assert(k == 30); + value = 3; + return 3; + } + int Func(int i, int j, int k, int l) { + assert(i == 40); + assert(j == 40); + assert(k == 40); + assert(l == 40); + value = 4; + return 4; + } + + static int StaticFunc(int i, int j, int k) { + assert(i == 30); + assert(j == 30); + assert(k == 30); + staticValue = 3; + return 3; + } + static int StaticFunc(int i, int j, int k, int l) { + assert(i == 40); + assert(j == 40); + assert(k == 40); + assert(l == 40); + staticValue = 4; + return 4; + } +}; + +struct MultipleAccessors { + int getConst() { + return 1; + } + int getConst() const { + return 2; + } + int getConst(int i) const { + return i; + } +}; + +struct ConstAndNonConst { + void method(int) { + } + + int method() const { + return 10; + } +}; + +class DummyForOverloads {}; + +class MultipleOverloadsDependingOnDummy { +public: + DummyForOverloads dummy() { + return DummyForOverloads(); + } + + DummyForOverloads dummy(DummyForOverloads d) { + return d; + } + + static DummyForOverloads staticDummy() { + return DummyForOverloads(); + } + + static DummyForOverloads staticDummy(DummyForOverloads d) { + return d; + } + +}; + +DummyForOverloads getDummy() { + return DummyForOverloads(); +} + +DummyForOverloads getDummy(DummyForOverloads d) { + return d; +} + +EMSCRIPTEN_BINDINGS(overloads) { + function("overloaded_function", select_overload(&overloaded_function)); + function("overloaded_function", select_overload(&overloaded_function)); + + class_("MultipleCtors") + .constructor() + .constructor() + .constructor() + .function("WhichCtorCalled", &MultipleCtors::WhichCtorCalled) + ; + + class_("MultipleSmartCtors") + .smart_ptr>("shared_ptr") + .constructor(&std::make_shared) + .constructor(&std::make_shared) + .function("WhichCtorCalled", &MultipleSmartCtors::WhichCtorCalled) + ; + + class_("MultipleOverloads") + .constructor<>() + .function("Func", select_overload(&MultipleOverloads::Func)) + .function("Func", select_overload(&MultipleOverloads::Func)) + .function("WhichFuncCalled", &MultipleOverloads::WhichFuncCalled) + .class_function("StaticFunc", select_overload(&MultipleOverloads::StaticFunc)) + .class_function("StaticFunc", select_overload(&MultipleOverloads::StaticFunc)) + .class_function("WhichStaticFuncCalled", &MultipleOverloads::WhichStaticFuncCalled) + ; + + class_ >("MultipleOverloadsDerived") + .constructor<>() + .function("Func", select_overload(&MultipleOverloadsDerived::Func)) + .function("Func", select_overload(&MultipleOverloadsDerived::Func)) + .class_function("StaticFunc", select_overload(&MultipleOverloadsDerived::StaticFunc)) + .class_function("StaticFunc", select_overload(&MultipleOverloadsDerived::StaticFunc)) + ; + + class_("MultipleAccessors") + .function("getConst", select_overload(&MultipleAccessors::getConst)) + ; + + class_("ConstAndNonConst") + .function("method", select_const(&ConstAndNonConst::method)) + ; + + class_("DummyForOverloads").constructor(); + + class_("MultipleOverloadsDependingOnDummy") + .constructor() + .function("dummy", select_overload(&MultipleOverloadsDependingOnDummy::dummy)) + .function("dummy", select_overload(&MultipleOverloadsDependingOnDummy::dummy)) + .class_function("staticDummy", select_overload(&MultipleOverloadsDependingOnDummy::staticDummy)) + .class_function("staticDummy", select_overload(&MultipleOverloadsDependingOnDummy::staticDummy)) + ; + + function("getDummy", select_overload(&getDummy)); + function("getDummy", select_overload(&getDummy)); +} + +// tests for out-of-order registration + +class SecondElement { +}; + +class FirstElement { +}; + +struct OrderedTuple { + FirstElement first; + SecondElement second; +}; + +struct OrderedStruct { + FirstElement first; + SecondElement second; +}; + +OrderedTuple getOrderedTuple() { + return OrderedTuple(); +} + +OrderedStruct getOrderedStruct() { + return OrderedStruct(); +} + +EMSCRIPTEN_BINDINGS(order) { + value_array("OrderedTuple") + .element(&OrderedTuple::first) + .element(&OrderedTuple::second) + ; + + value_object("OrderedStruct") + .field("first", &OrderedStruct::first) + .field("second", &OrderedStruct::second) + ; + + class_("SecondElement") + ; + + class_("FirstElement") + ; + + function("getOrderedTuple", &getOrderedTuple); + function("getOrderedStruct", &getOrderedStruct); +} + +// tests for unbound types + +template +T passThrough(T t) { + return t; +} + +struct UnboundClass { +}; + +struct HasUnboundBase : public UnboundClass { + static void noop() { + } +}; + +HasUnboundBase getHasUnboundBase(HasUnboundBase f) { + return f; +} + +struct HasConstructorUsingUnboundArgument { + HasConstructorUsingUnboundArgument(UnboundClass) { + } +}; + +struct SecondUnboundClass { +}; + +struct HasConstructorUsingUnboundArgumentAndUnboundBase : public SecondUnboundClass { + HasConstructorUsingUnboundArgumentAndUnboundBase(UnboundClass) { + } +}; + +struct BoundClass { + UnboundClass method(UnboundClass t) { + return t; + } + + static UnboundClass classfunction(UnboundClass t) { + return t; + } + + UnboundClass property; +}; + +#ifndef SKIP_UNBOUND_TYPES +EMSCRIPTEN_BINDINGS(incomplete) { + constant("hasUnboundTypeNames", emscripten::has_unbound_type_names); + + function("getUnboundClass", &passThrough); + + class_>("HasUnboundBase") + .class_function("noop", &HasUnboundBase::noop) + ; + function("getHasUnboundBase", &passThrough); + + class_("HasConstructorUsingUnboundArgument") + .constructor() + ; + + class_>("HasConstructorUsingUnboundArgumentAndUnboundBase") + .constructor() + ; + + class_("BoundClass") + .constructor<>() + .function("method", &BoundClass::method) + .class_function("classfunction", &BoundClass::classfunction) + .property("property", &BoundClass::property) + ; +} +#endif + +class Noncopyable { + Noncopyable(const Noncopyable&) = delete; + Noncopyable& operator=(const Noncopyable&) = delete; + +public: + Noncopyable() {} + Noncopyable(Noncopyable&& other) { + other.valid = false; + } + + std::string method() const { + return "foo"; + } + + bool valid = true; +}; + +Noncopyable getNoncopyable() { + return Noncopyable(); +} + +EMSCRIPTEN_BINDINGS(noncopyable) { + class_("Noncopyable") + .constructor<>() + .function("method", &Noncopyable::method) + ; + + function("getNoncopyable", &getNoncopyable); +} + +struct HasReadOnlyProperty { + HasReadOnlyProperty(int i) + : i(i) + {} + + const int i; +}; + +EMSCRIPTEN_BINDINGS(read_only_properties) { + class_("HasReadOnlyProperty") + .constructor() + .property("i", &HasReadOnlyProperty::i) + ; +} + +struct StaticConstIntStruct { + static const int STATIC_CONST_INTEGER_VALUE_1; + static const int STATIC_CONST_INTEGER_VALUE_1000; +}; + +const int StaticConstIntStruct::STATIC_CONST_INTEGER_VALUE_1 = 1; +const int StaticConstIntStruct::STATIC_CONST_INTEGER_VALUE_1000 = 1000; + +EMSCRIPTEN_BINDINGS(constants) { + constant("INT_CONSTANT", 10); + + constant("STATIC_CONST_INTEGER_VALUE_1", StaticConstIntStruct::STATIC_CONST_INTEGER_VALUE_1); + constant("STATIC_CONST_INTEGER_VALUE_1000", StaticConstIntStruct::STATIC_CONST_INTEGER_VALUE_1000); + + constant("STRING_CONSTANT", std::string("some string")); + + TupleVector tv(1, 2, 3, 4); + constant("VALUE_ARRAY_CONSTANT", tv); + + StructVector sv(1, 2, 3, 4); + constant("VALUE_OBJECT_CONSTANT", sv); +} + +class DerivedWithOffset : public DummyDataToTestPointerAdjustment, public Base { +}; + +std::shared_ptr return_Base_from_DerivedWithOffset(std::shared_ptr ptr) { + return ptr; +} + +EMSCRIPTEN_BINDINGS(with_adjustment) { + class_>("DerivedWithOffset") + .smart_ptr_constructor("shared_ptr", &std::make_shared) + ; + + function("return_Base_from_DerivedWithOffset", &return_Base_from_DerivedWithOffset); +} + +void clear_StringHolder(StringHolder& sh) { + sh.set(""); +} + +EMSCRIPTEN_BINDINGS(references) { + function("clear_StringHolder", &clear_StringHolder); +} + +StringHolder return_StringHolder_copy(val func) { + return func.as(); +} + +StringHolder call_StringHolder_func(val func) { + return func().as(); +} + +EMSCRIPTEN_BINDINGS(return_values) { + function("return_StringHolder_copy", &return_StringHolder_copy); + function("call_StringHolder_func", &call_StringHolder_func); +} + + +struct Mixin { + int get10() const { + return 10; + } +}; + +template +const ClassBinding& registerMixin(const ClassBinding& binding) { + // need a wrapper for implicit conversion from DerivedWithMixin to Mixin + struct Local { + static int get10(const typename ClassBinding::class_type& self) { + return self.get10(); + } + }; + + return binding + .function("get10", &Local::get10) + ; +} + +class DerivedWithMixin : public Base, public Mixin { +}; + +EMSCRIPTEN_BINDINGS(mixins) { + registerMixin( + class_>("DerivedWithMixin") + .constructor<>() + ); +} + +template +T val_as(const val& v) { + return v.as(); +} + +EMSCRIPTEN_BINDINGS(val_as) { + function("val_as_bool", &val_as); + function("val_as_char", &val_as); + function("val_as_short", &val_as); + function("val_as_int", &val_as); + function("val_as_long", &val_as); + + function("val_as_float", &val_as); + function("val_as_double", &val_as); + + function("val_as_uint64_t", &val_as); + function("val_as_int64_t", &val_as); + + function("val_as_string", &val_as); + function("val_as_wstring", &val_as); + function("val_as_val", &val_as); + + function("val_as_value_object", &val_as); + function("val_as_value_array", &val_as); + + function("val_as_enum", &val_as); + + // memory_view is always JS -> C++ + //function("val_as_memory_view", &val_as); +} + +val construct_with_6(val factory) { + unsigned char a1 = 6; + double a2 = -12.5; + std::string a3("a3"); + StructVector a4(1, 2, 3, 4); + EnumClass a5 = EnumClass::TWO; + TupleVector a6(-1, -2, -3, -4); + return factory.new_(a1, a2, a3, a4, a5, a6); +} + +val construct_with_memory_view(val factory) { + static const char data[11] = "0123456789"; + return factory.new_( + std::string("before"), + typed_memory_view(10, data), + std::string("after")); +} + +val construct_with_ints_and_float(val factory) { + return factory.new_(65537, 4.0f, 65538); +} + +val construct_with_arguments_before_and_after_memory_growth() { + auto out = val::array(); + out.set(0, val::global("Uint8Array").new_(5)); + force_memory_growth(); + out.set(1, val::global("Uint8Array").new_(5)); + return out; +} + +EMSCRIPTEN_BINDINGS(val_new_) { + function("construct_with_6_arguments", &construct_with_6); + function("construct_with_memory_view", &construct_with_memory_view); + function("construct_with_ints_and_float", &construct_with_ints_and_float); + function( + "construct_with_arguments_before_and_after_memory_growth", + &construct_with_arguments_before_and_after_memory_growth); +} + +template +class intrusive_ptr { +public: + typedef T element_type; + + intrusive_ptr(std::nullptr_t = nullptr) + : px(nullptr) + {} + + template + explicit intrusive_ptr(U* px) + : px(px) + { + addRef(px); + } + + intrusive_ptr(const intrusive_ptr& that) + : px(that.px) + { + addRef(px); + } + + template + intrusive_ptr(const intrusive_ptr& that) + : px(that.get()) + { + addRef(px); + } + + intrusive_ptr& operator=(const intrusive_ptr& that) { + reset(that.get()); + return *this; + } + + intrusive_ptr& operator=(intrusive_ptr&& that) { + release(px); + px = that.px; + that.px = 0; + return *this; + } + + template + intrusive_ptr& operator=(const intrusive_ptr& that) { + reset(that.get()); + return *this; + } + + template + intrusive_ptr& operator=(intrusive_ptr&& that) { + release(px); + px = that.px; + that.px = 0; + return *this; + } + + ~intrusive_ptr() { + release(px); + } + + void reset(T* nx = nullptr) { + addRef(nx); + release(px); + px = nx; + } + + T* get() const { + return px; + } + + T& operator*() const { + return *px; + } + + T* operator->() const { + return px; + } + + explicit operator bool() const { + return px != nullptr; + } + + void swap(intrusive_ptr& rhs) { + std::swap(px, rhs.px); + } + +private: + void addRef(T* px) { + if (px) { + ++px->referenceCount; + } + } + + void release(T* px) { + if (px && --px->referenceCount == 0) { + delete px; + } + } + + T* px; + + template + friend class intrusive_ptr; +}; + +namespace emscripten { + template + struct smart_ptr_trait> { + typedef intrusive_ptr pointer_type; + typedef T element_type; + + static sharing_policy get_sharing_policy() { + return sharing_policy::INTRUSIVE; + } + + static T* get(const intrusive_ptr& p) { + return p.get(); + } + + static intrusive_ptr share(const intrusive_ptr& r, T* ptr) { + return intrusive_ptr(ptr); + } + + static pointer_type* construct_null() { + return new pointer_type; + } + }; +} + +template +intrusive_ptr make_intrusive_ptr() { + return intrusive_ptr(new T); +} + +struct IntrusiveClass { + virtual ~IntrusiveClass() {} + long referenceCount = 0; +}; + +struct IntrusiveClassWrapper : public wrapper { + EMSCRIPTEN_WRAPPER(IntrusiveClassWrapper); +}; + +template +struct Holder { + void set(const T& v) { + value = v; + } + const T& get() const { + return value; + } + T value; +}; + +EMSCRIPTEN_BINDINGS(intrusive_pointers) { + class_("IntrusiveClass") + .smart_ptr_constructor("intrusive_ptr", &make_intrusive_ptr) + .allow_subclass>("IntrusiveClassWrapper", "IntrusiveClassWrapperPtr") + ; + + typedef Holder> IntrusiveClassHolder; + class_("IntrusiveClassHolder") + .constructor<>() + .function("set", &IntrusiveClassHolder::set) + .function("get", &IntrusiveClassHolder::get) + ; + + function("passThroughIntrusiveClass", &passThrough>); +} + +std::string getTypeOfVal(const val& v) { + return v.typeOf().as(); +} + +EMSCRIPTEN_BINDINGS(typeOf) { + function("getTypeOfVal", &getTypeOfVal); +} + +struct HasStaticMember { + static const int c; + static int v; +}; + +const int HasStaticMember::c = 10; +int HasStaticMember::v = 20; + +EMSCRIPTEN_BINDINGS(static_member) { + class_("HasStaticMember") + .class_property("c", &HasStaticMember::c) + .class_property("v", &HasStaticMember::v) + ; +} diff --git a/testdata/wasm/emval.cpp b/testdata/wasm/emval.cpp new file mode 100644 index 0000000..0f11d65 --- /dev/null +++ b/testdata/wasm/emval.cpp @@ -0,0 +1,99 @@ +#include +#include +#include +#include + +using namespace emscripten; + +std::string doEmval() { + std::string result = ""; + val AudioContext = val::global("AudioContext"); + if (!AudioContext.as()) { + result += "No global AudioContext, trying webkitAudioContext\n"; + AudioContext = val::global("webkitAudioContext"); + } + + result += "Got an AudioContext\n"; + val context = AudioContext.new_(); + val oscillator = context.call("createOscillator"); + + result += "Configuring oscillator\n"; + oscillator.set("type", val("triangle")); + oscillator["frequency"].set("value", val(261.63)); // Middle C + + result += "Playing\n"; + oscillator.call("connect", context["destination"]); + oscillator.call("start", 0); + + result += "All done!\n"; + return result; +} + +bool emval_instance_of(const val& v, const val& v2) { + return v.instanceof(v2); +} + +val emval_type_of(const val& v) { + return v.typeOf(); +} + +bool emval_in(const val& v, const val& v2) { + return v.in(v2); +} + +void emval_throw(const val& v) { + return v.throw_(); +} + +void emval_delete(const val& v) { + v.delete_("test"); +} + +val emval_await(const val& v) { + return v.await(); +} + +bool emval_is_number(const val& v) { + return v.isNumber(); +} + +bool emval_is_string(const val& v) { + return v.isString(); +} + +bool emval_is_array(const val& v) { + return v.isArray(); +} + +bool emval_has_own_property(const val& v, const char* key) { + return v.hasOwnProperty(key); +} + +val emval_u16_string(const char16_t* s) { + return val::u16string(s); +} + +val emval_u8_string(const char* s) { + return val::u8string(s); +} + +val emval_array() { + return val::array(); +} + +EMSCRIPTEN_BINDINGS(emval) { + function("doEmval", &doEmval); + function("emval_instance_of", &emval_instance_of); + function("emval_type_of", &emval_type_of); + function("emval_in", &emval_in); + function("emval_throw", &emval_throw); + function("emval_delete", &emval_delete); + function("emval_await", &emval_await); + function("emval_is_number", &emval_is_number); + function("emval_is_string", &emval_is_string); + function("emval_is_array", &emval_is_array); + function("emval_has_own_property", &emval_has_own_property, allow_raw_pointers()); + function("emval_u16_string", &emval_u16_string, allow_raw_pointers()); + function("emval_u8_string", &emval_u8_string, allow_raw_pointers()); + function("emval_array", &emval_array); +} \ No newline at end of file diff --git a/testdata/wasm/enums.cpp b/testdata/wasm/enums.cpp new file mode 100644 index 0000000..872dca2 --- /dev/null +++ b/testdata/wasm/enums.cpp @@ -0,0 +1,29 @@ +#include + +using namespace emscripten; + +enum OldStyle { + OLD_STYLE_ONE, + OLD_STYLE_TWO +}; + +enum class NewStyle { + ONE, + TWO +}; + +OldStyle enum_in_enum_out(NewStyle ns) { + return OldStyle::OLD_STYLE_TWO; +} + +EMSCRIPTEN_BINDINGS(enums) { + enum_("OldStyle") + .value("ONE", OLD_STYLE_ONE) + .value("TWO", OLD_STYLE_TWO) + ; + enum_("NewStyle") + .value("ONE", NewStyle::ONE) + .value("TWO", NewStyle::TWO) + ; + function("enum_in_enum_out", &enum_in_enum_out); +} \ No newline at end of file diff --git a/testdata/wasm/functions.cpp b/testdata/wasm/functions.cpp new file mode 100644 index 0000000..b73927f --- /dev/null +++ b/testdata/wasm/functions.cpp @@ -0,0 +1,206 @@ +#include +using namespace emscripten; + +bool bool_return_true() { + return true; +} + +bool bool_return_false() { + return false; +} + +bool bool_return_bool(bool a) { + return a; +} + +void float_return_void(float a) {} + +float float_return_float(float a) { + return a*a; +} + +double double_return_double(double a) { + return a*a; +} + +int int_return_int(int a) { + return a * a; +} + +char char_return_char(char a) { + return a; +} + +long long_return_long(long a) { + return a+a; +} + +short short_return_short(short a) { + return a+a; +} + +unsigned char uchar_return_uchar(unsigned char a) { + return a; +} + +unsigned int uint_return_uint(unsigned int a) { + return a + a; +} + +unsigned long ulong_return_ulong(unsigned long a) { + return a + a; +} + +unsigned short ushort_return_ushort(unsigned short a) { + return a + a; +} + +long long longlong_return_longlong(long long a) { + return a + a; +} + +unsigned long long ulonglong_return_ulonglong(unsigned long long a) { + return a + a; +} + +std::string std_string_return_std_string(std::string in) { + return "Hello there " + in; +} + +std::wstring std_wstring_return_std_wstring(std::wstring in) { + return L"Hello there " + in; +} + +std::u16string std_u16string_return_std_u16string(std::u16string in) { + return u"Hello there " + in; +} + +std::vector return_vector () { + std::vector v(10, 1); + return v; +} + +std::map return_map () { + std::map m; + m.insert(std::pair(10, "This is a string.")); + return m; +} + +char data_char[] = {0, 1, 2, 3, 4, 5}; +unsigned char data_unsigned_char[] = {0, 1, 2, 3, 4, 5}; +int data_int[] = {0, 1, 2, 3, 4, 5}; +unsigned int data_unsigned_int[] = {0, 1, 2, 3, 4, 5}; +long data_long[] = {0, 1, 2, 3, 4, 5}; +unsigned long data_unsigned_long[] = {0, 1, 2, 3, 4, 5}; +short data_short[] = {0, 1, 2, 3, 4, 5}; +unsigned short data_unsigned_short[] = {0, 1, 2, 3, 4, 5}; +long long data_longlong[] = {0, 1, 2, 3, 4, 5}; +unsigned long long data_unsigned_longlong[] = {0, 1, 2, 3, 4, 5}; +double data_double[] = {0, 1, 2, 3, 4, 5}; +float data_float[] = {0, 1, 2, 3, 4, 5}; + +template +constexpr size_t getElementCount(T (&)[sizeOfArray]) { + return sizeOfArray; +} + +val get_memory_view_char() { + return val(typed_memory_view(getElementCount(data_char), data_char)); +} + +val get_memory_view_unsigned_char() { + return val(typed_memory_view(getElementCount(data_unsigned_char), data_unsigned_char)); +} + +val get_memory_view_int() { + return val(typed_memory_view(getElementCount(data_int), data_int)); +} + +val get_memory_view_unsigned_int() { + return val(typed_memory_view(getElementCount(data_unsigned_int), data_unsigned_int)); +} + +val get_memory_view_long() { + return val(typed_memory_view(getElementCount(data_long), data_long)); +} + +val get_memory_view_unsigned_long() { + return val(typed_memory_view(getElementCount(data_unsigned_long), data_unsigned_long)); +} + +val get_memory_view_short() { + return val(typed_memory_view(getElementCount(data_short), data_short)); +} + +val get_memory_view_unsigned_short() { + return val(typed_memory_view(getElementCount(data_unsigned_short), data_unsigned_short)); +} + +val get_memory_view_longlong() { + return val(typed_memory_view(getElementCount(data_longlong), data_longlong)); +} + +val get_memory_view_unsigned_longlong() { + return val(typed_memory_view(getElementCount(data_unsigned_longlong), data_unsigned_longlong)); +} + +val get_memory_view_double() { + return val(typed_memory_view(getElementCount(data_double), data_double)); +} + +val get_memory_view_float() { + return val(typed_memory_view(getElementCount(data_float), data_float)); +} + +int function_overload() { + return 1; +} + +int function_overload_2(int x) { + return 2; +} + +EMSCRIPTEN_BINDINGS(functions) { + function("bool_return_bool", &bool_return_bool); + function("bool_return_true", &bool_return_true); + function("bool_return_false", &bool_return_false); + function("float_return_void", &float_return_void); + function("float_return_float", &float_return_float); + function("double_return_double", &double_return_double); + function("int_return_int", &int_return_int); + function("char_return_char", &char_return_char); + function("long_return_long", &long_return_long); + function("short_return_short", &short_return_short); + function("uchar_return_uchar", &uchar_return_uchar); + function("uint_return_uint", &uint_return_uint); + function("ulong_return_ulong", &ulong_return_ulong); + function("ushort_return_ushort", &ushort_return_ushort); + function("longlong_return_longlong", &longlong_return_longlong); + function("ulonglong_return_ulonglong", &ulonglong_return_ulonglong); + function("std_string_return_std_string", &std_string_return_std_string); + function("std_wstring_return_std_wstring", &std_wstring_return_std_wstring); + function("std_u16string_return_std_u16string", &std_u16string_return_std_u16string); + + // Already registered in embind_test.cpp + //register_vector("vector"); + register_map("map"); + + function("return_vector", &return_vector); + function("return_map", &return_map); + + function("get_memory_view_char", &get_memory_view_char); + function("get_memory_view_unsigned_char", &get_memory_view_unsigned_char); + function("get_memory_view_int", &get_memory_view_int); + function("get_memory_view_unsigned_int", &get_memory_view_unsigned_int); + function("get_memory_view_long", &get_memory_view_long); + function("get_memory_view_unsigned_long", &get_memory_view_unsigned_long); + function("get_memory_view_short", &get_memory_view_short); + function("get_memory_view_unsigned_short", &get_memory_view_unsigned_short); + function("get_memory_view_longlong", &get_memory_view_longlong); + function("get_memory_view_unsigned_longlong", &get_memory_view_unsigned_longlong); + function("get_memory_view_double", &get_memory_view_double); + function("get_memory_view_float", &get_memory_view_float); + + function("function_overload", &function_overload); + function("function_overload", &function_overload_2); +} \ No newline at end of file diff --git a/testdata/wasm/structs.cpp b/testdata/wasm/structs.cpp new file mode 100644 index 0000000..d2ac3d1 --- /dev/null +++ b/testdata/wasm/structs.cpp @@ -0,0 +1,60 @@ +#include + +using namespace emscripten; + +struct Point2f { + float x; + float y; +}; + +// Array fields are treated as if they were std::array +struct ArrayInStructStruct { + int field[2]; +}; + +struct PersonRecord { + std::string name; + int age; + ArrayInStructStruct structArray; +}; + +PersonRecord findPersonAtLocation(Point2f) { + return PersonRecord{ + .name="123", + .age=12, + .structArray=ArrayInStructStruct{ + .field={1,2} + }, + }; +} + +void setPersonAtLocation(Point2f, PersonRecord) { +} + +EMSCRIPTEN_BINDINGS(structs) { + value_array("Point2f") + .element(&Point2f::x) + .element(&Point2f::y) + ; + + value_object("PersonRecord") + .field("name", &PersonRecord::name) + .field("age", &PersonRecord::age) + .field("structArray", &PersonRecord::structArray) + ; + + value_object("ArrayInStructStruct") + .field("field", &ArrayInStructStruct::field) // Need to register the array type + ; + + // Register std::array because ArrayInStructStruct::field is interpreted as such + // Already registered in embind_test.cpp + //value_array>("array_int_2") + // .element(emscripten::index<0>()) + // .element(emscripten::index<1>()) + // ; + + function("findPersonAtLocation", &findPersonAtLocation); + + function("setPersonAtLocation", &setPersonAtLocation); +} \ No newline at end of file diff --git a/testdata/wasm/test_custom_marshal.cpp b/testdata/wasm/test_custom_marshal.cpp new file mode 100644 index 0000000..7b38144 --- /dev/null +++ b/testdata/wasm/test_custom_marshal.cpp @@ -0,0 +1,81 @@ +// Copyright 2019 The Emscripten Authors. All rights reserved. +// Emscripten is available under two separate licenses, the MIT license and the +// University of Illinois/NCSA Open Source License. Both these licenses can be +// found in the LICENSE file. + +#include +#include +#include +#include +#include +#include + +using namespace emscripten; + +// Class which wraps int and have no explicit or implicit conversions. +struct IntWrapper { + int get() const { + return value; + } + static IntWrapper create(int v) { + return IntWrapper(v); + } + +private: + explicit IntWrapper(int v) : value(v) {} + int value; +}; + +// Need for SFINAE-based specialization testing. +template struct IsIntWrapper : std::false_type {}; +template<> struct IsIntWrapper : std::true_type {}; + +// We will pass IntWrapper between C++ and JavaScript via IntWrapperIntermediate +// which should be already registered by embind on both C++ and JavaScript sides. +// That way we can write C++ conversions only and use standard JS conversions. +using IntWrapperIntermediate = int; + +// Specify custom (un)marshalling for all types satisfying IsIntWrapper. +namespace emscripten { +namespace internal { +// remove_cv/remove_reference are required for TypeID, but not BindingType, see https://github.com/emscripten-core/emscripten/issues/7292 +template +struct TypeID::type>::type>::value, void>::type> { + static constexpr TYPEID get() { + return TypeID::get(); + } +}; + +template +struct BindingType::value, void>::type> { + typedef typename BindingType::WireType WireType; + + constexpr static WireType toWireType(const T& v) { + return BindingType::toWireType(v.get()); + } + constexpr static T fromWireType(WireType v) { + return T::create(BindingType::fromWireType(v)); + } +}; +} // namespace internal +} // namespace emscripten + +template +void test() { + IntWrapper x = IntWrapper::create(10); + val js_func = val::module_property("js_func"); + IntWrapper y = js_func(val(std::forward(x))).as(); + printf("C++ got %d\n", y.get()); +} + +void doCustomMarshalTest() { + test(); + test(); + test(); + test(); +} + +EMSCRIPTEN_BINDINGS(customMarshalTest) { + function("doCustomMarshalTest", doCustomMarshalTest); +} + diff --git a/testdata/wasm/test_finalization.cpp b/testdata/wasm/test_finalization.cpp new file mode 100644 index 0000000..a0a3dc4 --- /dev/null +++ b/testdata/wasm/test_finalization.cpp @@ -0,0 +1,27 @@ +#include +#include +#include + +class Foo { + std::string mName; + +public: + Foo(std::string name) : mName(name) {} + ~Foo() { std::cout << mName << " destructed" << std::endl; } +}; + +std::shared_ptr foo() { + return std::make_shared("Constructed from C++"); +} + +Foo* pFoo() { return new Foo("Foo*"); } + +using namespace emscripten; + +EMSCRIPTEN_BINDINGS(Marci) { + class_("Foo").smart_ptr_constructor>( + "Foo", &std::make_shared); + + function("foo", foo); + function("pFoo", pFoo, allow_raw_pointers()); +} diff --git a/testdata/wasm/test_unsigned.cpp b/testdata/wasm/test_unsigned.cpp new file mode 100644 index 0000000..71302fd --- /dev/null +++ b/testdata/wasm/test_unsigned.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 The Emscripten Authors. All rights reserved. +// Emscripten is available under two separate licenses, the MIT license and the +// University of Illinois/NCSA Open Source License. Both these licenses can be +// found in the LICENSE file. + +#include +#include +#include +static void set_bind_f64(emscripten::val val) { + printf("set_bind_f64: %x\n", (uint32_t)val.as()); +} +static void set_bind_u64(emscripten::val val) { + printf("set_bind_u64: %x\n", (uint32_t)val.as()); +} +static void set_bind_u32(emscripten::val val) { + printf("set_bind_u32: %x\n", val.as()); +} +extern "C" { + EMSCRIPTEN_KEEPALIVE void set_c_u64(uint64_t v) { + printf("set_c_u64: %x\n", (uint32_t)v); + } + EMSCRIPTEN_KEEPALIVE void set_c_u32(uint32_t v) { + printf("set_c_u32: %x\n", v); + } +} + +EMSCRIPTEN_BINDINGS(TEST) { + emscripten::function("set_bind_f64", &set_bind_f64); + emscripten::function("set_bind_u64", &set_bind_u64); + emscripten::function("set_bind_u32", &set_bind_u32); +} diff --git a/testdata/wasm/tests.html b/testdata/wasm/tests.html new file mode 100644 index 0000000..cf05aac --- /dev/null +++ b/testdata/wasm/tests.html @@ -0,0 +1,1294 @@ + + + + + + Emscripten-Generated Code + + + + + image/svg+xml + + +
+
Downloading...
+ + + Resize canvas + Lock/hide mouse pointer     + + + + +
+ +
+ + +
+ +
+ + + + + + diff --git a/testdata/wasm/tests.js b/testdata/wasm/tests.js new file mode 100644 index 0000000..4dd429d --- /dev/null +++ b/testdata/wasm/tests.js @@ -0,0 +1,8065 @@ +// include: shell.js +// The Module object: Our interface to the outside world. We import +// and export values on it. There are various ways Module can be used: +// 1. Not defined. We create it here +// 2. A function parameter, function(Module) { ..generated code.. } +// 3. pre-run appended it, var Module = {}; ..generated code.. +// 4. External script tag defines var Module. +// We need to check if Module already exists (e.g. case 3 above). +// Substitution will be replaced with actual code on later stage of the build, +// this way Closure Compiler will not mangle it (e.g. case 4. above). +// Note that if you want to run closure, and also to use Module +// after the generated code, you will need to define var Module = {}; +// before the code. Then that object will be used in the code, and you +// can continue to use Module afterwards as well. +var Module = typeof Module != 'undefined' ? Module : {}; + +// --pre-jses are emitted after the Module integration code, so that they can +// refer to Module (if they choose; they can also define Module) + + +// Sometimes an existing Module object exists with properties +// meant to overwrite the default module functionality. Here +// we collect those properties and reapply _after_ we configure +// the current environment's defaults to avoid having to be so +// defensive during initialization. +var moduleOverrides = Object.assign({}, Module); + +var arguments_ = []; +var thisProgram = './this.program'; +var quit_ = (status, toThrow) => { + throw toThrow; +}; + +// Determine the runtime environment we are in. You can customize this by +// setting the ENVIRONMENT setting at compile time (see settings.js). + +// Attempt to auto-detect the environment +var ENVIRONMENT_IS_WEB = typeof window == 'object'; +var ENVIRONMENT_IS_WORKER = typeof importScripts == 'function'; +// N.b. Electron.js environment is simultaneously a NODE-environment, but +// also a web environment. +var ENVIRONMENT_IS_NODE = typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string'; +var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; + +if (Module['ENVIRONMENT']) { + throw new Error('Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)'); +} + +// `/` should be present at the end if `scriptDirectory` is not empty +var scriptDirectory = ''; +function locateFile(path) { + if (Module['locateFile']) { + return Module['locateFile'](path, scriptDirectory); + } + return scriptDirectory + path; +} + +// Hooks that are implemented differently in different runtime environments. +var read_, + readAsync, + readBinary, + setWindowTitle; + +if (ENVIRONMENT_IS_NODE) { + if (typeof process == 'undefined' || !process.release || process.release.name !== 'node') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); + + var nodeVersion = process.versions.node; + var numericVersion = nodeVersion.split('.').slice(0, 3); + numericVersion = (numericVersion[0] * 10000) + (numericVersion[1] * 100) + (numericVersion[2].split('-')[0] * 1); + var minVersion = 160000; + if (numericVersion < 160000) { + throw new Error('This emscripten-generated code requires node v16.0.0 (detected v' + nodeVersion + ')'); + } + + // `require()` is no-op in an ESM module, use `createRequire()` to construct + // the require()` function. This is only necessary for multi-environment + // builds, `-sENVIRONMENT=node` emits a static import declaration instead. + // TODO: Swap all `require()`'s with `import()`'s? + // These modules will usually be used on Node.js. Load them eagerly to avoid + // the complexity of lazy-loading. + var fs = require('fs'); + var nodePath = require('path'); + + if (ENVIRONMENT_IS_WORKER) { + scriptDirectory = nodePath.dirname(scriptDirectory) + '/'; + } else { + scriptDirectory = __dirname + '/'; + } + +// include: node_shell_read.js +read_ = (filename, binary) => { + // We need to re-wrap `file://` strings to URLs. Normalizing isn't + // necessary in that case, the path should already be absolute. + filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename); + return fs.readFileSync(filename, binary ? undefined : 'utf8'); +}; + +readBinary = (filename) => { + var ret = read_(filename, true); + if (!ret.buffer) { + ret = new Uint8Array(ret); + } + assert(ret.buffer); + return ret; +}; + +readAsync = (filename, onload, onerror, binary = true) => { + // See the comment in the `read_` function. + filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename); + fs.readFile(filename, binary ? undefined : 'utf8', (err, data) => { + if (err) onerror(err); + else onload(binary ? data.buffer : data); + }); +}; +// end include: node_shell_read.js + if (!Module['thisProgram'] && process.argv.length > 1) { + thisProgram = process.argv[1].replace(/\\/g, '/'); + } + + arguments_ = process.argv.slice(2); + + if (typeof module != 'undefined') { + module['exports'] = Module; + } + + process.on('uncaughtException', (ex) => { + // suppress ExitStatus exceptions from showing an error + if (ex !== 'unwind' && !(ex instanceof ExitStatus) && !(ex.context instanceof ExitStatus)) { + throw ex; + } + }); + + quit_ = (status, toThrow) => { + process.exitCode = status; + throw toThrow; + }; + + Module['inspect'] = () => '[Emscripten Module object]'; + +} else +if (ENVIRONMENT_IS_SHELL) { + + if ((typeof process == 'object' && typeof require === 'function') || typeof window == 'object' || typeof importScripts == 'function') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); + + if (typeof read != 'undefined') { + read_ = read; + } + + readBinary = (f) => { + if (typeof readbuffer == 'function') { + return new Uint8Array(readbuffer(f)); + } + let data = read(f, 'binary'); + assert(typeof data == 'object'); + return data; + }; + + readAsync = (f, onload, onerror) => { + setTimeout(() => onload(readBinary(f))); + }; + + if (typeof clearTimeout == 'undefined') { + globalThis.clearTimeout = (id) => {}; + } + + if (typeof setTimeout == 'undefined') { + // spidermonkey lacks setTimeout but we use it above in readAsync. + globalThis.setTimeout = (f) => (typeof f == 'function') ? f() : abort(); + } + + if (typeof scriptArgs != 'undefined') { + arguments_ = scriptArgs; + } else if (typeof arguments != 'undefined') { + arguments_ = arguments; + } + + if (typeof quit == 'function') { + quit_ = (status, toThrow) => { + // Unlike node which has process.exitCode, d8 has no such mechanism. So we + // have no way to set the exit code and then let the program exit with + // that code when it naturally stops running (say, when all setTimeouts + // have completed). For that reason, we must call `quit` - the only way to + // set the exit code - but quit also halts immediately. To increase + // consistency with node (and the web) we schedule the actual quit call + // using a setTimeout to give the current stack and any exception handlers + // a chance to run. This enables features such as addOnPostRun (which + // expected to be able to run code after main returns). + setTimeout(() => { + if (!(toThrow instanceof ExitStatus)) { + let toLog = toThrow; + if (toThrow && typeof toThrow == 'object' && toThrow.stack) { + toLog = [toThrow, toThrow.stack]; + } + err(`exiting due to exception: ${toLog}`); + } + quit(status); + }); + throw toThrow; + }; + } + + if (typeof print != 'undefined') { + // Prefer to use print/printErr where they exist, as they usually work better. + if (typeof console == 'undefined') console = /** @type{!Console} */({}); + console.log = /** @type{!function(this:Console, ...*): undefined} */ (print); + console.warn = console.error = /** @type{!function(this:Console, ...*): undefined} */ (typeof printErr != 'undefined' ? printErr : print); + } + +} else + +// Note that this includes Node.js workers when relevant (pthreads is enabled). +// Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and +// ENVIRONMENT_IS_NODE. +if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { + if (ENVIRONMENT_IS_WORKER) { // Check worker, not web, since window could be polyfilled + scriptDirectory = self.location.href; + } else if (typeof document != 'undefined' && document.currentScript) { // web + scriptDirectory = document.currentScript.src; + } + // blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them. + // otherwise, slice off the final part of the url to find the script directory. + // if scriptDirectory does not contain a slash, lastIndexOf will return -1, + // and scriptDirectory will correctly be replaced with an empty string. + // If scriptDirectory contains a query (starting with ?) or a fragment (starting with #), + // they are removed because they could contain a slash. + if (scriptDirectory.indexOf('blob:') !== 0) { + scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf('/')+1); + } else { + scriptDirectory = ''; + } + + if (!(typeof window == 'object' || typeof importScripts == 'function')) throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); + + // Differentiate the Web Worker from the Node Worker case, as reading must + // be done differently. + { +// include: web_or_worker_shell_read.js +read_ = (url) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.send(null); + return xhr.responseText; + } + + if (ENVIRONMENT_IS_WORKER) { + readBinary = (url) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.responseType = 'arraybuffer'; + xhr.send(null); + return new Uint8Array(/** @type{!ArrayBuffer} */(xhr.response)); + }; + } + + readAsync = (url, onload, onerror) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = 'arraybuffer'; + xhr.onload = () => { + if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 + onload(xhr.response); + return; + } + onerror(); + }; + xhr.onerror = onerror; + xhr.send(null); + } + +// end include: web_or_worker_shell_read.js + } + + setWindowTitle = (title) => document.title = title; +} else +{ + throw new Error('environment detection error'); +} + +var out = Module['print'] || console.log.bind(console); +var err = Module['printErr'] || console.error.bind(console); + +// Merge back in the overrides +Object.assign(Module, moduleOverrides); +// Free the object hierarchy contained in the overrides, this lets the GC +// reclaim data used e.g. in memoryInitializerRequest, which is a large typed array. +moduleOverrides = null; +checkIncomingModuleAPI(); + +// Emit code to handle expected values on the Module object. This applies Module.x +// to the proper local x. This has two benefits: first, we only emit it if it is +// expected to arrive, and second, by using a local everywhere else that can be +// minified. + +if (Module['arguments']) arguments_ = Module['arguments'];legacyModuleProp('arguments', 'arguments_'); + +if (Module['thisProgram']) thisProgram = Module['thisProgram'];legacyModuleProp('thisProgram', 'thisProgram'); + +if (Module['quit']) quit_ = Module['quit'];legacyModuleProp('quit', 'quit_'); + +// perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message +// Assertions on removed incoming Module JS APIs. +assert(typeof Module['memoryInitializerPrefixURL'] == 'undefined', 'Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['pthreadMainPrefixURL'] == 'undefined', 'Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['cdInitializerPrefixURL'] == 'undefined', 'Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['filePackagePrefixURL'] == 'undefined', 'Module.filePackagePrefixURL option was removed, use Module.locateFile instead'); +assert(typeof Module['read'] == 'undefined', 'Module.read option was removed (modify read_ in JS)'); +assert(typeof Module['readAsync'] == 'undefined', 'Module.readAsync option was removed (modify readAsync in JS)'); +assert(typeof Module['readBinary'] == 'undefined', 'Module.readBinary option was removed (modify readBinary in JS)'); +assert(typeof Module['setWindowTitle'] == 'undefined', 'Module.setWindowTitle option was removed (modify setWindowTitle in JS)'); +assert(typeof Module['TOTAL_MEMORY'] == 'undefined', 'Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY'); +legacyModuleProp('asm', 'wasmExports'); +legacyModuleProp('read', 'read_'); +legacyModuleProp('readAsync', 'readAsync'); +legacyModuleProp('readBinary', 'readBinary'); +legacyModuleProp('setWindowTitle', 'setWindowTitle'); +var IDBFS = 'IDBFS is no longer included by default; build with -lidbfs.js'; +var PROXYFS = 'PROXYFS is no longer included by default; build with -lproxyfs.js'; +var WORKERFS = 'WORKERFS is no longer included by default; build with -lworkerfs.js'; +var NODEFS = 'NODEFS is no longer included by default; build with -lnodefs.js'; + +assert(!ENVIRONMENT_IS_SHELL, "shell environment detected but not enabled at build time. Add 'shell' to `-sENVIRONMENT` to enable."); + + +// end include: shell.js +// include: preamble.js +// === Preamble library stuff === + +// Documentation for the public APIs defined in this file must be updated in: +// site/source/docs/api_reference/preamble.js.rst +// A prebuilt local version of the documentation is available at: +// site/build/text/docs/api_reference/preamble.js.txt +// You can also build docs locally as HTML or other formats in site/ +// An online HTML version (which may be of a different version of Emscripten) +// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html + +var wasmBinary; +if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];legacyModuleProp('wasmBinary', 'wasmBinary'); +var noExitRuntime = Module['noExitRuntime'] || true;legacyModuleProp('noExitRuntime', 'noExitRuntime'); + +if (typeof WebAssembly != 'object') { + abort('no native wasm support detected'); +} + +// Wasm globals + +var wasmMemory; +var wasmExports; + +//======================================== +// Runtime essentials +//======================================== + +// whether we are quitting the application. no code should run after this. +// set in exit() and abort() +var ABORT = false; + +// set by exit() and abort(). Passed to 'onExit' handler. +// NOTE: This is also used as the process return code code in shell environments +// but only when noExitRuntime is false. +var EXITSTATUS; + +/** @type {function(*, string=)} */ +function assert(condition, text) { + if (!condition) { + abort('Assertion failed' + (text ? ': ' + text : '')); + } +} + +// We used to include malloc/free by default in the past. Show a helpful error in +// builds with assertions. + +// Memory management + +var HEAP, +/** @type {!Int8Array} */ + HEAP8, +/** @type {!Uint8Array} */ + HEAPU8, +/** @type {!Int16Array} */ + HEAP16, +/** @type {!Uint16Array} */ + HEAPU16, +/** @type {!Int32Array} */ + HEAP32, +/** @type {!Uint32Array} */ + HEAPU32, +/** @type {!Float32Array} */ + HEAPF32, +/** @type {!Float64Array} */ + HEAPF64; + +function updateMemoryViews() { + var b = wasmMemory.buffer; + Module['HEAP8'] = HEAP8 = new Int8Array(b); + Module['HEAP16'] = HEAP16 = new Int16Array(b); + Module['HEAP32'] = HEAP32 = new Int32Array(b); + Module['HEAPU8'] = HEAPU8 = new Uint8Array(b); + Module['HEAPU16'] = HEAPU16 = new Uint16Array(b); + Module['HEAPU32'] = HEAPU32 = new Uint32Array(b); + Module['HEAPF32'] = HEAPF32 = new Float32Array(b); + Module['HEAPF64'] = HEAPF64 = new Float64Array(b); +} + +assert(!Module['STACK_SIZE'], 'STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time') + +assert(typeof Int32Array != 'undefined' && typeof Float64Array !== 'undefined' && Int32Array.prototype.subarray != undefined && Int32Array.prototype.set != undefined, + 'JS engine does not provide full typed array support'); + +// If memory is defined in wasm, the user can't provide it, or set INITIAL_MEMORY +assert(!Module['wasmMemory'], 'Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally'); +assert(!Module['INITIAL_MEMORY'], 'Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically'); + +// include: runtime_init_table.js +// In regular non-RELOCATABLE mode the table is exported +// from the wasm module and this will be assigned once +// the exports are available. +var wasmTable; +// end include: runtime_init_table.js +// include: runtime_stack_check.js +// Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode. +function writeStackCookie() { + var max = _emscripten_stack_get_end(); + assert((max & 3) == 0); + // If the stack ends at address zero we write our cookies 4 bytes into the + // stack. This prevents interference with SAFE_HEAP and ASAN which also + // monitor writes to address zero. + if (max == 0) { + max += 4; + } + // The stack grow downwards towards _emscripten_stack_get_end. + // We write cookies to the final two words in the stack and detect if they are + // ever overwritten. + HEAPU32[((max)>>2)] = 0x02135467; + HEAPU32[(((max)+(4))>>2)] = 0x89BACDFE; + // Also test the global address 0 for integrity. + HEAPU32[((0)>>2)] = 1668509029; +} + +function checkStackCookie() { + if (ABORT) return; + var max = _emscripten_stack_get_end(); + // See writeStackCookie(). + if (max == 0) { + max += 4; + } + var cookie1 = HEAPU32[((max)>>2)]; + var cookie2 = HEAPU32[(((max)+(4))>>2)]; + if (cookie1 != 0x02135467 || cookie2 != 0x89BACDFE) { + abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${ptrToString(cookie2)} ${ptrToString(cookie1)}`); + } + // Also test the global address 0 for integrity. + if (HEAPU32[((0)>>2)] != 0x63736d65 /* 'emsc' */) { + abort('Runtime error: The application has corrupted its heap memory area (address zero)!'); + } +} +// end include: runtime_stack_check.js +// include: runtime_assertions.js +// Endianness check +(function() { + var h16 = new Int16Array(1); + var h8 = new Int8Array(h16.buffer); + h16[0] = 0x6373; + if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)'; +})(); + +// end include: runtime_assertions.js +var __ATPRERUN__ = []; // functions called before the runtime is initialized +var __ATINIT__ = []; // functions called during startup +var __ATEXIT__ = []; // functions called during shutdown +var __ATPOSTRUN__ = []; // functions called after the main() is called + +var runtimeInitialized = false; + +var runtimeKeepaliveCounter = 0; + +function keepRuntimeAlive() { + return noExitRuntime || runtimeKeepaliveCounter > 0; +} + +function preRun() { + if (Module['preRun']) { + if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; + while (Module['preRun'].length) { + addOnPreRun(Module['preRun'].shift()); + } + } + callRuntimeCallbacks(__ATPRERUN__); +} + +function initRuntime() { + assert(!runtimeInitialized); + runtimeInitialized = true; + + checkStackCookie(); + + +if (!Module["noFSInit"] && !FS.init.initialized) + FS.init(); +FS.ignorePermissions = false; + +TTY.init(); + callRuntimeCallbacks(__ATINIT__); +} + +function postRun() { + checkStackCookie(); + + if (Module['postRun']) { + if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; + while (Module['postRun'].length) { + addOnPostRun(Module['postRun'].shift()); + } + } + + callRuntimeCallbacks(__ATPOSTRUN__); +} + +function addOnPreRun(cb) { + __ATPRERUN__.unshift(cb); +} + +function addOnInit(cb) { + __ATINIT__.unshift(cb); +} + +function addOnExit(cb) { +} + +function addOnPostRun(cb) { + __ATPOSTRUN__.unshift(cb); +} + +// include: runtime_math.js +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc + +assert(Math.imul, 'This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +assert(Math.fround, 'This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +assert(Math.clz32, 'This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +assert(Math.trunc, 'This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); +// end include: runtime_math.js +// A counter of dependencies for calling run(). If we need to +// do asynchronous work before running, increment this and +// decrement it. Incrementing must happen in a place like +// Module.preRun (used by emcc to add file preloading). +// Note that you can add dependencies in preRun, even though +// it happens right before run - run will be postponed until +// the dependencies are met. +var runDependencies = 0; +var runDependencyWatcher = null; +var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled +var runDependencyTracking = {}; + +function getUniqueRunDependency(id) { + var orig = id; + while (1) { + if (!runDependencyTracking[id]) return id; + id = orig + Math.random(); + } +} + +function addRunDependency(id) { + runDependencies++; + + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } + + if (id) { + assert(!runDependencyTracking[id]); + runDependencyTracking[id] = 1; + if (runDependencyWatcher === null && typeof setInterval != 'undefined') { + // Check for missing dependencies every few seconds + runDependencyWatcher = setInterval(() => { + if (ABORT) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + return; + } + var shown = false; + for (var dep in runDependencyTracking) { + if (!shown) { + shown = true; + err('still waiting on run dependencies:'); + } + err('dependency: ' + dep); + } + if (shown) { + err('(end of list)'); + } + }, 10000); + } + } else { + err('warning: run dependency added without ID'); + } +} + +function removeRunDependency(id) { + runDependencies--; + + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } + + if (id) { + assert(runDependencyTracking[id]); + delete runDependencyTracking[id]; + } else { + err('warning: run dependency removed without ID'); + } + if (runDependencies == 0) { + if (runDependencyWatcher !== null) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + } + if (dependenciesFulfilled) { + var callback = dependenciesFulfilled; + dependenciesFulfilled = null; + callback(); // can add another dependenciesFulfilled + } + } +} + +/** @param {string|number=} what */ +function abort(what) { + if (Module['onAbort']) { + Module['onAbort'](what); + } + + what = 'Aborted(' + what + ')'; + // TODO(sbc): Should we remove printing and leave it up to whoever + // catches the exception? + err(what); + + ABORT = true; + EXITSTATUS = 1; + + // Use a wasm runtime error, because a JS error might be seen as a foreign + // exception, which means we'd run destructors on it. We need the error to + // simply make the program stop. + // FIXME This approach does not work in Wasm EH because it currently does not assume + // all RuntimeErrors are from traps; it decides whether a RuntimeError is from + // a trap or not based on a hidden field within the object. So at the moment + // we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that + // allows this in the wasm spec. + + // Suppress closure compiler warning here. Closure compiler's builtin extern + // defintion for WebAssembly.RuntimeError claims it takes no arguments even + // though it can. + // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed. + /** @suppress {checkTypes} */ + var e = new WebAssembly.RuntimeError(what); + + // Throw the error whether or not MODULARIZE is set because abort is used + // in code paths apart from instantiation where an exception is expected + // to be thrown when abort is called. + throw e; +} + +// include: memoryprofiler.js +// end include: memoryprofiler.js +// include: URIUtils.js +// Prefix of data URIs emitted by SINGLE_FILE and related options. +var dataURIPrefix = 'data:application/octet-stream;base64,'; + +// Indicates whether filename is a base64 data URI. +function isDataURI(filename) { + // Prefix of data URIs emitted by SINGLE_FILE and related options. + return filename.startsWith(dataURIPrefix); +} + +// Indicates whether filename is delivered via file protocol (as opposed to http/https) +function isFileURI(filename) { + return filename.startsWith('file://'); +} +// end include: URIUtils.js +function createExportWrapper(name) { + return function() { + assert(runtimeInitialized, `native function \`${name}\` called before runtime initialization`); + var f = wasmExports[name]; + assert(f, `exported native function \`${name}\` not found`); + return f.apply(null, arguments); + }; +} + +// include: runtime_exceptions.js +// end include: runtime_exceptions.js +var wasmBinaryFile; + wasmBinaryFile = 'tests.wasm'; + if (!isDataURI(wasmBinaryFile)) { + wasmBinaryFile = locateFile(wasmBinaryFile); + } + +function getBinarySync(file) { + if (file == wasmBinaryFile && wasmBinary) { + return new Uint8Array(wasmBinary); + } + if (readBinary) { + return readBinary(file); + } + throw "both async and sync fetching of the wasm failed"; +} + +function getBinaryPromise(binaryFile) { + // If we don't have the binary yet, try to load it asynchronously. + // Fetch has some additional restrictions over XHR, like it can't be used on a file:// url. + // See https://github.com/github/fetch/pull/92#issuecomment-140665932 + // Cordova or Electron apps are typically loaded from a file:// url. + // So use fetch if it is available and the url is not a file, otherwise fall back to XHR. + if (!wasmBinary + && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) { + if (typeof fetch == 'function' + && !isFileURI(binaryFile) + ) { + return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => { + if (!response['ok']) { + throw "failed to load wasm binary file at '" + binaryFile + "'"; + } + return response['arrayBuffer'](); + }).catch(() => getBinarySync(binaryFile)); + } + else if (readAsync) { + // fetch is not available or url is file => try XHR (readAsync uses XHR internally) + return new Promise((resolve, reject) => { + readAsync(binaryFile, (response) => resolve(new Uint8Array(/** @type{!ArrayBuffer} */(response))), reject) + }); + } + } + + // Otherwise, getBinarySync should be able to get it synchronously + return Promise.resolve().then(() => getBinarySync(binaryFile)); +} + +function instantiateArrayBuffer(binaryFile, imports, receiver) { + return getBinaryPromise(binaryFile).then((binary) => { + return WebAssembly.instantiate(binary, imports); + }).then((instance) => { + return instance; + }).then(receiver, (reason) => { + err('failed to asynchronously prepare wasm: ' + reason); + + // Warn on some common problems. + if (isFileURI(wasmBinaryFile)) { + err('warning: Loading from a file URI (' + wasmBinaryFile + ') is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing'); + } + abort(reason); + }); +} + +function instantiateAsync(binary, binaryFile, imports, callback) { + if (!binary && + typeof WebAssembly.instantiateStreaming == 'function' && + !isDataURI(binaryFile) && + // Don't use streaming for file:// delivered objects in a webview, fetch them synchronously. + !isFileURI(binaryFile) && + // Avoid instantiateStreaming() on Node.js environment for now, as while + // Node.js v18.1.0 implements it, it does not have a full fetch() + // implementation yet. + // + // Reference: + // https://github.com/emscripten-core/emscripten/pull/16917 + !ENVIRONMENT_IS_NODE && + typeof fetch == 'function') { + return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => { + // Suppress closure warning here since the upstream definition for + // instantiateStreaming only allows Promise rather than + // an actual Response. + // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure is fixed. + /** @suppress {checkTypes} */ + var result = WebAssembly.instantiateStreaming(response, imports); + + return result.then( + callback, + function(reason) { + // We expect the most common failure cause to be a bad MIME type for the binary, + // in which case falling back to ArrayBuffer instantiation should work. + err('wasm streaming compile failed: ' + reason); + err('falling back to ArrayBuffer instantiation'); + return instantiateArrayBuffer(binaryFile, imports, callback); + }); + }); + } + return instantiateArrayBuffer(binaryFile, imports, callback); +} + +// Create the wasm instance. +// Receives the wasm imports, returns the exports. +function createWasm() { + // prepare imports + var info = { + 'env': wasmImports, + 'wasi_snapshot_preview1': wasmImports, + }; + // Load the wasm module and create an instance of using native support in the JS engine. + // handle a generated wasm instance, receiving its exports and + // performing other necessary setup + /** @param {WebAssembly.Module=} module*/ + function receiveInstance(instance, module) { + var exports = instance.exports; + + wasmExports = exports; + + + wasmMemory = wasmExports['memory']; + + assert(wasmMemory, "memory not found in wasm exports"); + // This assertion doesn't hold when emscripten is run in --post-link + // mode. + // TODO(sbc): Read INITIAL_MEMORY out of the wasm file in post-link mode. + //assert(wasmMemory.buffer.byteLength === 16777216); + updateMemoryViews(); + + wasmTable = wasmExports['__indirect_function_table']; + + assert(wasmTable, "table not found in wasm exports"); + + addOnInit(wasmExports['__wasm_call_ctors']); + + removeRunDependency('wasm-instantiate'); + return exports; + } + // wait for the pthread pool (if any) + addRunDependency('wasm-instantiate'); + + // Prefer streaming instantiation if available. + // Async compilation can be confusing when an error on the page overwrites Module + // (for example, if the order of elements is wrong, and the one defining Module is + // later), so we save Module and check it later. + var trueModule = Module; + function receiveInstantiationResult(result) { + // 'result' is a ResultObject object which has both the module and instance. + // receiveInstance() will swap in the exports (to Module.asm) so they can be called + assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?'); + trueModule = null; + // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line. + // When the regression is fixed, can restore the above PTHREADS-enabled path. + receiveInstance(result['instance']); + } + + // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback + // to manually instantiate the Wasm module themselves. This allows pages to + // run the instantiation parallel to any other async startup actions they are + // performing. + // Also pthreads and wasm workers initialize the wasm instance through this + // path. + if (Module['instantiateWasm']) { + + try { + return Module['instantiateWasm'](info, receiveInstance); + } catch(e) { + err('Module.instantiateWasm callback failed with error: ' + e); + return false; + } + } + + instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult); + return {}; // no exports yet; we'll fill them in later +} + +// Globals used by JS i64 conversions (see makeSetValue) +var tempDouble; +var tempI64; + +// include: runtime_debug.js +function legacyModuleProp(prop, newName, incomming=true) { + if (!Object.getOwnPropertyDescriptor(Module, prop)) { + Object.defineProperty(Module, prop, { + configurable: true, + get() { + let extra = incomming ? ' (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)' : ''; + abort(`\`Module.${prop}\` has been replaced by \`${newName}\`` + extra); + + } + }); + } +} + +function ignoredModuleProp(prop) { + if (Object.getOwnPropertyDescriptor(Module, prop)) { + abort(`\`Module.${prop}\` was supplied but \`${prop}\` not included in INCOMING_MODULE_JS_API`); + } +} + +// forcing the filesystem exports a few things by default +function isExportedByForceFilesystem(name) { + return name === 'FS_createPath' || + name === 'FS_createDataFile' || + name === 'FS_createPreloadedFile' || + name === 'FS_unlink' || + name === 'addRunDependency' || + // The old FS has some functionality that WasmFS lacks. + name === 'FS_createLazyFile' || + name === 'FS_createDevice' || + name === 'removeRunDependency'; +} + +function missingGlobal(sym, msg) { + if (typeof globalThis !== 'undefined') { + Object.defineProperty(globalThis, sym, { + configurable: true, + get() { + warnOnce('`' + sym + '` is not longer defined by emscripten. ' + msg); + return undefined; + } + }); + } +} + +missingGlobal('buffer', 'Please use HEAP8.buffer or wasmMemory.buffer'); + +function missingLibrarySymbol(sym) { + if (typeof globalThis !== 'undefined' && !Object.getOwnPropertyDescriptor(globalThis, sym)) { + Object.defineProperty(globalThis, sym, { + configurable: true, + get() { + // Can't `abort()` here because it would break code that does runtime + // checks. e.g. `if (typeof SDL === 'undefined')`. + var msg = '`' + sym + '` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line'; + // DEFAULT_LIBRARY_FUNCS_TO_INCLUDE requires the name as it appears in + // library.js, which means $name for a JS name with no prefix, or name + // for a JS name like _name. + var librarySymbol = sym; + if (!librarySymbol.startsWith('_')) { + librarySymbol = '$' + sym; + } + msg += " (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='" + librarySymbol + "')"; + if (isExportedByForceFilesystem(sym)) { + msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; + } + warnOnce(msg); + return undefined; + } + }); + } + // Any symbol that is not included from the JS libary is also (by definition) + // not exported on the Module object. + unexportedRuntimeSymbol(sym); +} + +function unexportedRuntimeSymbol(sym) { + if (!Object.getOwnPropertyDescriptor(Module, sym)) { + Object.defineProperty(Module, sym, { + configurable: true, + get() { + var msg = "'" + sym + "' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)"; + if (isExportedByForceFilesystem(sym)) { + msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; + } + abort(msg); + } + }); + } +} + +// Used by XXXXX_DEBUG settings to output debug messages. +function dbg(text) { + // TODO(sbc): Make this configurable somehow. Its not always convenient for + // logging to show up as warnings. + console.warn.apply(console, arguments); +} +// end include: runtime_debug.js +// === Body === + +// end include: preamble.js + + /** @constructor */ + function ExitStatus(status) { + this.name = 'ExitStatus'; + this.message = `Program terminated with exit(${status})`; + this.status = status; + } + + var callRuntimeCallbacks = (callbacks) => { + while (callbacks.length > 0) { + // Pass the module as the first argument. + callbacks.shift()(Module); + } + }; + + + /** + * @param {number} ptr + * @param {string} type + */ + function getValue(ptr, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': return HEAP8[((ptr)>>0)]; + case 'i8': return HEAP8[((ptr)>>0)]; + case 'i16': return HEAP16[((ptr)>>1)]; + case 'i32': return HEAP32[((ptr)>>2)]; + case 'i64': abort('to do getValue(i64) use WASM_BIGINT'); + case 'float': return HEAPF32[((ptr)>>2)]; + case 'double': return HEAPF64[((ptr)>>3)]; + case '*': return HEAPU32[((ptr)>>2)]; + default: abort(`invalid type for getValue: ${type}`); + } + } + + var ptrToString = (ptr) => { + assert(typeof ptr === 'number'); + // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned. + ptr >>>= 0; + return '0x' + ptr.toString(16).padStart(8, '0'); + }; + + + /** + * @param {number} ptr + * @param {number} value + * @param {string} type + */ + function setValue(ptr, value, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': HEAP8[((ptr)>>0)] = value; break; + case 'i8': HEAP8[((ptr)>>0)] = value; break; + case 'i16': HEAP16[((ptr)>>1)] = value; break; + case 'i32': HEAP32[((ptr)>>2)] = value; break; + case 'i64': abort('to do setValue(i64) use WASM_BIGINT'); + case 'float': HEAPF32[((ptr)>>2)] = value; break; + case 'double': HEAPF64[((ptr)>>3)] = value; break; + case '*': HEAPU32[((ptr)>>2)] = value; break; + default: abort(`invalid type for setValue: ${type}`); + } + } + + var warnOnce = (text) => { + if (!warnOnce.shown) warnOnce.shown = {}; + if (!warnOnce.shown[text]) { + warnOnce.shown[text] = 1; + if (ENVIRONMENT_IS_NODE) text = 'warning: ' + text; + err(text); + } + }; + + var UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf8') : undefined; + + /** + * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given + * array that contains uint8 values, returns a copy of that string as a + * Javascript String object. + * heapOrArray is either a regular array, or a JavaScript typed array view. + * @param {number} idx + * @param {number=} maxBytesToRead + * @return {string} + */ + var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => { + var endIdx = idx + maxBytesToRead; + var endPtr = idx; + // TextDecoder needs to know the byte length in advance, it doesn't stop on + // null terminator by itself. Also, use the length info to avoid running tiny + // strings through TextDecoder, since .subarray() allocates garbage. + // (As a tiny code save trick, compare endPtr against endIdx using a negation, + // so that undefined means Infinity) + while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr; + + if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) { + return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr)); + } + var str = ''; + // If building with TextDecoder, we have already computed the string length + // above, so test loop end condition against that + while (idx < endPtr) { + // For UTF8 byte structure, see: + // http://en.wikipedia.org/wiki/UTF-8#Description + // https://www.ietf.org/rfc/rfc2279.txt + // https://tools.ietf.org/html/rfc3629 + var u0 = heapOrArray[idx++]; + if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; } + var u1 = heapOrArray[idx++] & 63; + if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } + var u2 = heapOrArray[idx++] & 63; + if ((u0 & 0xF0) == 0xE0) { + u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; + } else { + if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte ' + ptrToString(u0) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!'); + u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63); + } + + if (u0 < 0x10000) { + str += String.fromCharCode(u0); + } else { + var ch = u0 - 0x10000; + str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); + } + } + return str; + }; + + /** + * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the + * emscripten HEAP, returns a copy of that string as a Javascript String object. + * + * @param {number} ptr + * @param {number=} maxBytesToRead - An optional length that specifies the + * maximum number of bytes to read. You can omit this parameter to scan the + * string until the first 0 byte. If maxBytesToRead is passed, and the string + * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the + * string will cut short at that byte index (i.e. maxBytesToRead will not + * produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing + * frequent uses of UTF8ToString() with and without maxBytesToRead may throw + * JS JIT optimizations off, so it is worth to consider consistently using one + * @return {string} + */ + var UTF8ToString = (ptr, maxBytesToRead) => { + assert(typeof ptr == 'number'); + return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ''; + }; + var ___assert_fail = (condition, filename, line, func) => { + abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']); + }; + + /** @constructor */ + function ExceptionInfo(excPtr) { + this.excPtr = excPtr; + this.ptr = excPtr - 24; + + this.set_type = function(type) { + HEAPU32[(((this.ptr)+(4))>>2)] = type; + }; + + this.get_type = function() { + return HEAPU32[(((this.ptr)+(4))>>2)]; + }; + + this.set_destructor = function(destructor) { + HEAPU32[(((this.ptr)+(8))>>2)] = destructor; + }; + + this.get_destructor = function() { + return HEAPU32[(((this.ptr)+(8))>>2)]; + }; + + this.set_caught = function (caught) { + caught = caught ? 1 : 0; + HEAP8[(((this.ptr)+(12))>>0)] = caught; + }; + + this.get_caught = function () { + return HEAP8[(((this.ptr)+(12))>>0)] != 0; + }; + + this.set_rethrown = function (rethrown) { + rethrown = rethrown ? 1 : 0; + HEAP8[(((this.ptr)+(13))>>0)] = rethrown; + }; + + this.get_rethrown = function () { + return HEAP8[(((this.ptr)+(13))>>0)] != 0; + }; + + // Initialize native structure fields. Should be called once after allocated. + this.init = function(type, destructor) { + this.set_adjusted_ptr(0); + this.set_type(type); + this.set_destructor(destructor); + } + + this.set_adjusted_ptr = function(adjustedPtr) { + HEAPU32[(((this.ptr)+(16))>>2)] = adjustedPtr; + }; + + this.get_adjusted_ptr = function() { + return HEAPU32[(((this.ptr)+(16))>>2)]; + }; + + // Get pointer which is expected to be received by catch clause in C++ code. It may be adjusted + // when the pointer is casted to some of the exception object base classes (e.g. when virtual + // inheritance is used). When a pointer is thrown this method should return the thrown pointer + // itself. + this.get_exception_ptr = function() { + // Work around a fastcomp bug, this code is still included for some reason in a build without + // exceptions support. + var isPointer = ___cxa_is_pointer_type(this.get_type()); + if (isPointer) { + return HEAPU32[((this.excPtr)>>2)]; + } + var adjusted = this.get_adjusted_ptr(); + if (adjusted !== 0) return adjusted; + return this.excPtr; + }; + } + + var exceptionLast = 0; + + var uncaughtExceptionCount = 0; + function ___cxa_throw(ptr, type, destructor) { + var info = new ExceptionInfo(ptr); + // Initialize ExceptionInfo content after it was allocated in __cxa_allocate_exception. + info.init(type, destructor); + exceptionLast = ptr; + uncaughtExceptionCount++; + assert(false, 'Exception thrown, but exception catching is not enabled. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.'); + } + + var char_0 = 48; + + var char_9 = 57; + function makeLegalFunctionName(name) { + if (undefined === name) { + return '_unknown'; + } + name = name.replace(/[^a-zA-Z0-9_]/g, '$'); + var f = name.charCodeAt(0); + if (f >= char_0 && f <= char_9) { + return `_${name}`; + } + return name; + } + function createNamedFunction(name, body) { + name = makeLegalFunctionName(name); + // Use an abject with a computed property name to create a new function with + // a name specified at runtime, but without using `new Function` or `eval`. + return { + [name]: function() { + return body.apply(this, arguments); + } + }[name]; + } + + function handleAllocatorInit() { + Object.assign(HandleAllocator.prototype, /** @lends {HandleAllocator.prototype} */ { + get(id) { + assert(this.allocated[id] !== undefined, `invalid handle: ${id}`); + return this.allocated[id]; + }, + has(id) { + return this.allocated[id] !== undefined; + }, + allocate(handle) { + var id = this.freelist.pop() || this.allocated.length; + this.allocated[id] = handle; + return id; + }, + free(id) { + assert(this.allocated[id] !== undefined); + // Set the slot to `undefined` rather than using `delete` here since + // apparently arrays with holes in them can be less efficient. + this.allocated[id] = undefined; + this.freelist.push(id); + } + }); + } + /** @constructor */ + function HandleAllocator() { + // Reserve slot 0 so that 0 is always an invalid handle + this.allocated = [undefined]; + this.freelist = []; + } + var emval_handles = new HandleAllocator();; + + var BindingError = undefined; + function throwBindingError(message) { + throw new BindingError(message); + } + + function count_emval_handles() { + var count = 0; + for (var i = emval_handles.reserved; i < emval_handles.allocated.length; ++i) { + if (emval_handles.allocated[i] !== undefined) { + ++count; + } + } + return count; + } + + function init_emval() { + // reserve some special values. These never get de-allocated. + // The HandleAllocator takes care of reserving zero. + emval_handles.allocated.push( + {value: undefined}, + {value: null}, + {value: true}, + {value: false}, + ); + emval_handles.reserved = emval_handles.allocated.length + Module['count_emval_handles'] = count_emval_handles; + } + var Emval = { + toValue:(handle) => { + if (!handle) { + throwBindingError('Cannot use deleted val. handle = ' + handle); + } + return emval_handles.get(handle).value; + }, + toHandle:(value) => { + switch (value) { + case undefined: return 1; + case null: return 2; + case true: return 3; + case false: return 4; + default:{ + return emval_handles.allocate({refcount: 1, value: value}); + } + } + }, + }; + + function extendError(baseErrorType, errorName) { + var errorClass = createNamedFunction(errorName, function(message) { + this.name = errorName; + this.message = message; + + var stack = (new Error(message)).stack; + if (stack !== undefined) { + this.stack = this.toString() + '\n' + + stack.replace(/^Error(:[^\n]*)?\n/, ''); + } + }); + errorClass.prototype = Object.create(baseErrorType.prototype); + errorClass.prototype.constructor = errorClass; + errorClass.prototype.toString = function() { + if (this.message === undefined) { + return this.name; + } else { + return `${this.name}: ${this.message}`; + } + }; + + return errorClass; + } + var PureVirtualError = undefined; + + function embind_init_charCodes() { + var codes = new Array(256); + for (var i = 0; i < 256; ++i) { + codes[i] = String.fromCharCode(i); + } + embind_charCodes = codes; + } + var embind_charCodes = undefined; + function readLatin1String(ptr) { + var ret = ""; + var c = ptr; + while (HEAPU8[c]) { + ret += embind_charCodes[HEAPU8[c++]]; + } + return ret; + } + + function getInheritedInstanceCount() { + return Object.keys(registeredInstances).length; + } + + function getLiveInheritedInstances() { + var rv = []; + for (var k in registeredInstances) { + if (registeredInstances.hasOwnProperty(k)) { + rv.push(registeredInstances[k]); + } + } + return rv; + } + + var deletionQueue = []; + function flushPendingDeletes() { + while (deletionQueue.length) { + var obj = deletionQueue.pop(); + obj.$$.deleteScheduled = false; + obj['delete'](); + } + } + + var delayFunction = undefined; + + + function setDelayFunction(fn) { + delayFunction = fn; + if (deletionQueue.length && delayFunction) { + delayFunction(flushPendingDeletes); + } + } + function init_embind() { + Module['getInheritedInstanceCount'] = getInheritedInstanceCount; + Module['getLiveInheritedInstances'] = getLiveInheritedInstances; + Module['flushPendingDeletes'] = flushPendingDeletes; + Module['setDelayFunction'] = setDelayFunction; + } + var registeredInstances = { + }; + + function getBasestPointer(class_, ptr) { + if (ptr === undefined) { + throwBindingError('ptr should not be undefined'); + } + while (class_.baseClass) { + ptr = class_.upcast(ptr); + class_ = class_.baseClass; + } + return ptr; + } + + function registerInheritedInstance(class_, ptr, instance) { + ptr = getBasestPointer(class_, ptr); + if (registeredInstances.hasOwnProperty(ptr)) { + throwBindingError(`Tried to register registered instance: ${ptr}`); + } else { + registeredInstances[ptr] = instance; + } + } + + var registeredTypes = { + }; + + + + function getTypeName(type) { + var ptr = ___getTypeName(type); + var rv = readLatin1String(ptr); + _free(ptr); + return rv; + } + + function requireRegisteredType(rawType, humanName) { + var impl = registeredTypes[rawType]; + if (undefined === impl) { + throwBindingError(humanName + " has unknown type " + getTypeName(rawType)); + } + return impl; + } + + + + + function unregisterInheritedInstance(class_, ptr) { + ptr = getBasestPointer(class_, ptr); + if (registeredInstances.hasOwnProperty(ptr)) { + delete registeredInstances[ptr]; + } else { + throwBindingError(`Tried to unregister unregistered instance: ${ptr}`); + } + } + + function detachFinalizer(handle) {} + + var finalizationRegistry = false; + + + function runDestructor($$) { + if ($$.smartPtr) { + $$.smartPtrType.rawDestructor($$.smartPtr); + } else { + $$.ptrType.registeredClass.rawDestructor($$.ptr); + } + } + function releaseClassHandle($$) { + $$.count.value -= 1; + var toDelete = 0 === $$.count.value; + if (toDelete) { + runDestructor($$); + } + } + + function downcastPointer(ptr, ptrClass, desiredClass) { + if (ptrClass === desiredClass) { + return ptr; + } + if (undefined === desiredClass.baseClass) { + return null; // no conversion + } + + var rv = downcastPointer(ptr, ptrClass, desiredClass.baseClass); + if (rv === null) { + return null; + } + return desiredClass.downcast(rv); + } + + var registeredPointers = { + }; + + + function getInheritedInstance(class_, ptr) { + ptr = getBasestPointer(class_, ptr); + return registeredInstances[ptr]; + } + + var InternalError = undefined; + function throwInternalError(message) { + throw new InternalError(message); + } + + function makeClassHandle(prototype, record) { + if (!record.ptrType || !record.ptr) { + throwInternalError('makeClassHandle requires ptr and ptrType'); + } + var hasSmartPtrType = !!record.smartPtrType; + var hasSmartPtr = !!record.smartPtr; + if (hasSmartPtrType !== hasSmartPtr) { + throwInternalError('Both smartPtrType and smartPtr must be specified'); + } + record.count = { value: 1 }; + return attachFinalizer(Object.create(prototype, { + $$: { + value: record, + }, + })); + } + function RegisteredPointer_fromWireType(ptr) { + // ptr is a raw pointer (or a raw smartpointer) + + // rawPointer is a maybe-null raw pointer + var rawPointer = this.getPointee(ptr); + if (!rawPointer) { + this.destructor(ptr); + return null; + } + + var registeredInstance = getInheritedInstance(this.registeredClass, rawPointer); + if (undefined !== registeredInstance) { + // JS object has been neutered, time to repopulate it + if (0 === registeredInstance.$$.count.value) { + registeredInstance.$$.ptr = rawPointer; + registeredInstance.$$.smartPtr = ptr; + return registeredInstance['clone'](); + } else { + // else, just increment reference count on existing object + // it already has a reference to the smart pointer + var rv = registeredInstance['clone'](); + this.destructor(ptr); + return rv; + } + } + + function makeDefaultHandle() { + if (this.isSmartPointer) { + return makeClassHandle(this.registeredClass.instancePrototype, { + ptrType: this.pointeeType, + ptr: rawPointer, + smartPtrType: this, + smartPtr: ptr, + }); + } else { + return makeClassHandle(this.registeredClass.instancePrototype, { + ptrType: this, + ptr, + }); + } + } + + var actualType = this.registeredClass.getActualType(rawPointer); + var registeredPointerRecord = registeredPointers[actualType]; + if (!registeredPointerRecord) { + return makeDefaultHandle.call(this); + } + + var toType; + if (this.isConst) { + toType = registeredPointerRecord.constPointerType; + } else { + toType = registeredPointerRecord.pointerType; + } + var dp = downcastPointer( + rawPointer, + this.registeredClass, + toType.registeredClass); + if (dp === null) { + return makeDefaultHandle.call(this); + } + if (this.isSmartPointer) { + return makeClassHandle(toType.registeredClass.instancePrototype, { + ptrType: toType, + ptr: dp, + smartPtrType: this, + smartPtr: ptr, + }); + } else { + return makeClassHandle(toType.registeredClass.instancePrototype, { + ptrType: toType, + ptr: dp, + }); + } + } + var attachFinalizer = function(handle) { + if ('undefined' === typeof FinalizationRegistry) { + attachFinalizer = (handle) => handle; + return handle; + } + // If the running environment has a FinalizationRegistry (see + // https://github.com/tc39/proposal-weakrefs), then attach finalizers + // for class handles. We check for the presence of FinalizationRegistry + // at run-time, not build-time. + finalizationRegistry = new FinalizationRegistry((info) => { + console.warn(info.leakWarning.stack.replace(/^Error: /, '')); + releaseClassHandle(info.$$); + }); + attachFinalizer = (handle) => { + var $$ = handle.$$; + var hasSmartPtr = !!$$.smartPtr; + if (hasSmartPtr) { + // We should not call the destructor on raw pointers in case other code expects the pointee to live + var info = { $$: $$ }; + // Create a warning as an Error instance in advance so that we can store + // the current stacktrace and point to it when / if a leak is detected. + // This is more useful than the empty stacktrace of `FinalizationRegistry` + // callback. + var cls = $$.ptrType.registeredClass; + info.leakWarning = new Error(`Embind found a leaked C++ instance ${cls.name} <${ptrToString($$.ptr)}>.\n` + + "We'll free it automatically in this case, but this functionality is not reliable across various environments.\n" + + "Make sure to invoke .delete() manually once you're done with the instance instead.\n" + + "Originally allocated"); // `.stack` will add "at ..." after this sentence + if ('captureStackTrace' in Error) { + Error.captureStackTrace(info.leakWarning, RegisteredPointer_fromWireType); + } + finalizationRegistry.register(handle, info, handle); + } + return handle; + }; + detachFinalizer = (handle) => finalizationRegistry.unregister(handle); + return attachFinalizer(handle); + }; + function __embind_create_inheriting_constructor(constructorName, wrapperType, properties) { + constructorName = readLatin1String(constructorName); + wrapperType = requireRegisteredType(wrapperType, 'wrapper'); + properties = Emval.toValue(properties); + + var arraySlice = [].slice; + + var registeredClass = wrapperType.registeredClass; + var wrapperPrototype = registeredClass.instancePrototype; + var baseClass = registeredClass.baseClass; + var baseClassPrototype = baseClass.instancePrototype; + var baseConstructor = registeredClass.baseClass.constructor; + var ctor = createNamedFunction(constructorName, function() { + registeredClass.baseClass.pureVirtualFunctions.forEach(function(name) { + if (this[name] === baseClassPrototype[name]) { + throw new PureVirtualError(`Pure virtual function ${name} must be implemented in JavaScript`); + } + }.bind(this)); + + Object.defineProperty(this, '__parent', { + value: wrapperPrototype + }); + this["__construct"].apply(this, arraySlice.call(arguments)); + }); + + // It's a little nasty that we're modifying the wrapper prototype here. + + wrapperPrototype["__construct"] = function __construct() { + if (this === wrapperPrototype) { + throwBindingError("Pass correct 'this' to __construct"); + } + + var inner = baseConstructor["implement"].apply( + undefined, + [this].concat(arraySlice.call(arguments))); + detachFinalizer(inner); + var $$ = inner.$$; + inner["notifyOnDestruction"](); + $$.preservePointerOnDelete = true; + Object.defineProperties(this, { $$: { + value: $$ + }}); + attachFinalizer(this); + registerInheritedInstance(registeredClass, $$.ptr, this); + }; + + wrapperPrototype["__destruct"] = function __destruct() { + if (this === wrapperPrototype) { + throwBindingError("Pass correct 'this' to __destruct"); + } + + detachFinalizer(this); + unregisterInheritedInstance(registeredClass, this.$$.ptr); + }; + + ctor.prototype = Object.create(wrapperPrototype); + for (var p in properties) { + ctor.prototype[p] = properties[p]; + } + return Emval.toHandle(ctor); + } + + var tupleRegistrations = { + }; + + function runDestructors(destructors) { + while (destructors.length) { + var ptr = destructors.pop(); + var del = destructors.pop(); + del(ptr); + } + } + + function simpleReadValueFromPointer(pointer) { + return this['fromWireType'](HEAP32[((pointer)>>2)]); + } + + var awaitingDependencies = { + }; + + + var typeDependencies = { + }; + + function whenDependentTypesAreResolved(myTypes, dependentTypes, getTypeConverters) { + myTypes.forEach(function(type) { + typeDependencies[type] = dependentTypes; + }); + + function onComplete(typeConverters) { + var myTypeConverters = getTypeConverters(typeConverters); + if (myTypeConverters.length !== myTypes.length) { + throwInternalError('Mismatched type converter count'); + } + for (var i = 0; i < myTypes.length; ++i) { + registerType(myTypes[i], myTypeConverters[i]); + } + } + + var typeConverters = new Array(dependentTypes.length); + var unregisteredTypes = []; + var registered = 0; + dependentTypes.forEach((dt, i) => { + if (registeredTypes.hasOwnProperty(dt)) { + typeConverters[i] = registeredTypes[dt]; + } else { + unregisteredTypes.push(dt); + if (!awaitingDependencies.hasOwnProperty(dt)) { + awaitingDependencies[dt] = []; + } + awaitingDependencies[dt].push(() => { + typeConverters[i] = registeredTypes[dt]; + ++registered; + if (registered === unregisteredTypes.length) { + onComplete(typeConverters); + } + }); + } + }); + if (0 === unregisteredTypes.length) { + onComplete(typeConverters); + } + } + function __embind_finalize_value_array(rawTupleType) { + var reg = tupleRegistrations[rawTupleType]; + delete tupleRegistrations[rawTupleType]; + var elements = reg.elements; + var elementsLength = elements.length; + var elementTypes = elements.map(function(elt) { return elt.getterReturnType; }). + concat(elements.map(function(elt) { return elt.setterArgumentType; })); + + var rawConstructor = reg.rawConstructor; + var rawDestructor = reg.rawDestructor; + + whenDependentTypesAreResolved([rawTupleType], elementTypes, function(elementTypes) { + elements.forEach((elt, i) => { + var getterReturnType = elementTypes[i]; + var getter = elt.getter; + var getterContext = elt.getterContext; + var setterArgumentType = elementTypes[i + elementsLength]; + var setter = elt.setter; + var setterContext = elt.setterContext; + elt.read = (ptr) => { + return getterReturnType['fromWireType'](getter(getterContext, ptr)); + }; + elt.write = (ptr, o) => { + var destructors = []; + setter(setterContext, ptr, setterArgumentType['toWireType'](destructors, o)); + runDestructors(destructors); + }; + }); + + return [{ + name: reg.name, + 'fromWireType': function(ptr) { + var rv = new Array(elementsLength); + for (var i = 0; i < elementsLength; ++i) { + rv[i] = elements[i].read(ptr); + } + rawDestructor(ptr); + return rv; + }, + 'toWireType': function(destructors, o) { + if (elementsLength !== o.length) { + throw new TypeError(`Incorrect number of tuple elements for ${reg.name}: expected=${elementsLength}, actual=${o.length}`); + } + var ptr = rawConstructor(); + for (var i = 0; i < elementsLength; ++i) { + elements[i].write(ptr, o[i]); + } + if (destructors !== null) { + destructors.push(rawDestructor, ptr); + } + return ptr; + }, + 'argPackAdvance': 8, + 'readValueFromPointer': simpleReadValueFromPointer, + destructorFunction: rawDestructor, + }]; + }); + } + + var structRegistrations = { + }; + + + + var __embind_finalize_value_object = function(structType) { + var reg = structRegistrations[structType]; + delete structRegistrations[structType]; + + var rawConstructor = reg.rawConstructor; + var rawDestructor = reg.rawDestructor; + var fieldRecords = reg.fields; + var fieldTypes = fieldRecords.map((field) => field.getterReturnType). + concat(fieldRecords.map((field) => field.setterArgumentType)); + whenDependentTypesAreResolved([structType], fieldTypes, (fieldTypes) => { + var fields = {}; + fieldRecords.forEach((field, i) => { + var fieldName = field.fieldName; + var getterReturnType = fieldTypes[i]; + var getter = field.getter; + var getterContext = field.getterContext; + var setterArgumentType = fieldTypes[i + fieldRecords.length]; + var setter = field.setter; + var setterContext = field.setterContext; + fields[fieldName] = { + read: (ptr) => { + return getterReturnType['fromWireType']( + getter(getterContext, ptr)); + }, + write: (ptr, o) => { + var destructors = []; + setter(setterContext, ptr, setterArgumentType['toWireType'](destructors, o)); + runDestructors(destructors); + } + }; + }); + + return [{ + name: reg.name, + 'fromWireType': function(ptr) { + var rv = {}; + for (var i in fields) { + rv[i] = fields[i].read(ptr); + } + rawDestructor(ptr); + return rv; + }, + 'toWireType': function(destructors, o) { + // todo: Here we have an opportunity for -O3 level "unsafe" optimizations: + // assume all fields are present without checking. + for (var fieldName in fields) { + if (!(fieldName in o)) { + throw new TypeError(`Missing field: "${fieldName}"`); + } + } + var ptr = rawConstructor(); + for (fieldName in fields) { + fields[fieldName].write(ptr, o[fieldName]); + } + if (destructors !== null) { + destructors.push(rawDestructor, ptr); + } + return ptr; + }, + 'argPackAdvance': 8, + 'readValueFromPointer': simpleReadValueFromPointer, + destructorFunction: rawDestructor, + }]; + }); + }; + + function __embind_register_bigint(primitiveType, name, size, minRange, maxRange) {} + + function getShiftFromSize(size) { + switch (size) { + case 1: return 0; + case 2: return 1; + case 4: return 2; + case 8: return 3; + default: + throw new TypeError(`Unknown type size: ${size}`); + } + } + + + + + + + /** @param {Object=} options */ + function sharedRegisterType(rawType, registeredInstance, options = {}) { + var name = registeredInstance.name; + if (!rawType) { + throwBindingError(`type "${name}" must have a positive integer typeid pointer`); + } + if (registeredTypes.hasOwnProperty(rawType)) { + if (options.ignoreDuplicateRegistrations) { + return; + } else { + throwBindingError(`Cannot register type '${name}' twice`); + } + } + + registeredTypes[rawType] = registeredInstance; + delete typeDependencies[rawType]; + + if (awaitingDependencies.hasOwnProperty(rawType)) { + var callbacks = awaitingDependencies[rawType]; + delete awaitingDependencies[rawType]; + callbacks.forEach((cb) => cb()); + } + } + /** @param {Object=} options */ + function registerType(rawType, registeredInstance, options = {}) { + if (!('argPackAdvance' in registeredInstance)) { + throw new TypeError('registerType registeredInstance requires argPackAdvance'); + } + return sharedRegisterType(rawType, registeredInstance, options); + } + function __embind_register_bool(rawType, name, size, trueValue, falseValue) { + var shift = getShiftFromSize(size); + + name = readLatin1String(name); + registerType(rawType, { + name, + 'fromWireType': function(wt) { + // ambiguous emscripten ABI: sometimes return values are + // true or false, and sometimes integers (0 or 1) + return !!wt; + }, + 'toWireType': function(destructors, o) { + return o ? trueValue : falseValue; + }, + 'argPackAdvance': 8, + 'readValueFromPointer': function(pointer) { + // TODO: if heap is fixed (like in asm.js) this could be executed outside + var heap; + if (size === 1) { + heap = HEAP8; + } else if (size === 2) { + heap = HEAP16; + } else if (size === 4) { + heap = HEAP32; + } else { + throw new TypeError("Unknown boolean type size: " + name); + } + return this['fromWireType'](heap[pointer >> shift]); + }, + destructorFunction: null, // This type does not need a destructor + }); + } + + + function ClassHandle_isAliasOf(other) { + if (!(this instanceof ClassHandle)) { + return false; + } + if (!(other instanceof ClassHandle)) { + return false; + } + + var leftClass = this.$$.ptrType.registeredClass; + var left = this.$$.ptr; + var rightClass = other.$$.ptrType.registeredClass; + var right = other.$$.ptr; + + while (leftClass.baseClass) { + left = leftClass.upcast(left); + leftClass = leftClass.baseClass; + } + + while (rightClass.baseClass) { + right = rightClass.upcast(right); + rightClass = rightClass.baseClass; + } + + return leftClass === rightClass && left === right; + } + + function shallowCopyInternalPointer(o) { + return { + count: o.count, + deleteScheduled: o.deleteScheduled, + preservePointerOnDelete: o.preservePointerOnDelete, + ptr: o.ptr, + ptrType: o.ptrType, + smartPtr: o.smartPtr, + smartPtrType: o.smartPtrType, + }; + } + + function throwInstanceAlreadyDeleted(obj) { + function getInstanceTypeName(handle) { + return handle.$$.ptrType.registeredClass.name; + } + throwBindingError(getInstanceTypeName(obj) + ' instance already deleted'); + } + + function ClassHandle_clone() { + if (!this.$$.ptr) { + throwInstanceAlreadyDeleted(this); + } + + if (this.$$.preservePointerOnDelete) { + this.$$.count.value += 1; + return this; + } else { + var clone = attachFinalizer(Object.create(Object.getPrototypeOf(this), { + $$: { + value: shallowCopyInternalPointer(this.$$), + } + })); + + clone.$$.count.value += 1; + clone.$$.deleteScheduled = false; + return clone; + } + } + + + + + function ClassHandle_delete() { + if (!this.$$.ptr) { + throwInstanceAlreadyDeleted(this); + } + + if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) { + throwBindingError('Object already scheduled for deletion'); + } + + detachFinalizer(this); + releaseClassHandle(this.$$); + + if (!this.$$.preservePointerOnDelete) { + this.$$.smartPtr = undefined; + this.$$.ptr = undefined; + } + } + + function ClassHandle_isDeleted() { + return !this.$$.ptr; + } + + + + function ClassHandle_deleteLater() { + if (!this.$$.ptr) { + throwInstanceAlreadyDeleted(this); + } + if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) { + throwBindingError('Object already scheduled for deletion'); + } + deletionQueue.push(this); + if (deletionQueue.length === 1 && delayFunction) { + delayFunction(flushPendingDeletes); + } + this.$$.deleteScheduled = true; + return this; + } + function init_ClassHandle() { + ClassHandle.prototype['isAliasOf'] = ClassHandle_isAliasOf; + ClassHandle.prototype['clone'] = ClassHandle_clone; + ClassHandle.prototype['delete'] = ClassHandle_delete; + ClassHandle.prototype['isDeleted'] = ClassHandle_isDeleted; + ClassHandle.prototype['deleteLater'] = ClassHandle_deleteLater; + } + function ClassHandle() { + } + + + + function ensureOverloadTable(proto, methodName, humanName) { + if (undefined === proto[methodName].overloadTable) { + var prevFunc = proto[methodName]; + // Inject an overload resolver function that routes to the appropriate overload based on the number of arguments. + proto[methodName] = function() { + // TODO This check can be removed in -O3 level "unsafe" optimizations. + if (!proto[methodName].overloadTable.hasOwnProperty(arguments.length)) { + throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${arguments.length}) - expects one of (${proto[methodName].overloadTable})!`); + } + return proto[methodName].overloadTable[arguments.length].apply(this, arguments); + }; + // Move the previous function into the overload table. + proto[methodName].overloadTable = []; + proto[methodName].overloadTable[prevFunc.argCount] = prevFunc; + } + } + + /** @param {number=} numArguments */ + function exposePublicSymbol(name, value, numArguments) { + if (Module.hasOwnProperty(name)) { + if (undefined === numArguments || (undefined !== Module[name].overloadTable && undefined !== Module[name].overloadTable[numArguments])) { + throwBindingError(`Cannot register public name '${name}' twice`); + } + + // We are exposing a function with the same name as an existing function. Create an overload table and a function selector + // that routes between the two. + ensureOverloadTable(Module, name, name); + if (Module.hasOwnProperty(numArguments)) { + throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`); + } + // Add the new function into the overload table. + Module[name].overloadTable[numArguments] = value; + } + else { + Module[name] = value; + if (undefined !== numArguments) { + Module[name].numArguments = numArguments; + } + } + } + + + + /** @constructor */ + function RegisteredClass(name, + constructor, + instancePrototype, + rawDestructor, + baseClass, + getActualType, + upcast, + downcast) { + this.name = name; + this.constructor = constructor; + this.instancePrototype = instancePrototype; + this.rawDestructor = rawDestructor; + this.baseClass = baseClass; + this.getActualType = getActualType; + this.upcast = upcast; + this.downcast = downcast; + this.pureVirtualFunctions = []; + } + + + function upcastPointer(ptr, ptrClass, desiredClass) { + while (ptrClass !== desiredClass) { + if (!ptrClass.upcast) { + throwBindingError(`Expected null or instance of ${desiredClass.name}, got an instance of ${ptrClass.name}`); + } + ptr = ptrClass.upcast(ptr); + ptrClass = ptrClass.baseClass; + } + return ptr; + } + function constNoSmartPtrRawPointerToWireType(destructors, handle) { + if (handle === null) { + if (this.isReference) { + throwBindingError(`null is not a valid ${this.name}`); + } + return 0; + } + + if (!handle.$$) { + throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`); + } + if (!handle.$$.ptr) { + throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`); + } + var handleClass = handle.$$.ptrType.registeredClass; + var ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass); + return ptr; + } + + + function genericPointerToWireType(destructors, handle) { + var ptr; + if (handle === null) { + if (this.isReference) { + throwBindingError(`null is not a valid ${this.name}`); + } + + if (this.isSmartPointer) { + ptr = this.rawConstructor(); + if (destructors !== null) { + destructors.push(this.rawDestructor, ptr); + } + return ptr; + } else { + return 0; + } + } + + if (!handle.$$) { + throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`); + } + if (!handle.$$.ptr) { + throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`); + } + if (!this.isConst && handle.$$.ptrType.isConst) { + throwBindingError(`Cannot convert argument of type ${(handle.$$.smartPtrType ? handle.$$.smartPtrType.name : handle.$$.ptrType.name)} to parameter type ${this.name}`); + } + var handleClass = handle.$$.ptrType.registeredClass; + ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass); + + if (this.isSmartPointer) { + // TODO: this is not strictly true + // We could support BY_EMVAL conversions from raw pointers to smart pointers + // because the smart pointer can hold a reference to the handle + if (undefined === handle.$$.smartPtr) { + throwBindingError('Passing raw pointer to smart pointer is illegal'); + } + + switch (this.sharingPolicy) { + case 0: // NONE + // no upcasting + if (handle.$$.smartPtrType === this) { + ptr = handle.$$.smartPtr; + } else { + throwBindingError(`Cannot convert argument of type ${(handle.$$.smartPtrType ? handle.$$.smartPtrType.name : handle.$$.ptrType.name)} to parameter type ${this.name}`); + } + break; + + case 1: // INTRUSIVE + ptr = handle.$$.smartPtr; + break; + + case 2: // BY_EMVAL + if (handle.$$.smartPtrType === this) { + ptr = handle.$$.smartPtr; + } else { + var clonedHandle = handle['clone'](); + ptr = this.rawShare( + ptr, + Emval.toHandle(function() { + clonedHandle['delete'](); + }) + ); + if (destructors !== null) { + destructors.push(this.rawDestructor, ptr); + } + } + break; + + default: + throwBindingError('Unsupporting sharing policy'); + } + } + return ptr; + } + + + function nonConstNoSmartPtrRawPointerToWireType(destructors, handle) { + if (handle === null) { + if (this.isReference) { + throwBindingError(`null is not a valid ${this.name}`); + } + return 0; + } + + if (!handle.$$) { + throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`); + } + if (!handle.$$.ptr) { + throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`); + } + if (handle.$$.ptrType.isConst) { + throwBindingError(`Cannot convert argument of type ${handle.$$.ptrType.name} to parameter type ${this.name}`); + } + var handleClass = handle.$$.ptrType.registeredClass; + var ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass); + return ptr; + } + + + function RegisteredPointer_getPointee(ptr) { + if (this.rawGetPointee) { + ptr = this.rawGetPointee(ptr); + } + return ptr; + } + + function RegisteredPointer_destructor(ptr) { + if (this.rawDestructor) { + this.rawDestructor(ptr); + } + } + + function RegisteredPointer_deleteObject(handle) { + if (handle !== null) { + handle['delete'](); + } + } + + function init_RegisteredPointer() { + RegisteredPointer.prototype.getPointee = RegisteredPointer_getPointee; + RegisteredPointer.prototype.destructor = RegisteredPointer_destructor; + RegisteredPointer.prototype['argPackAdvance'] = 8; + RegisteredPointer.prototype['readValueFromPointer'] = simpleReadValueFromPointer; + RegisteredPointer.prototype['deleteObject'] = RegisteredPointer_deleteObject; + RegisteredPointer.prototype['fromWireType'] = RegisteredPointer_fromWireType; + } + /** @constructor + @param {*=} pointeeType, + @param {*=} sharingPolicy, + @param {*=} rawGetPointee, + @param {*=} rawConstructor, + @param {*=} rawShare, + @param {*=} rawDestructor, + */ + function RegisteredPointer( + name, + registeredClass, + isReference, + isConst, + + // smart pointer properties + isSmartPointer, + pointeeType, + sharingPolicy, + rawGetPointee, + rawConstructor, + rawShare, + rawDestructor + ) { + this.name = name; + this.registeredClass = registeredClass; + this.isReference = isReference; + this.isConst = isConst; + + // smart pointer properties + this.isSmartPointer = isSmartPointer; + this.pointeeType = pointeeType; + this.sharingPolicy = sharingPolicy; + this.rawGetPointee = rawGetPointee; + this.rawConstructor = rawConstructor; + this.rawShare = rawShare; + this.rawDestructor = rawDestructor; + + if (!isSmartPointer && registeredClass.baseClass === undefined) { + if (isConst) { + this['toWireType'] = constNoSmartPtrRawPointerToWireType; + this.destructorFunction = null; + } else { + this['toWireType'] = nonConstNoSmartPtrRawPointerToWireType; + this.destructorFunction = null; + } + } else { + this['toWireType'] = genericPointerToWireType; + // Here we must leave this.destructorFunction undefined, since whether genericPointerToWireType returns + // a pointer that needs to be freed up is runtime-dependent, and cannot be evaluated at registration time. + // TODO: Create an alternative mechanism that allows removing the use of var destructors = []; array in + // craftInvokerFunction altogether. + } + } + + /** @param {number=} numArguments */ + function replacePublicSymbol(name, value, numArguments) { + if (!Module.hasOwnProperty(name)) { + throwInternalError('Replacing nonexistant public symbol'); + } + // If there's an overload table for this symbol, replace the symbol in the overload table instead. + if (undefined !== Module[name].overloadTable && undefined !== numArguments) { + Module[name].overloadTable[numArguments] = value; + } + else { + Module[name] = value; + Module[name].argCount = numArguments; + } + } + + + + var dynCallLegacy = (sig, ptr, args) => { + assert(('dynCall_' + sig) in Module, `bad function pointer type - dynCall function not found for sig '${sig}'`); + if (args && args.length) { + // j (64-bit integer) must be passed in as two numbers [low 32, high 32]. + assert(args.length === sig.substring(1).replace(/j/g, '--').length); + } else { + assert(sig.length == 1); + } + var f = Module['dynCall_' + sig]; + return args && args.length ? f.apply(null, [ptr].concat(args)) : f.call(null, ptr); + }; + + var wasmTableMirror = []; + var getWasmTableEntry = (funcPtr) => { + var func = wasmTableMirror[funcPtr]; + if (!func) { + if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1; + wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr); + } + assert(wasmTable.get(funcPtr) == func, "JavaScript-side Wasm function table mirror is out of date!"); + return func; + }; + + /** @param {Object=} args */ + var dynCall = (sig, ptr, args) => { + // Without WASM_BIGINT support we cannot directly call function with i64 as + // part of thier signature, so we rely the dynCall functions generated by + // wasm-emscripten-finalize + if (sig.includes('j')) { + return dynCallLegacy(sig, ptr, args); + } + assert(getWasmTableEntry(ptr), `missing table entry in dynCall: ${ptr}`); + var rtn = getWasmTableEntry(ptr).apply(null, args); + return rtn; + + }; + var getDynCaller = (sig, ptr) => { + assert(sig.includes('j') || sig.includes('p'), 'getDynCaller should only be called with i64 sigs') + var argCache = []; + return function() { + argCache.length = 0; + Object.assign(argCache, arguments); + return dynCall(sig, ptr, argCache); + }; + }; + + + function embind__requireFunction(signature, rawFunction) { + signature = readLatin1String(signature); + + function makeDynCaller() { + if (signature.includes('j')) { + return getDynCaller(signature, rawFunction); + } + return getWasmTableEntry(rawFunction); + } + + var fp = makeDynCaller(); + if (typeof fp != "function") { + throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`); + } + return fp; + } + + + + var UnboundTypeError = undefined; + + function throwUnboundTypeError(message, types) { + var unboundTypes = []; + var seen = {}; + function visit(type) { + if (seen[type]) { + return; + } + if (registeredTypes[type]) { + return; + } + if (typeDependencies[type]) { + typeDependencies[type].forEach(visit); + return; + } + unboundTypes.push(type); + seen[type] = true; + } + types.forEach(visit); + + throw new UnboundTypeError(`${message}: ` + unboundTypes.map(getTypeName).join([', '])); + } + + function __embind_register_class(rawType, + rawPointerType, + rawConstPointerType, + baseClassRawType, + getActualTypeSignature, + getActualType, + upcastSignature, + upcast, + downcastSignature, + downcast, + name, + destructorSignature, + rawDestructor) { + name = readLatin1String(name); + getActualType = embind__requireFunction(getActualTypeSignature, getActualType); + if (upcast) { + upcast = embind__requireFunction(upcastSignature, upcast); + } + if (downcast) { + downcast = embind__requireFunction(downcastSignature, downcast); + } + rawDestructor = embind__requireFunction(destructorSignature, rawDestructor); + var legalFunctionName = makeLegalFunctionName(name); + + exposePublicSymbol(legalFunctionName, function() { + // this code cannot run if baseClassRawType is zero + throwUnboundTypeError(`Cannot construct ${name} due to unbound types`, [baseClassRawType]); + }); + + whenDependentTypesAreResolved( + [rawType, rawPointerType, rawConstPointerType], + baseClassRawType ? [baseClassRawType] : [], + function(base) { + base = base[0]; + + var baseClass; + var basePrototype; + if (baseClassRawType) { + baseClass = base.registeredClass; + basePrototype = baseClass.instancePrototype; + } else { + basePrototype = ClassHandle.prototype; + } + + var constructor = createNamedFunction(legalFunctionName, function() { + if (Object.getPrototypeOf(this) !== instancePrototype) { + throw new BindingError("Use 'new' to construct " + name); + } + if (undefined === registeredClass.constructor_body) { + throw new BindingError(name + " has no accessible constructor"); + } + var body = registeredClass.constructor_body[arguments.length]; + if (undefined === body) { + throw new BindingError(`Tried to invoke ctor of ${name} with invalid number of parameters (${arguments.length}) - expected (${Object.keys(registeredClass.constructor_body).toString()}) parameters instead!`); + } + return body.apply(this, arguments); + }); + + var instancePrototype = Object.create(basePrototype, { + constructor: { value: constructor }, + }); + + constructor.prototype = instancePrototype; + + var registeredClass = new RegisteredClass(name, + constructor, + instancePrototype, + rawDestructor, + baseClass, + getActualType, + upcast, + downcast); + + if (registeredClass.baseClass) { + // Keep track of class hierarchy. Used to allow sub-classes to inherit class functions. + if (registeredClass.baseClass.__derivedClasses === undefined) { + registeredClass.baseClass.__derivedClasses = []; + } + + registeredClass.baseClass.__derivedClasses.push(registeredClass); + } + + var referenceConverter = new RegisteredPointer(name, + registeredClass, + true, + false, + false); + + var pointerConverter = new RegisteredPointer(name + '*', + registeredClass, + false, + false, + false); + + var constPointerConverter = new RegisteredPointer(name + ' const*', + registeredClass, + false, + true, + false); + + registeredPointers[rawType] = { + pointerType: pointerConverter, + constPointerType: constPointerConverter + }; + + replacePublicSymbol(legalFunctionName, constructor); + + return [referenceConverter, pointerConverter, constPointerConverter]; + } + ); + } + + + + + function newFunc(constructor, argumentList) { + if (!(constructor instanceof Function)) { + throw new TypeError(`new_ called with constructor type ${typeof(constructor)} which is not a function`); + } + /* + * Previously, the following line was just: + * function dummy() {}; + * Unfortunately, Chrome was preserving 'dummy' as the object's name, even + * though at creation, the 'dummy' has the correct constructor name. Thus, + * objects created with IMVU.new would show up in the debugger as 'dummy', + * which isn't very helpful. Using IMVU.createNamedFunction addresses the + * issue. Doublely-unfortunately, there's no way to write a test for this + * behavior. -NRD 2013.02.22 + */ + var dummy = createNamedFunction(constructor.name || 'unknownFunctionName', function(){}); + dummy.prototype = constructor.prototype; + var obj = new dummy; + + var r = constructor.apply(obj, argumentList); + return (r instanceof Object) ? r : obj; + } + function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cppTargetFunc, /** boolean= */ isAsync) { + // humanName: a human-readable string name for the function to be generated. + // argTypes: An array that contains the embind type objects for all types in the function signature. + // argTypes[0] is the type object for the function return value. + // argTypes[1] is the type object for function this object/class type, or null if not crafting an invoker for a class method. + // argTypes[2...] are the actual function parameters. + // classType: The embind type object for the class to be bound, or null if this is not a method of a class. + // cppInvokerFunc: JS Function object to the C++-side function that interops into C++ code. + // cppTargetFunc: Function pointer (an integer to FUNCTION_TABLE) to the target C++ function the cppInvokerFunc will end up calling. + // isAsync: Optional. If true, returns an async function. Async bindings are only supported with JSPI. + var argCount = argTypes.length; + + if (argCount < 2) { + throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!"); + } + + assert(!isAsync, 'Async bindings are only supported with JSPI.'); + + var isClassMethodFunc = (argTypes[1] !== null && classType !== null); + + // Free functions with signature "void function()" do not need an invoker that marshalls between wire types. + // TODO: This omits argument count check - enable only at -O3 or similar. + // if (ENABLE_UNSAFE_OPTS && argCount == 2 && argTypes[0].name == "void" && !isClassMethodFunc) { + // return FUNCTION_TABLE[fn]; + // } + + // Determine if we need to use a dynamic stack to store the destructors for the function parameters. + // TODO: Remove this completely once all function invokers are being dynamically generated. + var needsDestructorStack = false; + + for (var i = 1; i < argTypes.length; ++i) { // Skip return value at index 0 - it's not deleted here. + if (argTypes[i] !== null && argTypes[i].destructorFunction === undefined) { // The type does not define a destructor function - must use dynamic stack + needsDestructorStack = true; + break; + } + } + + var returns = (argTypes[0].name !== "void"); + + var argsList = ""; + var argsListWired = ""; + for (var i = 0; i < argCount - 2; ++i) { + argsList += (i!==0?", ":"")+"arg"+i; + argsListWired += (i!==0?", ":"")+"arg"+i+"Wired"; + } + + var invokerFnBody = ` + return function ${makeLegalFunctionName(humanName)}(${argsList}) { + if (arguments.length !== ${argCount - 2}) { + throwBindingError('function ${humanName} called with ${arguments.length} arguments, expected ${argCount - 2} args!'); + }`; + + if (needsDestructorStack) { + invokerFnBody += "var destructors = [];\n"; + } + + var dtorStack = needsDestructorStack ? "destructors" : "null"; + var args1 = ["throwBindingError", "invoker", "fn", "runDestructors", "retType", "classParam"]; + var args2 = [throwBindingError, cppInvokerFunc, cppTargetFunc, runDestructors, argTypes[0], argTypes[1]]; + + if (isClassMethodFunc) { + invokerFnBody += "var thisWired = classParam.toWireType("+dtorStack+", this);\n"; + } + + for (var i = 0; i < argCount - 2; ++i) { + invokerFnBody += "var arg"+i+"Wired = argType"+i+".toWireType("+dtorStack+", arg"+i+"); // "+argTypes[i+2].name+"\n"; + args1.push("argType"+i); + args2.push(argTypes[i+2]); + } + + if (isClassMethodFunc) { + argsListWired = "thisWired" + (argsListWired.length > 0 ? ", " : "") + argsListWired; + } + + invokerFnBody += + (returns || isAsync ? "var rv = ":"") + "invoker(fn"+(argsListWired.length>0?", ":"")+argsListWired+");\n"; + + if (needsDestructorStack) { + invokerFnBody += "runDestructors(destructors);\n"; + } else { + for (var i = isClassMethodFunc?1:2; i < argTypes.length; ++i) { // Skip return value at index 0 - it's not deleted here. Also skip class type if not a method. + var paramName = (i === 1 ? "thisWired" : ("arg"+(i - 2)+"Wired")); + if (argTypes[i].destructorFunction !== null) { + invokerFnBody += paramName+"_dtor("+paramName+"); // "+argTypes[i].name+"\n"; + args1.push(paramName+"_dtor"); + args2.push(argTypes[i].destructorFunction); + } + } + } + + if (returns) { + invokerFnBody += "var ret = retType.fromWireType(rv);\n" + + "return ret;\n"; + } else { + } + + invokerFnBody += "}\n"; + + args1.push(invokerFnBody); + + return newFunc(Function, args1).apply(null, args2); + } + + + function heap32VectorToArray(count, firstElement) { + var array = []; + for (var i = 0; i < count; i++) { + // TODO(https://github.com/emscripten-core/emscripten/issues/17310): + // Find a way to hoist the `>> 2` or `>> 3` out of this loop. + array.push(HEAPU32[(((firstElement)+(i * 4))>>2)]); + } + return array; + } + + + + + function __embind_register_class_class_function(rawClassType, + methodName, + argCount, + rawArgTypesAddr, + invokerSignature, + rawInvoker, + fn, + isAsync) { + var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr); + methodName = readLatin1String(methodName); + rawInvoker = embind__requireFunction(invokerSignature, rawInvoker); + whenDependentTypesAreResolved([], [rawClassType], function(classType) { + classType = classType[0]; + var humanName = `${classType.name}.${methodName}`; + + function unboundTypesHandler() { + throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`, rawArgTypes); + } + + if (methodName.startsWith("@@")) { + methodName = Symbol[methodName.substring(2)]; + } + + var proto = classType.registeredClass.constructor; + if (undefined === proto[methodName]) { + // This is the first function to be registered with this name. + unboundTypesHandler.argCount = argCount-1; + proto[methodName] = unboundTypesHandler; + } else { + // There was an existing function with the same name registered. Set up + // a function overload routing table. + ensureOverloadTable(proto, methodName, humanName); + proto[methodName].overloadTable[argCount-1] = unboundTypesHandler; + } + + whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) { + // Replace the initial unbound-types-handler stub with the proper + // function. If multiple overloads are registered, the function handlers + // go into an overload table. + var invokerArgsArray = [argTypes[0] /* return value */, null /* no class 'this'*/].concat(argTypes.slice(1) /* actual params */); + var func = craftInvokerFunction(humanName, invokerArgsArray, null /* no class 'this'*/, rawInvoker, fn, isAsync); + if (undefined === proto[methodName].overloadTable) { + func.argCount = argCount-1; + proto[methodName] = func; + } else { + proto[methodName].overloadTable[argCount-1] = func; + } + + if (classType.registeredClass.__derivedClasses) { + for (const derivedClass of classType.registeredClass.__derivedClasses) { + if (!derivedClass.constructor.hasOwnProperty(methodName)) { + // TODO: Add support for overloads + derivedClass.constructor[methodName] = func; + } + } + } + + return []; + }); + return []; + }); + } + + + + + + + + + function validateThis(this_, classType, humanName) { + if (!(this_ instanceof Object)) { + throwBindingError(`${humanName} with invalid "this": ${this_}`); + } + if (!(this_ instanceof classType.registeredClass.constructor)) { + throwBindingError(`${humanName} incompatible with "this" of type ${this_.constructor.name}`); + } + if (!this_.$$.ptr) { + throwBindingError(`cannot call emscripten binding method ${humanName} on deleted object`); + } + + // todo: kill this + return upcastPointer(this_.$$.ptr, + this_.$$.ptrType.registeredClass, + classType.registeredClass); + } + function __embind_register_class_class_property(rawClassType, + fieldName, + rawFieldType, + rawFieldPtr, + getterSignature, + getter, + setterSignature, + setter) { + fieldName = readLatin1String(fieldName); + getter = embind__requireFunction(getterSignature, getter); + + whenDependentTypesAreResolved([], [rawClassType], function(classType) { + classType = classType[0]; + var humanName = `${classType.name}.${fieldName}`; + var desc = { + get() { + throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`, [rawFieldType]); + }, + enumerable: true, + configurable: true + }; + if (setter) { + desc.set = () => { + throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`, [rawFieldType]); + }; + } else { + desc.set = (v) => { + throwBindingError(`${humanName} is a read-only property`); + }; + } + + Object.defineProperty(classType.registeredClass.constructor, fieldName, desc); + + whenDependentTypesAreResolved([], [rawFieldType], function(fieldType) { + fieldType = fieldType[0]; + var desc = { + get() { + return fieldType['fromWireType'](getter(rawFieldPtr)); + }, + enumerable: true + }; + + if (setter) { + setter = embind__requireFunction(setterSignature, setter); + desc.set = (v) => { + var destructors = []; + setter(rawFieldPtr, fieldType['toWireType'](destructors, v)); + runDestructors(destructors); + }; + } + + Object.defineProperty(classType.registeredClass.constructor, fieldName, desc); + return []; + }); + + return []; + }); + } + + + + + + + + function __embind_register_class_constructor( + rawClassType, + argCount, + rawArgTypesAddr, + invokerSignature, + invoker, + rawConstructor + ) { + assert(argCount > 0); + var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr); + invoker = embind__requireFunction(invokerSignature, invoker); + var args = [rawConstructor]; + var destructors = []; + + whenDependentTypesAreResolved([], [rawClassType], function(classType) { + classType = classType[0]; + var humanName = `constructor ${classType.name}`; + + if (undefined === classType.registeredClass.constructor_body) { + classType.registeredClass.constructor_body = []; + } + if (undefined !== classType.registeredClass.constructor_body[argCount - 1]) { + throw new BindingError(`Cannot register multiple constructors with identical number of parameters (${argCount-1}) for class '${classType.name}'! Overload resolution is currently only performed using the parameter count, not actual type info!`); + } + classType.registeredClass.constructor_body[argCount - 1] = () => { + throwUnboundTypeError(`Cannot construct ${classType.name} due to unbound types`, rawArgTypes); + }; + + whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) { + // Insert empty slot for context type (argTypes[1]). + argTypes.splice(1, 0, null); + classType.registeredClass.constructor_body[argCount - 1] = craftInvokerFunction(humanName, argTypes, null, invoker, rawConstructor); + return []; + }); + return []; + }); + } + + + + + + + function __embind_register_class_function(rawClassType, + methodName, + argCount, + rawArgTypesAddr, // [ReturnType, ThisType, Args...] + invokerSignature, + rawInvoker, + context, + isPureVirtual, + isAsync) { + var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr); + methodName = readLatin1String(methodName); + rawInvoker = embind__requireFunction(invokerSignature, rawInvoker); + + whenDependentTypesAreResolved([], [rawClassType], function(classType) { + classType = classType[0]; + var humanName = `${classType.name}.${methodName}`; + + if (methodName.startsWith("@@")) { + methodName = Symbol[methodName.substring(2)]; + } + + if (isPureVirtual) { + classType.registeredClass.pureVirtualFunctions.push(methodName); + } + + function unboundTypesHandler() { + throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`, rawArgTypes); + } + + var proto = classType.registeredClass.instancePrototype; + var method = proto[methodName]; + if (undefined === method || (undefined === method.overloadTable && method.className !== classType.name && method.argCount === argCount - 2)) { + // This is the first overload to be registered, OR we are replacing a + // function in the base class with a function in the derived class. + unboundTypesHandler.argCount = argCount - 2; + unboundTypesHandler.className = classType.name; + proto[methodName] = unboundTypesHandler; + } else { + // There was an existing function with the same name registered. Set up + // a function overload routing table. + ensureOverloadTable(proto, methodName, humanName); + proto[methodName].overloadTable[argCount - 2] = unboundTypesHandler; + } + + whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) { + var memberFunction = craftInvokerFunction(humanName, argTypes, classType, rawInvoker, context, isAsync); + + // Replace the initial unbound-handler-stub function with the appropriate member function, now that all types + // are resolved. If multiple overloads are registered for this function, the function goes into an overload table. + if (undefined === proto[methodName].overloadTable) { + // Set argCount in case an overload is registered later + memberFunction.argCount = argCount - 2; + proto[methodName] = memberFunction; + } else { + proto[methodName].overloadTable[argCount - 2] = memberFunction; + } + + return []; + }); + return []; + }); + } + + + + + + + + function __embind_register_class_property(classType, + fieldName, + getterReturnType, + getterSignature, + getter, + getterContext, + setterArgumentType, + setterSignature, + setter, + setterContext) { + fieldName = readLatin1String(fieldName); + getter = embind__requireFunction(getterSignature, getter); + + whenDependentTypesAreResolved([], [classType], function(classType) { + classType = classType[0]; + var humanName = `${classType.name}.${fieldName}`; + var desc = { + get() { + throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`, [getterReturnType, setterArgumentType]); + }, + enumerable: true, + configurable: true + }; + if (setter) { + desc.set = () => { + throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`, [getterReturnType, setterArgumentType]); + }; + } else { + desc.set = (v) => { + throwBindingError(humanName + ' is a read-only property'); + }; + } + + Object.defineProperty(classType.registeredClass.instancePrototype, fieldName, desc); + + whenDependentTypesAreResolved( + [], + (setter ? [getterReturnType, setterArgumentType] : [getterReturnType]), + function(types) { + var getterReturnType = types[0]; + var desc = { + get() { + var ptr = validateThis(this, classType, humanName + ' getter'); + return getterReturnType['fromWireType'](getter(getterContext, ptr)); + }, + enumerable: true + }; + + if (setter) { + setter = embind__requireFunction(setterSignature, setter); + var setterArgumentType = types[1]; + desc.set = function(v) { + var ptr = validateThis(this, classType, humanName + ' setter'); + var destructors = []; + setter(setterContext, ptr, setterArgumentType['toWireType'](destructors, v)); + runDestructors(destructors); + }; + } + + Object.defineProperty(classType.registeredClass.instancePrototype, fieldName, desc); + return []; + }); + + return []; + }); + } + + + function __embind_register_constant(name, type, value) { + name = readLatin1String(name); + whenDependentTypesAreResolved([], [type], function(type) { + type = type[0]; + Module[name] = type['fromWireType'](value); + return []; + }); + } + + function __emval_decref(handle) { + if (handle >= emval_handles.reserved && 0 === --emval_handles.get(handle).refcount) { + emval_handles.free(handle); + } + } + + + + + function __embind_register_emval(rawType, name) { + name = readLatin1String(name); + registerType(rawType, { + name, + 'fromWireType': function(handle) { + var rv = Emval.toValue(handle); + __emval_decref(handle); + return rv; + }, + 'toWireType': function(destructors, value) { + return Emval.toHandle(value); + }, + 'argPackAdvance': 8, + 'readValueFromPointer': simpleReadValueFromPointer, + destructorFunction: null, // This type does not need a destructor + + // TODO: do we need a deleteObject here? write a test where + // emval is passed into JS via an interface + }); + } + + + + function enumReadValueFromPointer(name, shift, signed) { + switch (shift) { + case 0: return function(pointer) { + var heap = signed ? HEAP8 : HEAPU8; + return this['fromWireType'](heap[pointer]); + }; + case 1: return function(pointer) { + var heap = signed ? HEAP16 : HEAPU16; + return this['fromWireType'](heap[pointer >> 1]); + }; + case 2: return function(pointer) { + var heap = signed ? HEAP32 : HEAPU32; + return this['fromWireType'](heap[pointer >> 2]); + }; + default: + throw new TypeError("Unknown integer type: " + name); + } + } + + + function __embind_register_enum(rawType, name, size, isSigned) { + var shift = getShiftFromSize(size); + name = readLatin1String(name); + + function ctor() {} + ctor.values = {}; + + registerType(rawType, { + name, + constructor: ctor, + 'fromWireType': function(c) { + return this.constructor.values[c]; + }, + 'toWireType': function(destructors, c) { + return c.value; + }, + 'argPackAdvance': 8, + 'readValueFromPointer': enumReadValueFromPointer(name, shift, isSigned), + destructorFunction: null, + }); + exposePublicSymbol(name, ctor); + } + + + + function __embind_register_enum_value(rawEnumType, name, enumValue) { + var enumType = requireRegisteredType(rawEnumType, 'enum'); + name = readLatin1String(name); + + var Enum = enumType.constructor; + + var Value = Object.create(enumType.constructor.prototype, { + value: {value: enumValue}, + constructor: {value: createNamedFunction(`${enumType.name}_${name}`, function() {})}, + }); + Enum.values[enumValue] = Value; + Enum[name] = Value; + } + + function embindRepr(v) { + if (v === null) { + return 'null'; + } + var t = typeof v; + if (t === 'object' || t === 'array' || t === 'function') { + return v.toString(); + } else { + return '' + v; + } + } + + function floatReadValueFromPointer(name, shift) { + switch (shift) { + case 2: return function(pointer) { + return this['fromWireType'](HEAPF32[pointer >> 2]); + }; + case 3: return function(pointer) { + return this['fromWireType'](HEAPF64[pointer >> 3]); + }; + default: + throw new TypeError("Unknown float type: " + name); + } + } + + + + function __embind_register_float(rawType, name, size) { + var shift = getShiftFromSize(size); + name = readLatin1String(name); + registerType(rawType, { + name, + 'fromWireType': function(value) { + return value; + }, + 'toWireType': function(destructors, value) { + if (typeof value != "number" && typeof value != "boolean") { + throw new TypeError(`Cannot convert ${embindRepr(value)} to ${this.name}`); + } + // The VM will perform JS to Wasm value conversion, according to the spec: + // https://www.w3.org/TR/wasm-js-api-1/#towebassemblyvalue + return value; + }, + 'argPackAdvance': 8, + 'readValueFromPointer': floatReadValueFromPointer(name, shift), + destructorFunction: null, // This type does not need a destructor + }); + } + + + + + + + + + function __embind_register_function(name, argCount, rawArgTypesAddr, signature, rawInvoker, fn, isAsync) { + var argTypes = heap32VectorToArray(argCount, rawArgTypesAddr); + name = readLatin1String(name); + + rawInvoker = embind__requireFunction(signature, rawInvoker); + + exposePublicSymbol(name, function() { + throwUnboundTypeError(`Cannot call ${name} due to unbound types`, argTypes); + }, argCount - 1); + + whenDependentTypesAreResolved([], argTypes, function(argTypes) { + var invokerArgsArray = [argTypes[0] /* return value */, null /* no class 'this'*/].concat(argTypes.slice(1) /* actual params */); + replacePublicSymbol(name, craftInvokerFunction(name, invokerArgsArray, null /* no class 'this'*/, rawInvoker, fn, isAsync), argCount - 1); + return []; + }); + } + + + + function integerReadValueFromPointer(name, shift, signed) { + // integers are quite common, so generate very specialized functions + switch (shift) { + case 0: return signed ? + function readS8FromPointer(pointer) { return HEAP8[pointer]; } : + function readU8FromPointer(pointer) { return HEAPU8[pointer]; }; + case 1: return signed ? + function readS16FromPointer(pointer) { return HEAP16[pointer >> 1]; } : + function readU16FromPointer(pointer) { return HEAPU16[pointer >> 1]; }; + case 2: return signed ? + function readS32FromPointer(pointer) { return HEAP32[pointer >> 2]; } : + function readU32FromPointer(pointer) { return HEAPU32[pointer >> 2]; }; + default: + throw new TypeError("Unknown integer type: " + name); + } + } + + + function __embind_register_integer(primitiveType, name, size, minRange, maxRange) { + name = readLatin1String(name); + // LLVM doesn't have signed and unsigned 32-bit types, so u32 literals come + // out as 'i32 -1'. Always treat those as max u32. + if (maxRange === -1) { + maxRange = 4294967295; + } + + var shift = getShiftFromSize(size); + + var fromWireType = (value) => value; + + if (minRange === 0) { + var bitshift = 32 - 8*size; + fromWireType = (value) => (value << bitshift) >>> bitshift; + } + + var isUnsignedType = (name.includes('unsigned')); + var checkAssertions = (value, toTypeName) => { + if (typeof value != "number" && typeof value != "boolean") { + throw new TypeError(`Cannot convert "${embindRepr(value)}" to ${toTypeName}`); + } + if (value < minRange || value > maxRange) { + throw new TypeError(`Passing a number "${embindRepr(value)}" from JS side to C/C++ side to an argument of type "${name}", which is outside the valid range [${minRange}, ${maxRange}]!`); + } + } + var toWireType; + if (isUnsignedType) { + toWireType = function(destructors, value) { + checkAssertions(value, this.name); + return value >>> 0; + } + } else { + toWireType = function(destructors, value) { + checkAssertions(value, this.name); + // The VM will perform JS to Wasm value conversion, according to the spec: + // https://www.w3.org/TR/wasm-js-api-1/#towebassemblyvalue + return value; + } + } + registerType(primitiveType, { + name, + 'fromWireType': fromWireType, + 'toWireType': toWireType, + 'argPackAdvance': 8, + 'readValueFromPointer': integerReadValueFromPointer(name, shift, minRange !== 0), + destructorFunction: null, // This type does not need a destructor + }); + } + + + function __embind_register_memory_view(rawType, dataTypeIndex, name) { + var typeMapping = [ + Int8Array, + Uint8Array, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array, + ]; + + var TA = typeMapping[dataTypeIndex]; + + function decodeMemoryView(handle) { + handle = handle >> 2; + var heap = HEAPU32; + var size = heap[handle]; // in elements + var data = heap[handle + 1]; // byte offset into emscripten heap + return new TA(heap.buffer, data, size); + } + + name = readLatin1String(name); + registerType(rawType, { + name, + 'fromWireType': decodeMemoryView, + 'argPackAdvance': 8, + 'readValueFromPointer': decodeMemoryView, + }, { + ignoreDuplicateRegistrations: true, + }); + } + + + + function __embind_register_smart_ptr(rawType, + rawPointeeType, + name, + sharingPolicy, + getPointeeSignature, + rawGetPointee, + constructorSignature, + rawConstructor, + shareSignature, + rawShare, + destructorSignature, + rawDestructor) { + name = readLatin1String(name); + rawGetPointee = embind__requireFunction(getPointeeSignature, rawGetPointee); + rawConstructor = embind__requireFunction(constructorSignature, rawConstructor); + rawShare = embind__requireFunction(shareSignature, rawShare); + rawDestructor = embind__requireFunction(destructorSignature, rawDestructor); + + whenDependentTypesAreResolved([rawType], [rawPointeeType], function(pointeeType) { + pointeeType = pointeeType[0]; + + var registeredPointer = new RegisteredPointer(name, + pointeeType.registeredClass, + false, + false, + // smart pointer properties + true, + pointeeType, + sharingPolicy, + rawGetPointee, + rawConstructor, + rawShare, + rawDestructor); + return [registeredPointer]; + }); + } + + + + + + var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => { + assert(typeof str === 'string'); + // Parameter maxBytesToWrite is not optional. Negative values, 0, null, + // undefined and false each don't write out any bytes. + if (!(maxBytesToWrite > 0)) + return 0; + + var startIdx = outIdx; + var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator. + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code + // unit, not a Unicode code point of the character! So decode + // UTF16->UTF32->UTF8. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description + // and https://www.ietf.org/rfc/rfc2279.txt + // and https://tools.ietf.org/html/rfc3629 + var u = str.charCodeAt(i); // possibly a lead surrogate + if (u >= 0xD800 && u <= 0xDFFF) { + var u1 = str.charCodeAt(++i); + u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF); + } + if (u <= 0x7F) { + if (outIdx >= endIdx) break; + heap[outIdx++] = u; + } else if (u <= 0x7FF) { + if (outIdx + 1 >= endIdx) break; + heap[outIdx++] = 0xC0 | (u >> 6); + heap[outIdx++] = 0x80 | (u & 63); + } else if (u <= 0xFFFF) { + if (outIdx + 2 >= endIdx) break; + heap[outIdx++] = 0xE0 | (u >> 12); + heap[outIdx++] = 0x80 | ((u >> 6) & 63); + heap[outIdx++] = 0x80 | (u & 63); + } else { + if (outIdx + 3 >= endIdx) break; + if (u > 0x10FFFF) warnOnce('Invalid Unicode code point ' + ptrToString(u) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).'); + heap[outIdx++] = 0xF0 | (u >> 18); + heap[outIdx++] = 0x80 | ((u >> 12) & 63); + heap[outIdx++] = 0x80 | ((u >> 6) & 63); + heap[outIdx++] = 0x80 | (u & 63); + } + } + // Null-terminate the pointer to the buffer. + heap[outIdx] = 0; + return outIdx - startIdx; + }; + var stringToUTF8 = (str, outPtr, maxBytesToWrite) => { + assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); + return stringToUTF8Array(str, HEAPU8,outPtr, maxBytesToWrite); + }; + + var lengthBytesUTF8 = (str) => { + var len = 0; + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code + // unit, not a Unicode code point of the character! So decode + // UTF16->UTF32->UTF8. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + var c = str.charCodeAt(i); // possibly a lead surrogate + if (c <= 0x7F) { + len++; + } else if (c <= 0x7FF) { + len += 2; + } else if (c >= 0xD800 && c <= 0xDFFF) { + len += 4; ++i; + } else { + len += 3; + } + } + return len; + }; + + + + function __embind_register_std_string(rawType, name) { + name = readLatin1String(name); + var stdStringIsUTF8 + //process only std::string bindings with UTF8 support, in contrast to e.g. std::basic_string + = (name === "std::string"); + + registerType(rawType, { + name, + 'fromWireType': function(value) { + var length = HEAPU32[((value)>>2)]; + var payload = value + 4; + + var str; + if (stdStringIsUTF8) { + var decodeStartPtr = payload; + // Looping here to support possible embedded '0' bytes + for (var i = 0; i <= length; ++i) { + var currentBytePtr = payload + i; + if (i == length || HEAPU8[currentBytePtr] == 0) { + var maxRead = currentBytePtr - decodeStartPtr; + var stringSegment = UTF8ToString(decodeStartPtr, maxRead); + if (str === undefined) { + str = stringSegment; + } else { + str += String.fromCharCode(0); + str += stringSegment; + } + decodeStartPtr = currentBytePtr + 1; + } + } + } else { + var a = new Array(length); + for (var i = 0; i < length; ++i) { + a[i] = String.fromCharCode(HEAPU8[payload + i]); + } + str = a.join(''); + } + + _free(value); + + return str; + }, + 'toWireType': function(destructors, value) { + if (value instanceof ArrayBuffer) { + value = new Uint8Array(value); + } + + var length; + var valueIsOfTypeString = (typeof value == 'string'); + + if (!(valueIsOfTypeString || value instanceof Uint8Array || value instanceof Uint8ClampedArray || value instanceof Int8Array)) { + throwBindingError('Cannot pass non-string to std::string'); + } + if (stdStringIsUTF8 && valueIsOfTypeString) { + length = lengthBytesUTF8(value); + } else { + length = value.length; + } + + // assumes 4-byte alignment + var base = _malloc(4 + length + 1); + var ptr = base + 4; + HEAPU32[((base)>>2)] = length; + if (stdStringIsUTF8 && valueIsOfTypeString) { + stringToUTF8(value, ptr, length + 1); + } else { + if (valueIsOfTypeString) { + for (var i = 0; i < length; ++i) { + var charCode = value.charCodeAt(i); + if (charCode > 255) { + _free(ptr); + throwBindingError('String has UTF-16 code units that do not fit in 8 bits'); + } + HEAPU8[ptr + i] = charCode; + } + } else { + for (var i = 0; i < length; ++i) { + HEAPU8[ptr + i] = value[i]; + } + } + } + + if (destructors !== null) { + destructors.push(_free, base); + } + return base; + }, + 'argPackAdvance': 8, + 'readValueFromPointer': simpleReadValueFromPointer, + destructorFunction: function(ptr) { _free(ptr); }, + }); + } + + + + + var UTF16Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf-16le') : undefined;; + var UTF16ToString = (ptr, maxBytesToRead) => { + assert(ptr % 2 == 0, 'Pointer passed to UTF16ToString must be aligned to two bytes!'); + var endPtr = ptr; + // TextDecoder needs to know the byte length in advance, it doesn't stop on + // null terminator by itself. + // Also, use the length info to avoid running tiny strings through + // TextDecoder, since .subarray() allocates garbage. + var idx = endPtr >> 1; + var maxIdx = idx + maxBytesToRead / 2; + // If maxBytesToRead is not passed explicitly, it will be undefined, and this + // will always evaluate to true. This saves on code size. + while (!(idx >= maxIdx) && HEAPU16[idx]) ++idx; + endPtr = idx << 1; + + if (endPtr - ptr > 32 && UTF16Decoder) + return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr)); + + // Fallback: decode without UTF16Decoder + var str = ''; + + // If maxBytesToRead is not passed explicitly, it will be undefined, and the + // for-loop's condition will always evaluate to true. The loop is then + // terminated on the first null char. + for (var i = 0; !(i >= maxBytesToRead / 2); ++i) { + var codeUnit = HEAP16[(((ptr)+(i*2))>>1)]; + if (codeUnit == 0) break; + // fromCharCode constructs a character from a UTF-16 code unit, so we can + // pass the UTF16 string right through. + str += String.fromCharCode(codeUnit); + } + + return str; + }; + + var stringToUTF16 = (str, outPtr, maxBytesToWrite) => { + assert(outPtr % 2 == 0, 'Pointer passed to stringToUTF16 must be aligned to two bytes!'); + assert(typeof maxBytesToWrite == 'number', 'stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); + // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed. + if (maxBytesToWrite === undefined) { + maxBytesToWrite = 0x7FFFFFFF; + } + if (maxBytesToWrite < 2) return 0; + maxBytesToWrite -= 2; // Null terminator. + var startPtr = outPtr; + var numCharsToWrite = (maxBytesToWrite < str.length*2) ? (maxBytesToWrite / 2) : str.length; + for (var i = 0; i < numCharsToWrite; ++i) { + // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP. + var codeUnit = str.charCodeAt(i); // possibly a lead surrogate + HEAP16[((outPtr)>>1)] = codeUnit; + outPtr += 2; + } + // Null-terminate the pointer to the HEAP. + HEAP16[((outPtr)>>1)] = 0; + return outPtr - startPtr; + }; + + var lengthBytesUTF16 = (str) => { + return str.length*2; + }; + + var UTF32ToString = (ptr, maxBytesToRead) => { + assert(ptr % 4 == 0, 'Pointer passed to UTF32ToString must be aligned to four bytes!'); + var i = 0; + + var str = ''; + // If maxBytesToRead is not passed explicitly, it will be undefined, and this + // will always evaluate to true. This saves on code size. + while (!(i >= maxBytesToRead / 4)) { + var utf32 = HEAP32[(((ptr)+(i*4))>>2)]; + if (utf32 == 0) break; + ++i; + // Gotcha: fromCharCode constructs a character from a UTF-16 encoded code (pair), not from a Unicode code point! So encode the code point to UTF-16 for constructing. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + if (utf32 >= 0x10000) { + var ch = utf32 - 0x10000; + str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); + } else { + str += String.fromCharCode(utf32); + } + } + return str; + }; + + var stringToUTF32 = (str, outPtr, maxBytesToWrite) => { + assert(outPtr % 4 == 0, 'Pointer passed to stringToUTF32 must be aligned to four bytes!'); + assert(typeof maxBytesToWrite == 'number', 'stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); + // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed. + if (maxBytesToWrite === undefined) { + maxBytesToWrite = 0x7FFFFFFF; + } + if (maxBytesToWrite < 4) return 0; + var startPtr = outPtr; + var endPtr = startPtr + maxBytesToWrite - 4; + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + var codeUnit = str.charCodeAt(i); // possibly a lead surrogate + if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) { + var trailSurrogate = str.charCodeAt(++i); + codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF); + } + HEAP32[((outPtr)>>2)] = codeUnit; + outPtr += 4; + if (outPtr + 4 > endPtr) break; + } + // Null-terminate the pointer to the HEAP. + HEAP32[((outPtr)>>2)] = 0; + return outPtr - startPtr; + }; + + var lengthBytesUTF32 = (str) => { + var len = 0; + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + var codeUnit = str.charCodeAt(i); + if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) ++i; // possibly a lead surrogate, so skip over the tail surrogate. + len += 4; + } + + return len; + }; + var __embind_register_std_wstring = function(rawType, charSize, name) { + name = readLatin1String(name); + var decodeString, encodeString, getHeap, lengthBytesUTF, shift; + if (charSize === 2) { + decodeString = UTF16ToString; + encodeString = stringToUTF16; + lengthBytesUTF = lengthBytesUTF16; + getHeap = () => HEAPU16; + shift = 1; + } else if (charSize === 4) { + decodeString = UTF32ToString; + encodeString = stringToUTF32; + lengthBytesUTF = lengthBytesUTF32; + getHeap = () => HEAPU32; + shift = 2; + } + registerType(rawType, { + name, + 'fromWireType': function(value) { + // Code mostly taken from _embind_register_std_string fromWireType + var length = HEAPU32[value >> 2]; + var HEAP = getHeap(); + var str; + + var decodeStartPtr = value + 4; + // Looping here to support possible embedded '0' bytes + for (var i = 0; i <= length; ++i) { + var currentBytePtr = value + 4 + i * charSize; + if (i == length || HEAP[currentBytePtr >> shift] == 0) { + var maxReadBytes = currentBytePtr - decodeStartPtr; + var stringSegment = decodeString(decodeStartPtr, maxReadBytes); + if (str === undefined) { + str = stringSegment; + } else { + str += String.fromCharCode(0); + str += stringSegment; + } + decodeStartPtr = currentBytePtr + charSize; + } + } + + _free(value); + + return str; + }, + 'toWireType': function(destructors, value) { + if (!(typeof value == 'string')) { + throwBindingError(`Cannot pass non-string to C++ string type ${name}`); + } + + // assumes 4-byte alignment + var length = lengthBytesUTF(value); + var ptr = _malloc(4 + length + charSize); + HEAPU32[ptr >> 2] = length >> shift; + + encodeString(value, ptr + 4, length + charSize); + + if (destructors !== null) { + destructors.push(_free, ptr); + } + return ptr; + }, + 'argPackAdvance': 8, + 'readValueFromPointer': simpleReadValueFromPointer, + destructorFunction: function(ptr) { _free(ptr); }, + }); + }; + + + + function __embind_register_value_array( + rawType, + name, + constructorSignature, + rawConstructor, + destructorSignature, + rawDestructor + ) { + tupleRegistrations[rawType] = { + name: readLatin1String(name), + rawConstructor: embind__requireFunction(constructorSignature, rawConstructor), + rawDestructor: embind__requireFunction(destructorSignature, rawDestructor), + elements: [], + }; + } + + + function __embind_register_value_array_element( + rawTupleType, + getterReturnType, + getterSignature, + getter, + getterContext, + setterArgumentType, + setterSignature, + setter, + setterContext + ) { + tupleRegistrations[rawTupleType].elements.push({ + getterReturnType, + getter: embind__requireFunction(getterSignature, getter), + getterContext, + setterArgumentType, + setter: embind__requireFunction(setterSignature, setter), + setterContext, + }); + } + + + + function __embind_register_value_object( + rawType, + name, + constructorSignature, + rawConstructor, + destructorSignature, + rawDestructor + ) { + structRegistrations[rawType] = { + name: readLatin1String(name), + rawConstructor: embind__requireFunction(constructorSignature, rawConstructor), + rawDestructor: embind__requireFunction(destructorSignature, rawDestructor), + fields: [], + }; + } + + + + function __embind_register_value_object_field( + structType, + fieldName, + getterReturnType, + getterSignature, + getter, + getterContext, + setterArgumentType, + setterSignature, + setter, + setterContext + ) { + structRegistrations[structType].fields.push({ + fieldName: readLatin1String(fieldName), + getterReturnType, + getter: embind__requireFunction(getterSignature, getter), + getterContext, + setterArgumentType, + setter: embind__requireFunction(setterSignature, setter), + setterContext, + }); + } + + + function __embind_register_void(rawType, name) { + name = readLatin1String(name); + registerType(rawType, { + isVoid: true, // void return values can be optimized out sometimes + name, + 'argPackAdvance': 0, + 'fromWireType': function() { + return undefined; + }, + 'toWireType': function(destructors, o) { + // TODO: assert if anything else is given? + return undefined; + }, + }); + } + + + function __emval_as(handle, returnType, destructorsRef) { + handle = Emval.toValue(handle); + returnType = requireRegisteredType(returnType, 'emval::as'); + var destructors = []; + var rd = Emval.toHandle(destructors); + HEAPU32[((destructorsRef)>>2)] = rd; + return returnType['toWireType'](destructors, handle); + } + + + + function __emval_as_int64(handle, returnType) { + handle = Emval.toValue(handle); + returnType = requireRegisteredType(returnType, 'emval::as'); + return returnType['toWireType'](null, handle); + } + + + + function __emval_as_uint64(handle, returnType) { + handle = Emval.toValue(handle); + returnType = requireRegisteredType(returnType, 'emval::as'); + return returnType['toWireType'](null, handle); + } + + /** @type {function(...*):?} */ + function __emval_await( + ) { + err('missing function: _emval_await'); abort(-1); + } + + function emval_lookupTypes(argCount, argTypes) { + var a = new Array(argCount); + for (var i = 0; i < argCount; ++i) { + a[i] = requireRegisteredType(HEAPU32[(((argTypes)+(i * 4))>>2)], + "parameter " + i); + } + return a; + } + + function __emval_call(handle, argCount, argTypes, argv) { + handle = Emval.toValue(handle); + var types = emval_lookupTypes(argCount, argTypes); + + var args = new Array(argCount); + for (var i = 0; i < argCount; ++i) { + var type = types[i]; + args[i] = type['readValueFromPointer'](argv); + argv += type['argPackAdvance']; + } + + var rv = handle.apply(undefined, args); + return Emval.toHandle(rv); + } + + function emval_allocateDestructors(destructorsRef) { + var destructors = []; + HEAPU32[((destructorsRef)>>2)] = Emval.toHandle(destructors); + return destructors; + } + + var emval_symbols = { + }; + + function getStringOrSymbol(address) { + var symbol = emval_symbols[address]; + if (symbol === undefined) { + return readLatin1String(address); + } + return symbol; + } + + var emval_methodCallers = []; + + function __emval_call_method(caller, handle, methodName, destructorsRef, args) { + caller = emval_methodCallers[caller]; + handle = Emval.toValue(handle); + methodName = getStringOrSymbol(methodName); + return caller(handle, methodName, emval_allocateDestructors(destructorsRef), args); + } + + + + + function __emval_call_void_method(caller, handle, methodName, args) { + caller = emval_methodCallers[caller]; + handle = Emval.toValue(handle); + methodName = getStringOrSymbol(methodName); + caller(handle, methodName, null, args); + } + + + function __emval_delete(object, property) { + object = Emval.toValue(object); + property = Emval.toValue(property); + return delete object[property]; + } + + function __emval_equals(first, second) { + first = Emval.toValue(first); + second = Emval.toValue(second); + return first == second; + } + + + + function emval_get_global() { + if (typeof globalThis == 'object') { + return globalThis; + } + return (function(){ + return Function; + })()('return this')(); + } + function __emval_get_global(name) { + if (name===0) { + return Emval.toHandle(emval_get_global()); + } else { + name = getStringOrSymbol(name); + return Emval.toHandle(emval_get_global()[name]); + } + } + + function emval_addMethodCaller(caller) { + var id = emval_methodCallers.length; + emval_methodCallers.push(caller); + return id; + } + + + + var emval_registeredMethods = []; + + function __emval_get_method_caller(argCount, argTypes) { + var types = emval_lookupTypes(argCount, argTypes); + var retType = types[0]; + var signatureName = retType.name + "_$" + types.slice(1).map(function (t) { return t.name; }).join("_") + "$"; + var returnId = emval_registeredMethods[signatureName]; + if (returnId !== undefined) { + return returnId; + } + + var params = ["retType"]; + var args = [retType]; + + var argsList = ""; // 'arg0, arg1, arg2, ... , argN' + for (var i = 0; i < argCount - 1; ++i) { + argsList += (i !== 0 ? ", " : "") + "arg" + i; + params.push("argType" + i); + args.push(types[1 + i]); + } + + var functionName = makeLegalFunctionName("methodCaller_" + signatureName); + var functionBody = + "return function " + functionName + "(handle, name, destructors, args) {\n"; + + var offset = 0; + for (var i = 0; i < argCount - 1; ++i) { + functionBody += + " var arg" + i + " = argType" + i + ".readValueFromPointer(args" + (offset ? ("+"+offset) : "") + ");\n"; + offset += types[i + 1]['argPackAdvance']; + } + functionBody += + " var rv = handle[name](" + argsList + ");\n"; + for (var i = 0; i < argCount - 1; ++i) { + if (types[i + 1]['deleteObject']) { + functionBody += + " argType" + i + ".deleteObject(arg" + i + ");\n"; + } + } + if (!retType.isVoid) { + functionBody += + " return retType.toWireType(destructors, rv);\n"; + } + functionBody += + "};\n"; + + params.push(functionBody); + var invokerFunction = newFunc(Function, params).apply(null, args); + returnId = emval_addMethodCaller(invokerFunction); + emval_registeredMethods[signatureName] = returnId; + return returnId; + } + + + function __emval_get_module_property(name) { + name = getStringOrSymbol(name); + return Emval.toHandle(Module[name]); + } + + function __emval_get_property(handle, key) { + handle = Emval.toValue(handle); + key = Emval.toValue(key); + return Emval.toHandle(handle[key]); + } + + function __emval_in(item, object) { + item = Emval.toValue(item); + object = Emval.toValue(object); + return item in object; + } + + function __emval_incref(handle) { + if (handle > 4) { + emval_handles.get(handle).refcount += 1; + } + } + + function __emval_instanceof(object, constructor) { + object = Emval.toValue(object); + constructor = Emval.toValue(constructor); + return object instanceof constructor; + } + + function __emval_is_number(handle) { + handle = Emval.toValue(handle); + return typeof handle == 'number'; + } + + function __emval_is_string(handle) { + handle = Emval.toValue(handle); + return typeof handle == 'string'; + } + + + function craftEmvalAllocator(argCount) { + /*This function returns a new function that looks like this: + function emval_allocator_3(constructor, argTypes, args) { + var argType0 = requireRegisteredType(HEAP32[(argTypes >> 2)], "parameter 0"); + var arg0 = argType0['readValueFromPointer'](args); + var argType1 = requireRegisteredType(HEAP32[(argTypes >> 2) + 1], "parameter 1"); + var arg1 = argType1['readValueFromPointer'](args + 8); + var argType2 = requireRegisteredType(HEAP32[(argTypes >> 2) + 2], "parameter 2"); + var arg2 = argType2['readValueFromPointer'](args + 16); + var obj = new constructor(arg0, arg1, arg2); + return Emval.toHandle(obj); + } */ + var argsList = ""; + for (var i = 0; i < argCount; ++i) { + argsList += (i!==0?", ":"")+"arg"+i; // 'arg0, arg1, ..., argn' + } + + // The body of the generated function does not have access to enclosing + // scope where HEAPU64/HEAPU32/etc are defined, and we cannot pass them + // directly as arguments (like we do the Module object) since memory + // growth can cause them to be re-bound. + var getMemory = () => HEAPU32; + + var functionBody = + "return function emval_allocator_"+argCount+"(constructor, argTypes, args) {\n" + + " var HEAPU32 = getMemory();\n"; + + for (var i = 0; i < argCount; ++i) { + functionBody += + "var argType"+i+" = requireRegisteredType(HEAPU32[((argTypes)>>2)], 'parameter "+i+"');\n" + + "var arg"+i+" = argType"+i+".readValueFromPointer(args);\n" + + "args += argType"+i+"['argPackAdvance'];\n" + + "argTypes += 4;\n"; + } + functionBody += + "var obj = new constructor("+argsList+");\n" + + "return valueToHandle(obj);\n" + + "}\n"; + + /*jshint evil:true*/ + return (new Function("requireRegisteredType", "Module", "valueToHandle", "getMemory" , functionBody))( + requireRegisteredType, Module, Emval.toHandle, getMemory); + } + + var emval_newers = { + }; + + function __emval_new(handle, argCount, argTypes, args) { + handle = Emval.toValue(handle); + + var newer = emval_newers[argCount]; + if (!newer) { + newer = craftEmvalAllocator(argCount); + emval_newers[argCount] = newer; + } + + return newer(handle, argTypes, args); + } + + function __emval_new_array() { + return Emval.toHandle([]); + } + + function __emval_new_array_from_memory_view(view) { + view = Emval.toValue(view); + // using for..loop is faster than Array.from + var a = new Array(view.length); + for (var i = 0; i < view.length; i++) a[i] = view[i]; + return Emval.toHandle(a); + } + + + function __emval_new_cstring(v) { + return Emval.toHandle(getStringOrSymbol(v)); + } + + function __emval_new_object() { + return Emval.toHandle({}); + } + + function __emval_new_u16string(v) { + return Emval.toHandle(UTF16ToString(v)); + } + + + function __emval_new_u8string(v) { + return Emval.toHandle(UTF8ToString(v)); + } + + + function __emval_register_symbol(address) { + emval_symbols[address] = readLatin1String(address); + } + + + + function __emval_run_destructors(handle) { + var destructors = Emval.toValue(handle); + runDestructors(destructors); + __emval_decref(handle); + } + + function __emval_set_property(handle, key, value) { + handle = Emval.toValue(handle); + key = Emval.toValue(key); + value = Emval.toValue(value); + handle[key] = value; + } + + function __emval_strictly_equals(first, second) { + first = Emval.toValue(first); + second = Emval.toValue(second); + return first === second; + } + + + function __emval_take_value(type, arg) { + type = requireRegisteredType(type, '_emval_take_value'); + var v = type['readValueFromPointer'](arg); + return Emval.toHandle(v); + } + + function __emval_throw(object) { + object = Emval.toValue(object); + throw object; + } + + function __emval_typeof(handle) { + handle = Emval.toValue(handle); + return Emval.toHandle(typeof handle); + } + + var _abort = () => { + abort('native code called abort()'); + }; + + var _emscripten_memcpy_big = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num); + + var getHeapMax = () => + HEAPU8.length; + + var abortOnCannotGrowMemory = (requestedSize) => { + abort(`Cannot enlarge memory arrays to size ${requestedSize} bytes (OOM). Either (1) compile with -sINITIAL_MEMORY=X with X higher than the current value ${HEAP8.length}, (2) compile with -sALLOW_MEMORY_GROWTH which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -sABORTING_MALLOC=0`); + }; + var _emscripten_resize_heap = (requestedSize) => { + var oldSize = HEAPU8.length; + // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned. + requestedSize >>>= 0; + abortOnCannotGrowMemory(requestedSize); + }; + + var ENV = { + }; + + var getExecutableName = () => { + return thisProgram || './this.program'; + }; + var getEnvStrings = () => { + if (!getEnvStrings.strings) { + // Default values. + // Browser language detection #8751 + var lang = ((typeof navigator == 'object' && navigator.languages && navigator.languages[0]) || 'C').replace('-', '_') + '.UTF-8'; + var env = { + 'USER': 'web_user', + 'LOGNAME': 'web_user', + 'PATH': '/', + 'PWD': '/', + 'HOME': '/home/web_user', + 'LANG': lang, + '_': getExecutableName() + }; + // Apply the user-provided values, if any. + for (var x in ENV) { + // x is a key in ENV; if ENV[x] is undefined, that means it was + // explicitly set to be so. We allow user code to do that to + // force variables with default values to remain unset. + if (ENV[x] === undefined) delete env[x]; + else env[x] = ENV[x]; + } + var strings = []; + for (var x in env) { + strings.push(`${x}=${env[x]}`); + } + getEnvStrings.strings = strings; + } + return getEnvStrings.strings; + }; + + var stringToAscii = (str, buffer) => { + for (var i = 0; i < str.length; ++i) { + assert(str.charCodeAt(i) === (str.charCodeAt(i) & 0xff)); + HEAP8[((buffer++)>>0)] = str.charCodeAt(i); + } + // Null-terminate the string + HEAP8[((buffer)>>0)] = 0; + }; + + var PATH = { + isAbs:(path) => path.charAt(0) === '/', + splitPath:(filename) => { + var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; + return splitPathRe.exec(filename).slice(1); + }, + normalizeArray:(parts, allowAboveRoot) => { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up; up--) { + parts.unshift('..'); + } + } + return parts; + }, + normalize:(path) => { + var isAbsolute = PATH.isAbs(path), + trailingSlash = path.substr(-1) === '/'; + // Normalize the path + path = PATH.normalizeArray(path.split('/').filter((p) => !!p), !isAbsolute).join('/'); + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + return (isAbsolute ? '/' : '') + path; + }, + dirname:(path) => { + var result = PATH.splitPath(path), + root = result[0], + dir = result[1]; + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + return root + dir; + }, + basename:(path) => { + // EMSCRIPTEN return '/'' for '/', not an empty string + if (path === '/') return '/'; + path = PATH.normalize(path); + path = path.replace(/\/$/, ""); + var lastSlash = path.lastIndexOf('/'); + if (lastSlash === -1) return path; + return path.substr(lastSlash+1); + }, + join:function() { + var paths = Array.prototype.slice.call(arguments); + return PATH.normalize(paths.join('/')); + }, + join2:(l, r) => { + return PATH.normalize(l + '/' + r); + }, + }; + + var initRandomFill = () => { + if (typeof crypto == 'object' && typeof crypto['getRandomValues'] == 'function') { + // for modern web browsers + return (view) => crypto.getRandomValues(view); + } else + if (ENVIRONMENT_IS_NODE) { + // for nodejs with or without crypto support included + try { + var crypto_module = require('crypto'); + var randomFillSync = crypto_module['randomFillSync']; + if (randomFillSync) { + // nodejs with LTS crypto support + return (view) => crypto_module['randomFillSync'](view); + } + // very old nodejs with the original crypto API + var randomBytes = crypto_module['randomBytes']; + return (view) => ( + view.set(randomBytes(view.byteLength)), + // Return the original view to match modern native implementations. + view + ); + } catch (e) { + // nodejs doesn't have crypto support + } + } + // we couldn't find a proper implementation, as Math.random() is not suitable for /dev/random, see emscripten-core/emscripten/pull/7096 + abort("no cryptographic support found for randomDevice. consider polyfilling it if you want to use something insecure like Math.random(), e.g. put this in a --pre-js: var crypto = { getRandomValues: (array) => { for (var i = 0; i < array.length; i++) array[i] = (Math.random()*256)|0 } };"); + }; + var randomFill = (view) => { + // Lazily init on the first invocation. + return (randomFill = initRandomFill())(view); + }; + + + + var PATH_FS = { + resolve:function() { + var resolvedPath = '', + resolvedAbsolute = false; + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : FS.cwd(); + // Skip empty and invalid entries + if (typeof path != 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + return ''; // an invalid portion invalidates the whole thing + } + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = PATH.isAbs(path); + } + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + resolvedPath = PATH.normalizeArray(resolvedPath.split('/').filter((p) => !!p), !resolvedAbsolute).join('/'); + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; + }, + relative:(from, to) => { + from = PATH_FS.resolve(from).substr(1); + to = PATH_FS.resolve(to).substr(1); + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + return outputParts.join('/'); + }, + }; + + + + var FS_stdin_getChar_buffer = []; + + + /** @type {function(string, boolean=, number=)} */ + function intArrayFromString(stringy, dontAddNull, length) { + var len = length > 0 ? length : lengthBytesUTF8(stringy)+1; + var u8array = new Array(len); + var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length); + if (dontAddNull) u8array.length = numBytesWritten; + return u8array; + } + var FS_stdin_getChar = () => { + if (!FS_stdin_getChar_buffer.length) { + var result = null; + if (ENVIRONMENT_IS_NODE) { + // we will read data by chunks of BUFSIZE + var BUFSIZE = 256; + var buf = Buffer.alloc(BUFSIZE); + var bytesRead = 0; + + // For some reason we must suppress a closure warning here, even though + // fd definitely exists on process.stdin, and is even the proper way to + // get the fd of stdin, + // https://github.com/nodejs/help/issues/2136#issuecomment-523649904 + // This started to happen after moving this logic out of library_tty.js, + // so it is related to the surrounding code in some unclear manner. + /** @suppress {missingProperties} */ + var fd = process.stdin.fd; + + try { + bytesRead = fs.readSync(fd, buf, 0, BUFSIZE, -1); + } catch(e) { + // Cross-platform differences: on Windows, reading EOF throws an exception, but on other OSes, + // reading EOF returns 0. Uniformize behavior by treating the EOF exception to return 0. + if (e.toString().includes('EOF')) bytesRead = 0; + else throw e; + } + + if (bytesRead > 0) { + result = buf.slice(0, bytesRead).toString('utf-8'); + } else { + result = null; + } + } else + if (typeof window != 'undefined' && + typeof window.prompt == 'function') { + // Browser. + result = window.prompt('Input: '); // returns null on cancel + if (result !== null) { + result += '\n'; + } + } else if (typeof readline == 'function') { + // Command line. + result = readline(); + if (result !== null) { + result += '\n'; + } + } + if (!result) { + return null; + } + FS_stdin_getChar_buffer = intArrayFromString(result, true); + } + return FS_stdin_getChar_buffer.shift(); + }; + var TTY = { + ttys:[], + init:function () { + // https://github.com/emscripten-core/emscripten/pull/1555 + // if (ENVIRONMENT_IS_NODE) { + // // currently, FS.init does not distinguish if process.stdin is a file or TTY + // // device, it always assumes it's a TTY device. because of this, we're forcing + // // process.stdin to UTF8 encoding to at least make stdin reading compatible + // // with text files until FS.init can be refactored. + // process.stdin.setEncoding('utf8'); + // } + }, + shutdown:function() { + // https://github.com/emscripten-core/emscripten/pull/1555 + // if (ENVIRONMENT_IS_NODE) { + // // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)? + // // isaacs: because now it's reading from the stream, you've expressed interest in it, so that read() kicks off a _read() which creates a ReadReq operation + // // inolen: I thought read() in that case was a synchronous operation that just grabbed some amount of buffered data if it exists? + // // isaacs: it is. but it also triggers a _read() call, which calls readStart() on the handle + // // isaacs: do process.stdin.pause() and i'd think it'd probably close the pending call + // process.stdin.pause(); + // } + }, + register:function(dev, ops) { + TTY.ttys[dev] = { input: [], output: [], ops: ops }; + FS.registerDevice(dev, TTY.stream_ops); + }, + stream_ops:{ + open:function(stream) { + var tty = TTY.ttys[stream.node.rdev]; + if (!tty) { + throw new FS.ErrnoError(43); + } + stream.tty = tty; + stream.seekable = false; + }, + close:function(stream) { + // flush any pending line data + stream.tty.ops.fsync(stream.tty); + }, + fsync:function(stream) { + stream.tty.ops.fsync(stream.tty); + }, + read:function(stream, buffer, offset, length, pos /* ignored */) { + if (!stream.tty || !stream.tty.ops.get_char) { + throw new FS.ErrnoError(60); + } + var bytesRead = 0; + for (var i = 0; i < length; i++) { + var result; + try { + result = stream.tty.ops.get_char(stream.tty); + } catch (e) { + throw new FS.ErrnoError(29); + } + if (result === undefined && bytesRead === 0) { + throw new FS.ErrnoError(6); + } + if (result === null || result === undefined) break; + bytesRead++; + buffer[offset+i] = result; + } + if (bytesRead) { + stream.node.timestamp = Date.now(); + } + return bytesRead; + }, + write:function(stream, buffer, offset, length, pos) { + if (!stream.tty || !stream.tty.ops.put_char) { + throw new FS.ErrnoError(60); + } + try { + for (var i = 0; i < length; i++) { + stream.tty.ops.put_char(stream.tty, buffer[offset+i]); + } + } catch (e) { + throw new FS.ErrnoError(29); + } + if (length) { + stream.node.timestamp = Date.now(); + } + return i; + }, + }, + default_tty_ops:{ + get_char:function(tty) { + return FS_stdin_getChar(); + }, + put_char:function(tty, val) { + if (val === null || val === 10) { + out(UTF8ArrayToString(tty.output, 0)); + tty.output = []; + } else { + if (val != 0) tty.output.push(val); // val == 0 would cut text output off in the middle. + } + }, + fsync:function(tty) { + if (tty.output && tty.output.length > 0) { + out(UTF8ArrayToString(tty.output, 0)); + tty.output = []; + } + }, + ioctl_tcgets:function(tty) { + // typical setting + return { + c_iflag: 25856, + c_oflag: 5, + c_cflag: 191, + c_lflag: 35387, + c_cc: [ + 0x03, 0x1c, 0x7f, 0x15, 0x04, 0x00, 0x01, 0x00, 0x11, 0x13, 0x1a, 0x00, + 0x12, 0x0f, 0x17, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ] + }; + }, + ioctl_tcsets:function(tty, optional_actions, data) { + // currently just ignore + return 0; + }, + ioctl_tiocgwinsz:function(tty) { + return [24, 80]; + }, + }, + default_tty1_ops:{ + put_char:function(tty, val) { + if (val === null || val === 10) { + err(UTF8ArrayToString(tty.output, 0)); + tty.output = []; + } else { + if (val != 0) tty.output.push(val); + } + }, + fsync:function(tty) { + if (tty.output && tty.output.length > 0) { + err(UTF8ArrayToString(tty.output, 0)); + tty.output = []; + } + }, + }, + }; + + + var zeroMemory = (address, size) => { + HEAPU8.fill(0, address, address + size); + return address; + }; + + var alignMemory = (size, alignment) => { + assert(alignment, "alignment argument is required"); + return Math.ceil(size / alignment) * alignment; + }; + var mmapAlloc = (size) => { + abort('internal error: mmapAlloc called but `emscripten_builtin_memalign` native symbol not exported'); + }; + var MEMFS = { + ops_table:null, + mount(mount) { + return MEMFS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + }, + createNode(parent, name, mode, dev) { + if (FS.isBlkdev(mode) || FS.isFIFO(mode)) { + // no supported + throw new FS.ErrnoError(63); + } + if (!MEMFS.ops_table) { + MEMFS.ops_table = { + dir: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr, + lookup: MEMFS.node_ops.lookup, + mknod: MEMFS.node_ops.mknod, + rename: MEMFS.node_ops.rename, + unlink: MEMFS.node_ops.unlink, + rmdir: MEMFS.node_ops.rmdir, + readdir: MEMFS.node_ops.readdir, + symlink: MEMFS.node_ops.symlink + }, + stream: { + llseek: MEMFS.stream_ops.llseek + } + }, + file: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr + }, + stream: { + llseek: MEMFS.stream_ops.llseek, + read: MEMFS.stream_ops.read, + write: MEMFS.stream_ops.write, + allocate: MEMFS.stream_ops.allocate, + mmap: MEMFS.stream_ops.mmap, + msync: MEMFS.stream_ops.msync + } + }, + link: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr, + readlink: MEMFS.node_ops.readlink + }, + stream: {} + }, + chrdev: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr + }, + stream: FS.chrdev_stream_ops + } + }; + } + var node = FS.createNode(parent, name, mode, dev); + if (FS.isDir(node.mode)) { + node.node_ops = MEMFS.ops_table.dir.node; + node.stream_ops = MEMFS.ops_table.dir.stream; + node.contents = {}; + } else if (FS.isFile(node.mode)) { + node.node_ops = MEMFS.ops_table.file.node; + node.stream_ops = MEMFS.ops_table.file.stream; + node.usedBytes = 0; // The actual number of bytes used in the typed array, as opposed to contents.length which gives the whole capacity. + // When the byte data of the file is populated, this will point to either a typed array, or a normal JS array. Typed arrays are preferred + // for performance, and used by default. However, typed arrays are not resizable like normal JS arrays are, so there is a small disk size + // penalty involved for appending file writes that continuously grow a file similar to std::vector capacity vs used -scheme. + node.contents = null; + } else if (FS.isLink(node.mode)) { + node.node_ops = MEMFS.ops_table.link.node; + node.stream_ops = MEMFS.ops_table.link.stream; + } else if (FS.isChrdev(node.mode)) { + node.node_ops = MEMFS.ops_table.chrdev.node; + node.stream_ops = MEMFS.ops_table.chrdev.stream; + } + node.timestamp = Date.now(); + // add the new node to the parent + if (parent) { + parent.contents[name] = node; + parent.timestamp = node.timestamp; + } + return node; + }, + getFileDataAsTypedArray(node) { + if (!node.contents) return new Uint8Array(0); + if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes. + return new Uint8Array(node.contents); + }, + expandFileStorage(node, newCapacity) { + var prevCapacity = node.contents ? node.contents.length : 0; + if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough. + // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity. + // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to + // avoid overshooting the allocation cap by a very large margin. + var CAPACITY_DOUBLING_MAX = 1024 * 1024; + newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) >>> 0); + if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding. + var oldContents = node.contents; + node.contents = new Uint8Array(newCapacity); // Allocate new storage. + if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0); // Copy old data over to the new storage. + }, + resizeFileStorage(node, newSize) { + if (node.usedBytes == newSize) return; + if (newSize == 0) { + node.contents = null; // Fully decommit when requesting a resize to zero. + node.usedBytes = 0; + } else { + var oldContents = node.contents; + node.contents = new Uint8Array(newSize); // Allocate new storage. + if (oldContents) { + node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage. + } + node.usedBytes = newSize; + } + }, + node_ops:{ + getattr(node) { + var attr = {}; + // device numbers reuse inode numbers. + attr.dev = FS.isChrdev(node.mode) ? node.id : 1; + attr.ino = node.id; + attr.mode = node.mode; + attr.nlink = 1; + attr.uid = 0; + attr.gid = 0; + attr.rdev = node.rdev; + if (FS.isDir(node.mode)) { + attr.size = 4096; + } else if (FS.isFile(node.mode)) { + attr.size = node.usedBytes; + } else if (FS.isLink(node.mode)) { + attr.size = node.link.length; + } else { + attr.size = 0; + } + attr.atime = new Date(node.timestamp); + attr.mtime = new Date(node.timestamp); + attr.ctime = new Date(node.timestamp); + // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize), + // but this is not required by the standard. + attr.blksize = 4096; + attr.blocks = Math.ceil(attr.size / attr.blksize); + return attr; + }, + setattr(node, attr) { + if (attr.mode !== undefined) { + node.mode = attr.mode; + } + if (attr.timestamp !== undefined) { + node.timestamp = attr.timestamp; + } + if (attr.size !== undefined) { + MEMFS.resizeFileStorage(node, attr.size); + } + }, + lookup(parent, name) { + throw FS.genericErrors[44]; + }, + mknod(parent, name, mode, dev) { + return MEMFS.createNode(parent, name, mode, dev); + }, + rename(old_node, new_dir, new_name) { + // if we're overwriting a directory at new_name, make sure it's empty. + if (FS.isDir(old_node.mode)) { + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) { + } + if (new_node) { + for (var i in new_node.contents) { + throw new FS.ErrnoError(55); + } + } + } + // do the internal rewiring + delete old_node.parent.contents[old_node.name]; + old_node.parent.timestamp = Date.now() + old_node.name = new_name; + new_dir.contents[new_name] = old_node; + new_dir.timestamp = old_node.parent.timestamp; + old_node.parent = new_dir; + }, + unlink(parent, name) { + delete parent.contents[name]; + parent.timestamp = Date.now(); + }, + rmdir(parent, name) { + var node = FS.lookupNode(parent, name); + for (var i in node.contents) { + throw new FS.ErrnoError(55); + } + delete parent.contents[name]; + parent.timestamp = Date.now(); + }, + readdir(node) { + var entries = ['.', '..']; + for (var key in node.contents) { + if (!node.contents.hasOwnProperty(key)) { + continue; + } + entries.push(key); + } + return entries; + }, + symlink(parent, newname, oldpath) { + var node = MEMFS.createNode(parent, newname, 511 /* 0777 */ | 40960, 0); + node.link = oldpath; + return node; + }, + readlink(node) { + if (!FS.isLink(node.mode)) { + throw new FS.ErrnoError(28); + } + return node.link; + }, + }, + stream_ops:{ + read(stream, buffer, offset, length, position) { + var contents = stream.node.contents; + if (position >= stream.node.usedBytes) return 0; + var size = Math.min(stream.node.usedBytes - position, length); + assert(size >= 0); + if (size > 8 && contents.subarray) { // non-trivial, and typed array + buffer.set(contents.subarray(position, position + size), offset); + } else { + for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i]; + } + return size; + }, + write(stream, buffer, offset, length, position, canOwn) { + // The data buffer should be a typed array view + assert(!(buffer instanceof ArrayBuffer)); + + if (!length) return 0; + var node = stream.node; + node.timestamp = Date.now(); + + if (buffer.subarray && (!node.contents || node.contents.subarray)) { // This write is from a typed array to a typed array? + if (canOwn) { + assert(position === 0, 'canOwn must imply no weird position inside the file'); + node.contents = buffer.subarray(offset, offset + length); + node.usedBytes = length; + return length; + } else if (node.usedBytes === 0 && position === 0) { // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data. + node.contents = buffer.slice(offset, offset + length); + node.usedBytes = length; + return length; + } else if (position + length <= node.usedBytes) { // Writing to an already allocated and used subrange of the file? + node.contents.set(buffer.subarray(offset, offset + length), position); + return length; + } + } + + // Appending to an existing file and we need to reallocate, or source data did not come as a typed array. + MEMFS.expandFileStorage(node, position+length); + if (node.contents.subarray && buffer.subarray) { + // Use typed array write which is available. + node.contents.set(buffer.subarray(offset, offset + length), position); + } else { + for (var i = 0; i < length; i++) { + node.contents[position + i] = buffer[offset + i]; // Or fall back to manual write if not. + } + } + node.usedBytes = Math.max(node.usedBytes, position + length); + return length; + }, + llseek(stream, offset, whence) { + var position = offset; + if (whence === 1) { + position += stream.position; + } else if (whence === 2) { + if (FS.isFile(stream.node.mode)) { + position += stream.node.usedBytes; + } + } + if (position < 0) { + throw new FS.ErrnoError(28); + } + return position; + }, + allocate(stream, offset, length) { + MEMFS.expandFileStorage(stream.node, offset + length); + stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length); + }, + mmap(stream, length, position, prot, flags) { + if (!FS.isFile(stream.node.mode)) { + throw new FS.ErrnoError(43); + } + var ptr; + var allocated; + var contents = stream.node.contents; + // Only make a new copy when MAP_PRIVATE is specified. + if (!(flags & 2) && contents.buffer === HEAP8.buffer) { + // We can't emulate MAP_SHARED when the file is not backed by the + // buffer we're mapping to (e.g. the HEAP buffer). + allocated = false; + ptr = contents.byteOffset; + } else { + // Try to avoid unnecessary slices. + if (position > 0 || position + length < contents.length) { + if (contents.subarray) { + contents = contents.subarray(position, position + length); + } else { + contents = Array.prototype.slice.call(contents, position, position + length); + } + } + allocated = true; + ptr = mmapAlloc(length); + if (!ptr) { + throw new FS.ErrnoError(48); + } + HEAP8.set(contents, ptr); + } + return { ptr, allocated }; + }, + msync(stream, buffer, offset, length, mmapFlags) { + MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false); + // should we check if bytesWritten and length are the same? + return 0; + }, + }, + }; + + /** @param {boolean=} noRunDep */ + var asyncLoad = (url, onload, onerror, noRunDep) => { + var dep = !noRunDep ? getUniqueRunDependency(`al ${url}`) : ''; + readAsync(url, (arrayBuffer) => { + assert(arrayBuffer, `Loading data file "${url}" failed (no arrayBuffer).`); + onload(new Uint8Array(arrayBuffer)); + if (dep) removeRunDependency(dep); + }, (event) => { + if (onerror) { + onerror(); + } else { + throw `Loading data file "${url}" failed.`; + } + }); + if (dep) addRunDependency(dep); + }; + + + var preloadPlugins = Module['preloadPlugins'] || []; + function FS_handledByPreloadPlugin(byteArray, fullname, finish, onerror) { + // Ensure plugins are ready. + if (typeof Browser != 'undefined') Browser.init(); + + var handled = false; + preloadPlugins.forEach(function(plugin) { + if (handled) return; + if (plugin['canHandle'](fullname)) { + plugin['handle'](byteArray, fullname, finish, onerror); + handled = true; + } + }); + return handled; + } + function FS_createPreloadedFile(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) { + // TODO we should allow people to just pass in a complete filename instead + // of parent and name being that we just join them anyways + var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent; + var dep = getUniqueRunDependency(`cp ${fullname}`); // might have several active requests for the same fullname + function processData(byteArray) { + function finish(byteArray) { + if (preFinish) preFinish(); + if (!dontCreateFile) { + FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); + } + if (onload) onload(); + removeRunDependency(dep); + } + if (FS_handledByPreloadPlugin(byteArray, fullname, finish, () => { + if (onerror) onerror(); + removeRunDependency(dep); + })) { + return; + } + finish(byteArray); + } + addRunDependency(dep); + if (typeof url == 'string') { + asyncLoad(url, (byteArray) => processData(byteArray), onerror); + } else { + processData(url); + } + } + + function FS_modeStringToFlags(str) { + var flagModes = { + 'r': 0, + 'r+': 2, + 'w': 512 | 64 | 1, + 'w+': 512 | 64 | 2, + 'a': 1024 | 64 | 1, + 'a+': 1024 | 64 | 2, + }; + var flags = flagModes[str]; + if (typeof flags == 'undefined') { + throw new Error(`Unknown file open mode: ${str}`); + } + return flags; + } + + function FS_getMode(canRead, canWrite) { + var mode = 0; + if (canRead) mode |= 292 | 73; + if (canWrite) mode |= 146; + return mode; + } + + + + + var ERRNO_MESSAGES = { + 0:"Success", + 1:"Arg list too long", + 2:"Permission denied", + 3:"Address already in use", + 4:"Address not available", + 5:"Address family not supported by protocol family", + 6:"No more processes", + 7:"Socket already connected", + 8:"Bad file number", + 9:"Trying to read unreadable message", + 10:"Mount device busy", + 11:"Operation canceled", + 12:"No children", + 13:"Connection aborted", + 14:"Connection refused", + 15:"Connection reset by peer", + 16:"File locking deadlock error", + 17:"Destination address required", + 18:"Math arg out of domain of func", + 19:"Quota exceeded", + 20:"File exists", + 21:"Bad address", + 22:"File too large", + 23:"Host is unreachable", + 24:"Identifier removed", + 25:"Illegal byte sequence", + 26:"Connection already in progress", + 27:"Interrupted system call", + 28:"Invalid argument", + 29:"I/O error", + 30:"Socket is already connected", + 31:"Is a directory", + 32:"Too many symbolic links", + 33:"Too many open files", + 34:"Too many links", + 35:"Message too long", + 36:"Multihop attempted", + 37:"File or path name too long", + 38:"Network interface is not configured", + 39:"Connection reset by network", + 40:"Network is unreachable", + 41:"Too many open files in system", + 42:"No buffer space available", + 43:"No such device", + 44:"No such file or directory", + 45:"Exec format error", + 46:"No record locks available", + 47:"The link has been severed", + 48:"Not enough core", + 49:"No message of desired type", + 50:"Protocol not available", + 51:"No space left on device", + 52:"Function not implemented", + 53:"Socket is not connected", + 54:"Not a directory", + 55:"Directory not empty", + 56:"State not recoverable", + 57:"Socket operation on non-socket", + 59:"Not a typewriter", + 60:"No such device or address", + 61:"Value too large for defined data type", + 62:"Previous owner died", + 63:"Not super-user", + 64:"Broken pipe", + 65:"Protocol error", + 66:"Unknown protocol", + 67:"Protocol wrong type for socket", + 68:"Math result not representable", + 69:"Read only file system", + 70:"Illegal seek", + 71:"No such process", + 72:"Stale file handle", + 73:"Connection timed out", + 74:"Text file busy", + 75:"Cross-device link", + 100:"Device not a stream", + 101:"Bad font file fmt", + 102:"Invalid slot", + 103:"Invalid request code", + 104:"No anode", + 105:"Block device required", + 106:"Channel number out of range", + 107:"Level 3 halted", + 108:"Level 3 reset", + 109:"Link number out of range", + 110:"Protocol driver not attached", + 111:"No CSI structure available", + 112:"Level 2 halted", + 113:"Invalid exchange", + 114:"Invalid request descriptor", + 115:"Exchange full", + 116:"No data (for no delay io)", + 117:"Timer expired", + 118:"Out of streams resources", + 119:"Machine is not on the network", + 120:"Package not installed", + 121:"The object is remote", + 122:"Advertise error", + 123:"Srmount error", + 124:"Communication error on send", + 125:"Cross mount point (not really error)", + 126:"Given log. name not unique", + 127:"f.d. invalid for this operation", + 128:"Remote address changed", + 129:"Can access a needed shared lib", + 130:"Accessing a corrupted shared lib", + 131:".lib section in a.out corrupted", + 132:"Attempting to link in too many libs", + 133:"Attempting to exec a shared library", + 135:"Streams pipe error", + 136:"Too many users", + 137:"Socket type not supported", + 138:"Not supported", + 139:"Protocol family not supported", + 140:"Can't send after socket shutdown", + 141:"Too many references", + 142:"Host is down", + 148:"No medium (in tape drive)", + 156:"Level 2 not synchronized", + }; + + var ERRNO_CODES = { + }; + + function demangle(func) { + warnOnce('warning: build with -sDEMANGLE_SUPPORT to link in libcxxabi demangling'); + return func; + } + function demangleAll(text) { + var regex = + /\b_Z[\w\d_]+/g; + return text.replace(regex, + function(x) { + var y = demangle(x); + return x === y ? x : (y + ' [' + x + ']'); + }); + } + var FS = { + root:null, + mounts:[], + devices:{ + }, + streams:[], + nextInode:1, + nameTable:null, + currentPath:"/", + initialized:false, + ignorePermissions:true, + ErrnoError:null, + genericErrors:{ + }, + filesystems:null, + syncFSRequests:0, + lookupPath:(path, opts = {}) => { + path = PATH_FS.resolve(path); + + if (!path) return { path: '', node: null }; + + var defaults = { + follow_mount: true, + recurse_count: 0 + }; + opts = Object.assign(defaults, opts) + + if (opts.recurse_count > 8) { // max recursive lookup of 8 + throw new FS.ErrnoError(32); + } + + // split the absolute path + var parts = path.split('/').filter((p) => !!p); + + // start at the root + var current = FS.root; + var current_path = '/'; + + for (var i = 0; i < parts.length; i++) { + var islast = (i === parts.length-1); + if (islast && opts.parent) { + // stop resolving + break; + } + + current = FS.lookupNode(current, parts[i]); + current_path = PATH.join2(current_path, parts[i]); + + // jump to the mount's root node if this is a mountpoint + if (FS.isMountpoint(current)) { + if (!islast || (islast && opts.follow_mount)) { + current = current.mounted.root; + } + } + + // by default, lookupPath will not follow a symlink if it is the final path component. + // setting opts.follow = true will override this behavior. + if (!islast || opts.follow) { + var count = 0; + while (FS.isLink(current.mode)) { + var link = FS.readlink(current_path); + current_path = PATH_FS.resolve(PATH.dirname(current_path), link); + + var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count + 1 }); + current = lookup.node; + + if (count++ > 40) { // limit max consecutive symlinks to 40 (SYMLOOP_MAX). + throw new FS.ErrnoError(32); + } + } + } + } + + return { path: current_path, node: current }; + }, + getPath:(node) => { + var path; + while (true) { + if (FS.isRoot(node)) { + var mount = node.mount.mountpoint; + if (!path) return mount; + return mount[mount.length-1] !== '/' ? `${mount}/${path}` : mount + path; + } + path = path ? `${node.name}/${path}` : node.name; + node = node.parent; + } + }, + hashName:(parentid, name) => { + var hash = 0; + + for (var i = 0; i < name.length; i++) { + hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0; + } + return ((parentid + hash) >>> 0) % FS.nameTable.length; + }, + hashAddNode:(node) => { + var hash = FS.hashName(node.parent.id, node.name); + node.name_next = FS.nameTable[hash]; + FS.nameTable[hash] = node; + }, + hashRemoveNode:(node) => { + var hash = FS.hashName(node.parent.id, node.name); + if (FS.nameTable[hash] === node) { + FS.nameTable[hash] = node.name_next; + } else { + var current = FS.nameTable[hash]; + while (current) { + if (current.name_next === node) { + current.name_next = node.name_next; + break; + } + current = current.name_next; + } + } + }, + lookupNode:(parent, name) => { + var errCode = FS.mayLookup(parent); + if (errCode) { + throw new FS.ErrnoError(errCode, parent); + } + var hash = FS.hashName(parent.id, name); + for (var node = FS.nameTable[hash]; node; node = node.name_next) { + var nodeName = node.name; + if (node.parent.id === parent.id && nodeName === name) { + return node; + } + } + // if we failed to find it in the cache, call into the VFS + return FS.lookup(parent, name); + }, + createNode:(parent, name, mode, rdev) => { + assert(typeof parent == 'object') + var node = new FS.FSNode(parent, name, mode, rdev); + + FS.hashAddNode(node); + + return node; + }, + destroyNode:(node) => { + FS.hashRemoveNode(node); + }, + isRoot:(node) => { + return node === node.parent; + }, + isMountpoint:(node) => { + return !!node.mounted; + }, + isFile:(mode) => { + return (mode & 61440) === 32768; + }, + isDir:(mode) => { + return (mode & 61440) === 16384; + }, + isLink:(mode) => { + return (mode & 61440) === 40960; + }, + isChrdev:(mode) => { + return (mode & 61440) === 8192; + }, + isBlkdev:(mode) => { + return (mode & 61440) === 24576; + }, + isFIFO:(mode) => { + return (mode & 61440) === 4096; + }, + isSocket:(mode) => { + return (mode & 49152) === 49152; + }, + flagsToPermissionString:(flag) => { + var perms = ['r', 'w', 'rw'][flag & 3]; + if ((flag & 512)) { + perms += 'w'; + } + return perms; + }, + nodePermissions:(node, perms) => { + if (FS.ignorePermissions) { + return 0; + } + // return 0 if any user, group or owner bits are set. + if (perms.includes('r') && !(node.mode & 292)) { + return 2; + } else if (perms.includes('w') && !(node.mode & 146)) { + return 2; + } else if (perms.includes('x') && !(node.mode & 73)) { + return 2; + } + return 0; + }, + mayLookup:(dir) => { + var errCode = FS.nodePermissions(dir, 'x'); + if (errCode) return errCode; + if (!dir.node_ops.lookup) return 2; + return 0; + }, + mayCreate:(dir, name) => { + try { + var node = FS.lookupNode(dir, name); + return 20; + } catch (e) { + } + return FS.nodePermissions(dir, 'wx'); + }, + mayDelete:(dir, name, isdir) => { + var node; + try { + node = FS.lookupNode(dir, name); + } catch (e) { + return e.errno; + } + var errCode = FS.nodePermissions(dir, 'wx'); + if (errCode) { + return errCode; + } + if (isdir) { + if (!FS.isDir(node.mode)) { + return 54; + } + if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) { + return 10; + } + } else { + if (FS.isDir(node.mode)) { + return 31; + } + } + return 0; + }, + mayOpen:(node, flags) => { + if (!node) { + return 44; + } + if (FS.isLink(node.mode)) { + return 32; + } else if (FS.isDir(node.mode)) { + if (FS.flagsToPermissionString(flags) !== 'r' || // opening for write + (flags & 512)) { // TODO: check for O_SEARCH? (== search for dir only) + return 31; + } + } + return FS.nodePermissions(node, FS.flagsToPermissionString(flags)); + }, + MAX_OPEN_FDS:4096, + nextfd:() => { + for (var fd = 0; fd <= FS.MAX_OPEN_FDS; fd++) { + if (!FS.streams[fd]) { + return fd; + } + } + throw new FS.ErrnoError(33); + }, + getStreamChecked:(fd) => { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(8); + } + return stream; + }, + getStream:(fd) => FS.streams[fd], + createStream:(stream, fd = -1) => { + if (!FS.FSStream) { + FS.FSStream = /** @constructor */ function() { + this.shared = { }; + }; + FS.FSStream.prototype = {}; + Object.defineProperties(FS.FSStream.prototype, { + object: { + /** @this {FS.FSStream} */ + get() { return this.node; }, + /** @this {FS.FSStream} */ + set(val) { this.node = val; } + }, + isRead: { + /** @this {FS.FSStream} */ + get() { return (this.flags & 2097155) !== 1; } + }, + isWrite: { + /** @this {FS.FSStream} */ + get() { return (this.flags & 2097155) !== 0; } + }, + isAppend: { + /** @this {FS.FSStream} */ + get() { return (this.flags & 1024); } + }, + flags: { + /** @this {FS.FSStream} */ + get() { return this.shared.flags; }, + /** @this {FS.FSStream} */ + set(val) { this.shared.flags = val; }, + }, + position : { + /** @this {FS.FSStream} */ + get() { return this.shared.position; }, + /** @this {FS.FSStream} */ + set(val) { this.shared.position = val; }, + }, + }); + } + // clone it, so we can return an instance of FSStream + stream = Object.assign(new FS.FSStream(), stream); + if (fd == -1) { + fd = FS.nextfd(); + } + stream.fd = fd; + FS.streams[fd] = stream; + return stream; + }, + closeStream:(fd) => { + FS.streams[fd] = null; + }, + chrdev_stream_ops:{ + open:(stream) => { + var device = FS.getDevice(stream.node.rdev); + // override node's stream ops with the device's + stream.stream_ops = device.stream_ops; + // forward the open call + if (stream.stream_ops.open) { + stream.stream_ops.open(stream); + } + }, + llseek:() => { + throw new FS.ErrnoError(70); + }, + }, + major:(dev) => ((dev) >> 8), + minor:(dev) => ((dev) & 0xff), + makedev:(ma, mi) => ((ma) << 8 | (mi)), + registerDevice:(dev, ops) => { + FS.devices[dev] = { stream_ops: ops }; + }, + getDevice:(dev) => FS.devices[dev], + getMounts:(mount) => { + var mounts = []; + var check = [mount]; + + while (check.length) { + var m = check.pop(); + + mounts.push(m); + + check.push.apply(check, m.mounts); + } + + return mounts; + }, + syncfs:(populate, callback) => { + if (typeof populate == 'function') { + callback = populate; + populate = false; + } + + FS.syncFSRequests++; + + if (FS.syncFSRequests > 1) { + err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`); + } + + var mounts = FS.getMounts(FS.root.mount); + var completed = 0; + + function doCallback(errCode) { + assert(FS.syncFSRequests > 0); + FS.syncFSRequests--; + return callback(errCode); + } + + function done(errCode) { + if (errCode) { + if (!done.errored) { + done.errored = true; + return doCallback(errCode); + } + return; + } + if (++completed >= mounts.length) { + doCallback(null); + } + }; + + // sync all mounts + mounts.forEach((mount) => { + if (!mount.type.syncfs) { + return done(null); + } + mount.type.syncfs(mount, populate, done); + }); + }, + mount:(type, opts, mountpoint) => { + if (typeof type == 'string') { + // The filesystem was not included, and instead we have an error + // message stored in the variable. + throw type; + } + var root = mountpoint === '/'; + var pseudo = !mountpoint; + var node; + + if (root && FS.root) { + throw new FS.ErrnoError(10); + } else if (!root && !pseudo) { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + mountpoint = lookup.path; // use the absolute path + node = lookup.node; + + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(10); + } + + if (!FS.isDir(node.mode)) { + throw new FS.ErrnoError(54); + } + } + + var mount = { + type, + opts, + mountpoint, + mounts: [] + }; + + // create a root node for the fs + var mountRoot = type.mount(mount); + mountRoot.mount = mount; + mount.root = mountRoot; + + if (root) { + FS.root = mountRoot; + } else if (node) { + // set as a mountpoint + node.mounted = mount; + + // add the new mount to the current mount's children + if (node.mount) { + node.mount.mounts.push(mount); + } + } + + return mountRoot; + }, + unmount:(mountpoint) => { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + if (!FS.isMountpoint(lookup.node)) { + throw new FS.ErrnoError(28); + } + + // destroy the nodes for this mount, and all its child mounts + var node = lookup.node; + var mount = node.mounted; + var mounts = FS.getMounts(mount); + + Object.keys(FS.nameTable).forEach((hash) => { + var current = FS.nameTable[hash]; + + while (current) { + var next = current.name_next; + + if (mounts.includes(current.mount)) { + FS.destroyNode(current); + } + + current = next; + } + }); + + // no longer a mountpoint + node.mounted = null; + + // remove this mount from the child mounts + var idx = node.mount.mounts.indexOf(mount); + assert(idx !== -1); + node.mount.mounts.splice(idx, 1); + }, + lookup:(parent, name) => { + return parent.node_ops.lookup(parent, name); + }, + mknod:(path, mode, dev) => { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + if (!name || name === '.' || name === '..') { + throw new FS.ErrnoError(28); + } + var errCode = FS.mayCreate(parent, name); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.mknod) { + throw new FS.ErrnoError(63); + } + return parent.node_ops.mknod(parent, name, mode, dev); + }, + create:(path, mode) => { + mode = mode !== undefined ? mode : 438 /* 0666 */; + mode &= 4095; + mode |= 32768; + return FS.mknod(path, mode, 0); + }, + mkdir:(path, mode) => { + mode = mode !== undefined ? mode : 511 /* 0777 */; + mode &= 511 | 512; + mode |= 16384; + return FS.mknod(path, mode, 0); + }, + mkdirTree:(path, mode) => { + var dirs = path.split('/'); + var d = ''; + for (var i = 0; i < dirs.length; ++i) { + if (!dirs[i]) continue; + d += '/' + dirs[i]; + try { + FS.mkdir(d, mode); + } catch(e) { + if (e.errno != 20) throw e; + } + } + }, + mkdev:(path, mode, dev) => { + if (typeof dev == 'undefined') { + dev = mode; + mode = 438 /* 0666 */; + } + mode |= 8192; + return FS.mknod(path, mode, dev); + }, + symlink:(oldpath, newpath) => { + if (!PATH_FS.resolve(oldpath)) { + throw new FS.ErrnoError(44); + } + var lookup = FS.lookupPath(newpath, { parent: true }); + var parent = lookup.node; + if (!parent) { + throw new FS.ErrnoError(44); + } + var newname = PATH.basename(newpath); + var errCode = FS.mayCreate(parent, newname); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.symlink) { + throw new FS.ErrnoError(63); + } + return parent.node_ops.symlink(parent, newname, oldpath); + }, + rename:(old_path, new_path) => { + var old_dirname = PATH.dirname(old_path); + var new_dirname = PATH.dirname(new_path); + var old_name = PATH.basename(old_path); + var new_name = PATH.basename(new_path); + // parents must exist + var lookup, old_dir, new_dir; + + // let the errors from non existant directories percolate up + lookup = FS.lookupPath(old_path, { parent: true }); + old_dir = lookup.node; + lookup = FS.lookupPath(new_path, { parent: true }); + new_dir = lookup.node; + + if (!old_dir || !new_dir) throw new FS.ErrnoError(44); + // need to be part of the same mount + if (old_dir.mount !== new_dir.mount) { + throw new FS.ErrnoError(75); + } + // source must exist + var old_node = FS.lookupNode(old_dir, old_name); + // old path should not be an ancestor of the new path + var relative = PATH_FS.relative(old_path, new_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(28); + } + // new path should not be an ancestor of the old path + relative = PATH_FS.relative(new_path, old_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(55); + } + // see if the new path already exists + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) { + // not fatal + } + // early out if nothing needs to change + if (old_node === new_node) { + return; + } + // we'll need to delete the old entry + var isdir = FS.isDir(old_node.mode); + var errCode = FS.mayDelete(old_dir, old_name, isdir); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + // need delete permissions if we'll be overwriting. + // need create permissions if new doesn't already exist. + errCode = new_node ? + FS.mayDelete(new_dir, new_name, isdir) : + FS.mayCreate(new_dir, new_name); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!old_dir.node_ops.rename) { + throw new FS.ErrnoError(63); + } + if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) { + throw new FS.ErrnoError(10); + } + // if we are going to change the parent, check write permissions + if (new_dir !== old_dir) { + errCode = FS.nodePermissions(old_dir, 'w'); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + } + // remove the node from the lookup hash + FS.hashRemoveNode(old_node); + // do the underlying fs rename + try { + old_dir.node_ops.rename(old_node, new_dir, new_name); + } catch (e) { + throw e; + } finally { + // add the node back to the hash (in case node_ops.rename + // changed its name) + FS.hashAddNode(old_node); + } + }, + rmdir:(path) => { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var errCode = FS.mayDelete(parent, name, true); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.rmdir) { + throw new FS.ErrnoError(63); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(10); + } + parent.node_ops.rmdir(parent, name); + FS.destroyNode(node); + }, + readdir:(path) => { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + if (!node.node_ops.readdir) { + throw new FS.ErrnoError(54); + } + return node.node_ops.readdir(node); + }, + unlink:(path) => { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + if (!parent) { + throw new FS.ErrnoError(44); + } + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var errCode = FS.mayDelete(parent, name, false); + if (errCode) { + // According to POSIX, we should map EISDIR to EPERM, but + // we instead do what Linux does (and we must, as we use + // the musl linux libc). + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.unlink) { + throw new FS.ErrnoError(63); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(10); + } + parent.node_ops.unlink(parent, name); + FS.destroyNode(node); + }, + readlink:(path) => { + var lookup = FS.lookupPath(path); + var link = lookup.node; + if (!link) { + throw new FS.ErrnoError(44); + } + if (!link.node_ops.readlink) { + throw new FS.ErrnoError(28); + } + return PATH_FS.resolve(FS.getPath(link.parent), link.node_ops.readlink(link)); + }, + stat:(path, dontFollow) => { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + var node = lookup.node; + if (!node) { + throw new FS.ErrnoError(44); + } + if (!node.node_ops.getattr) { + throw new FS.ErrnoError(63); + } + return node.node_ops.getattr(node); + }, + lstat:(path) => { + return FS.stat(path, true); + }, + chmod:(path, mode, dontFollow) => { + var node; + if (typeof path == 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(63); + } + node.node_ops.setattr(node, { + mode: (mode & 4095) | (node.mode & ~4095), + timestamp: Date.now() + }); + }, + lchmod:(path, mode) => { + FS.chmod(path, mode, true); + }, + fchmod:(fd, mode) => { + var stream = FS.getStreamChecked(fd); + FS.chmod(stream.node, mode); + }, + chown:(path, uid, gid, dontFollow) => { + var node; + if (typeof path == 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(63); + } + node.node_ops.setattr(node, { + timestamp: Date.now() + // we ignore the uid / gid for now + }); + }, + lchown:(path, uid, gid) => { + FS.chown(path, uid, gid, true); + }, + fchown:(fd, uid, gid) => { + var stream = FS.getStreamChecked(fd); + FS.chown(stream.node, uid, gid); + }, + truncate:(path, len) => { + if (len < 0) { + throw new FS.ErrnoError(28); + } + var node; + if (typeof path == 'string') { + var lookup = FS.lookupPath(path, { follow: true }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(63); + } + if (FS.isDir(node.mode)) { + throw new FS.ErrnoError(31); + } + if (!FS.isFile(node.mode)) { + throw new FS.ErrnoError(28); + } + var errCode = FS.nodePermissions(node, 'w'); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + node.node_ops.setattr(node, { + size: len, + timestamp: Date.now() + }); + }, + ftruncate:(fd, len) => { + var stream = FS.getStreamChecked(fd); + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(28); + } + FS.truncate(stream.node, len); + }, + utime:(path, atime, mtime) => { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + node.node_ops.setattr(node, { + timestamp: Math.max(atime, mtime) + }); + }, + open:(path, flags, mode) => { + if (path === "") { + throw new FS.ErrnoError(44); + } + flags = typeof flags == 'string' ? FS_modeStringToFlags(flags) : flags; + mode = typeof mode == 'undefined' ? 438 /* 0666 */ : mode; + if ((flags & 64)) { + mode = (mode & 4095) | 32768; + } else { + mode = 0; + } + var node; + if (typeof path == 'object') { + node = path; + } else { + path = PATH.normalize(path); + try { + var lookup = FS.lookupPath(path, { + follow: !(flags & 131072) + }); + node = lookup.node; + } catch (e) { + // ignore + } + } + // perhaps we need to create the node + var created = false; + if ((flags & 64)) { + if (node) { + // if O_CREAT and O_EXCL are set, error out if the node already exists + if ((flags & 128)) { + throw new FS.ErrnoError(20); + } + } else { + // node doesn't exist, try to create it + node = FS.mknod(path, mode, 0); + created = true; + } + } + if (!node) { + throw new FS.ErrnoError(44); + } + // can't truncate a device + if (FS.isChrdev(node.mode)) { + flags &= ~512; + } + // if asked only for a directory, then this must be one + if ((flags & 65536) && !FS.isDir(node.mode)) { + throw new FS.ErrnoError(54); + } + // check permissions, if this is not a file we just created now (it is ok to + // create and write to a file with read-only permissions; it is read-only + // for later use) + if (!created) { + var errCode = FS.mayOpen(node, flags); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + } + // do truncation if necessary + if ((flags & 512) && !created) { + FS.truncate(node, 0); + } + // we've already handled these, don't pass down to the underlying vfs + flags &= ~(128 | 512 | 131072); + + // register the stream with the filesystem + var stream = FS.createStream({ + node, + path: FS.getPath(node), // we want the absolute path to the node + flags, + seekable: true, + position: 0, + stream_ops: node.stream_ops, + // used by the file family libc calls (fopen, fwrite, ferror, etc.) + ungotten: [], + error: false + }); + // call the new stream's open function + if (stream.stream_ops.open) { + stream.stream_ops.open(stream); + } + if (Module['logReadFiles'] && !(flags & 1)) { + if (!FS.readFiles) FS.readFiles = {}; + if (!(path in FS.readFiles)) { + FS.readFiles[path] = 1; + } + } + return stream; + }, + close:(stream) => { + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if (stream.getdents) stream.getdents = null; // free readdir state + try { + if (stream.stream_ops.close) { + stream.stream_ops.close(stream); + } + } catch (e) { + throw e; + } finally { + FS.closeStream(stream.fd); + } + stream.fd = null; + }, + isClosed:(stream) => { + return stream.fd === null; + }, + llseek:(stream, offset, whence) => { + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if (!stream.seekable || !stream.stream_ops.llseek) { + throw new FS.ErrnoError(70); + } + if (whence != 0 && whence != 1 && whence != 2) { + throw new FS.ErrnoError(28); + } + stream.position = stream.stream_ops.llseek(stream, offset, whence); + stream.ungotten = []; + return stream.position; + }, + read:(stream, buffer, offset, length, position) => { + assert(offset >= 0); + if (length < 0 || position < 0) { + throw new FS.ErrnoError(28); + } + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(8); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(31); + } + if (!stream.stream_ops.read) { + throw new FS.ErrnoError(28); + } + var seeking = typeof position != 'undefined'; + if (!seeking) { + position = stream.position; + } else if (!stream.seekable) { + throw new FS.ErrnoError(70); + } + var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position); + if (!seeking) stream.position += bytesRead; + return bytesRead; + }, + write:(stream, buffer, offset, length, position, canOwn) => { + assert(offset >= 0); + if (length < 0 || position < 0) { + throw new FS.ErrnoError(28); + } + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(8); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(31); + } + if (!stream.stream_ops.write) { + throw new FS.ErrnoError(28); + } + if (stream.seekable && stream.flags & 1024) { + // seek to the end before writing in append mode + FS.llseek(stream, 0, 2); + } + var seeking = typeof position != 'undefined'; + if (!seeking) { + position = stream.position; + } else if (!stream.seekable) { + throw new FS.ErrnoError(70); + } + var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn); + if (!seeking) stream.position += bytesWritten; + return bytesWritten; + }, + allocate:(stream, offset, length) => { + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if (offset < 0 || length <= 0) { + throw new FS.ErrnoError(28); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(8); + } + if (!FS.isFile(stream.node.mode) && !FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(43); + } + if (!stream.stream_ops.allocate) { + throw new FS.ErrnoError(138); + } + stream.stream_ops.allocate(stream, offset, length); + }, + mmap:(stream, length, position, prot, flags) => { + // User requests writing to file (prot & PROT_WRITE != 0). + // Checking if we have permissions to write to the file unless + // MAP_PRIVATE flag is set. According to POSIX spec it is possible + // to write to file opened in read-only mode with MAP_PRIVATE flag, + // as all modifications will be visible only in the memory of + // the current process. + if ((prot & 2) !== 0 + && (flags & 2) === 0 + && (stream.flags & 2097155) !== 2) { + throw new FS.ErrnoError(2); + } + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(2); + } + if (!stream.stream_ops.mmap) { + throw new FS.ErrnoError(43); + } + return stream.stream_ops.mmap(stream, length, position, prot, flags); + }, + msync:(stream, buffer, offset, length, mmapFlags) => { + assert(offset >= 0); + if (!stream.stream_ops.msync) { + return 0; + } + return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags); + }, + munmap:(stream) => 0, + ioctl:(stream, cmd, arg) => { + if (!stream.stream_ops.ioctl) { + throw new FS.ErrnoError(59); + } + return stream.stream_ops.ioctl(stream, cmd, arg); + }, + readFile:(path, opts = {}) => { + opts.flags = opts.flags || 0; + opts.encoding = opts.encoding || 'binary'; + if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { + throw new Error(`Invalid encoding type "${opts.encoding}"`); + } + var ret; + var stream = FS.open(path, opts.flags); + var stat = FS.stat(path); + var length = stat.size; + var buf = new Uint8Array(length); + FS.read(stream, buf, 0, length, 0); + if (opts.encoding === 'utf8') { + ret = UTF8ArrayToString(buf, 0); + } else if (opts.encoding === 'binary') { + ret = buf; + } + FS.close(stream); + return ret; + }, + writeFile:(path, data, opts = {}) => { + opts.flags = opts.flags || 577; + var stream = FS.open(path, opts.flags, opts.mode); + if (typeof data == 'string') { + var buf = new Uint8Array(lengthBytesUTF8(data)+1); + var actualNumBytes = stringToUTF8Array(data, buf, 0, buf.length); + FS.write(stream, buf, 0, actualNumBytes, undefined, opts.canOwn); + } else if (ArrayBuffer.isView(data)) { + FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn); + } else { + throw new Error('Unsupported data type'); + } + FS.close(stream); + }, + cwd:() => FS.currentPath, + chdir:(path) => { + var lookup = FS.lookupPath(path, { follow: true }); + if (lookup.node === null) { + throw new FS.ErrnoError(44); + } + if (!FS.isDir(lookup.node.mode)) { + throw new FS.ErrnoError(54); + } + var errCode = FS.nodePermissions(lookup.node, 'x'); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + FS.currentPath = lookup.path; + }, + createDefaultDirectories:() => { + FS.mkdir('/tmp'); + FS.mkdir('/home'); + FS.mkdir('/home/web_user'); + }, + createDefaultDevices:() => { + // create /dev + FS.mkdir('/dev'); + // setup /dev/null + FS.registerDevice(FS.makedev(1, 3), { + read: () => 0, + write: (stream, buffer, offset, length, pos) => length, + }); + FS.mkdev('/dev/null', FS.makedev(1, 3)); + // setup /dev/tty and /dev/tty1 + // stderr needs to print output using err() rather than out() + // so we register a second tty just for it. + TTY.register(FS.makedev(5, 0), TTY.default_tty_ops); + TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops); + FS.mkdev('/dev/tty', FS.makedev(5, 0)); + FS.mkdev('/dev/tty1', FS.makedev(6, 0)); + // setup /dev/[u]random + // use a buffer to avoid overhead of individual crypto calls per byte + var randomBuffer = new Uint8Array(1024), randomLeft = 0; + var randomByte = () => { + if (randomLeft === 0) { + randomLeft = randomFill(randomBuffer).byteLength; + } + return randomBuffer[--randomLeft]; + }; + FS.createDevice('/dev', 'random', randomByte); + FS.createDevice('/dev', 'urandom', randomByte); + // we're not going to emulate the actual shm device, + // just create the tmp dirs that reside in it commonly + FS.mkdir('/dev/shm'); + FS.mkdir('/dev/shm/tmp'); + }, + createSpecialDirectories:() => { + // create /proc/self/fd which allows /proc/self/fd/6 => readlink gives the + // name of the stream for fd 6 (see test_unistd_ttyname) + FS.mkdir('/proc'); + var proc_self = FS.mkdir('/proc/self'); + FS.mkdir('/proc/self/fd'); + FS.mount({ + mount: () => { + var node = FS.createNode(proc_self, 'fd', 16384 | 511 /* 0777 */, 73); + node.node_ops = { + lookup: (parent, name) => { + var fd = +name; + var stream = FS.getStreamChecked(fd); + var ret = { + parent: null, + mount: { mountpoint: 'fake' }, + node_ops: { readlink: () => stream.path }, + }; + ret.parent = ret; // make it look like a simple root node + return ret; + } + }; + return node; + } + }, {}, '/proc/self/fd'); + }, + createStandardStreams:() => { + // TODO deprecate the old functionality of a single + // input / output callback and that utilizes FS.createDevice + // and instead require a unique set of stream ops + + // by default, we symlink the standard streams to the + // default tty devices. however, if the standard streams + // have been overwritten we create a unique device for + // them instead. + if (Module['stdin']) { + FS.createDevice('/dev', 'stdin', Module['stdin']); + } else { + FS.symlink('/dev/tty', '/dev/stdin'); + } + if (Module['stdout']) { + FS.createDevice('/dev', 'stdout', null, Module['stdout']); + } else { + FS.symlink('/dev/tty', '/dev/stdout'); + } + if (Module['stderr']) { + FS.createDevice('/dev', 'stderr', null, Module['stderr']); + } else { + FS.symlink('/dev/tty1', '/dev/stderr'); + } + + // open default streams for the stdin, stdout and stderr devices + var stdin = FS.open('/dev/stdin', 0); + var stdout = FS.open('/dev/stdout', 1); + var stderr = FS.open('/dev/stderr', 1); + assert(stdin.fd === 0, `invalid handle for stdin (${stdin.fd})`); + assert(stdout.fd === 1, `invalid handle for stdout (${stdout.fd})`); + assert(stderr.fd === 2, `invalid handle for stderr (${stderr.fd})`); + }, + ensureErrnoError:() => { + if (FS.ErrnoError) return; + FS.ErrnoError = /** @this{Object} */ function ErrnoError(errno, node) { + // We set the `name` property to be able to identify `FS.ErrnoError` + // - the `name` is a standard ECMA-262 property of error objects. Kind of good to have it anyway. + // - when using PROXYFS, an error can come from an underlying FS + // as different FS objects have their own FS.ErrnoError each, + // the test `err instanceof FS.ErrnoError` won't detect an error coming from another filesystem, causing bugs. + // we'll use the reliable test `err.name == "ErrnoError"` instead + this.name = 'ErrnoError'; + this.node = node; + this.setErrno = /** @this{Object} */ function(errno) { + this.errno = errno; + for (var key in ERRNO_CODES) { + if (ERRNO_CODES[key] === errno) { + this.code = key; + break; + } + } + }; + this.setErrno(errno); + this.message = ERRNO_MESSAGES[errno]; + + // Try to get a maximally helpful stack trace. On Node.js, getting Error.stack + // now ensures it shows what we want. + if (this.stack) { + // Define the stack property for Node.js 4, which otherwise errors on the next line. + Object.defineProperty(this, "stack", { value: (new Error).stack, writable: true }); + this.stack = demangleAll(this.stack); + } + }; + FS.ErrnoError.prototype = new Error(); + FS.ErrnoError.prototype.constructor = FS.ErrnoError; + // Some errors may happen quite a bit, to avoid overhead we reuse them (and suffer a lack of stack info) + [44].forEach((code) => { + FS.genericErrors[code] = new FS.ErrnoError(code); + FS.genericErrors[code].stack = ''; + }); + }, + staticInit:() => { + FS.ensureErrnoError(); + + FS.nameTable = new Array(4096); + + FS.mount(MEMFS, {}, '/'); + + FS.createDefaultDirectories(); + FS.createDefaultDevices(); + FS.createSpecialDirectories(); + + FS.filesystems = { + 'MEMFS': MEMFS, + }; + }, + init:(input, output, error) => { + assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)'); + FS.init.initialized = true; + + FS.ensureErrnoError(); + + // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here + Module['stdin'] = input || Module['stdin']; + Module['stdout'] = output || Module['stdout']; + Module['stderr'] = error || Module['stderr']; + + FS.createStandardStreams(); + }, + quit:() => { + FS.init.initialized = false; + // force-flush all streams, so we get musl std streams printed out + _fflush(0); + // close all of our streams + for (var i = 0; i < FS.streams.length; i++) { + var stream = FS.streams[i]; + if (!stream) { + continue; + } + FS.close(stream); + } + }, + findObject:(path, dontResolveLastLink) => { + var ret = FS.analyzePath(path, dontResolveLastLink); + if (!ret.exists) { + return null; + } + return ret.object; + }, + analyzePath:(path, dontResolveLastLink) => { + // operate from within the context of the symlink's target + try { + var lookup = FS.lookupPath(path, { follow: !dontResolveLastLink }); + path = lookup.path; + } catch (e) { + } + var ret = { + isRoot: false, exists: false, error: 0, name: null, path: null, object: null, + parentExists: false, parentPath: null, parentObject: null + }; + try { + var lookup = FS.lookupPath(path, { parent: true }); + ret.parentExists = true; + ret.parentPath = lookup.path; + ret.parentObject = lookup.node; + ret.name = PATH.basename(path); + lookup = FS.lookupPath(path, { follow: !dontResolveLastLink }); + ret.exists = true; + ret.path = lookup.path; + ret.object = lookup.node; + ret.name = lookup.node.name; + ret.isRoot = lookup.path === '/'; + } catch (e) { + ret.error = e.errno; + }; + return ret; + }, + createPath:(parent, path, canRead, canWrite) => { + parent = typeof parent == 'string' ? parent : FS.getPath(parent); + var parts = path.split('/').reverse(); + while (parts.length) { + var part = parts.pop(); + if (!part) continue; + var current = PATH.join2(parent, part); + try { + FS.mkdir(current); + } catch (e) { + // ignore EEXIST + } + parent = current; + } + return current; + }, + createFile:(parent, name, properties, canRead, canWrite) => { + var path = PATH.join2(typeof parent == 'string' ? parent : FS.getPath(parent), name); + var mode = FS_getMode(canRead, canWrite); + return FS.create(path, mode); + }, + createDataFile:(parent, name, data, canRead, canWrite, canOwn) => { + var path = name; + if (parent) { + parent = typeof parent == 'string' ? parent : FS.getPath(parent); + path = name ? PATH.join2(parent, name) : parent; + } + var mode = FS_getMode(canRead, canWrite); + var node = FS.create(path, mode); + if (data) { + if (typeof data == 'string') { + var arr = new Array(data.length); + for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i); + data = arr; + } + // make sure we can write to the file + FS.chmod(node, mode | 146); + var stream = FS.open(node, 577); + FS.write(stream, data, 0, data.length, 0, canOwn); + FS.close(stream); + FS.chmod(node, mode); + } + return node; + }, + createDevice:(parent, name, input, output) => { + var path = PATH.join2(typeof parent == 'string' ? parent : FS.getPath(parent), name); + var mode = FS_getMode(!!input, !!output); + if (!FS.createDevice.major) FS.createDevice.major = 64; + var dev = FS.makedev(FS.createDevice.major++, 0); + // Create a fake device that a set of stream ops to emulate + // the old behavior. + FS.registerDevice(dev, { + open: (stream) => { + stream.seekable = false; + }, + close: (stream) => { + // flush any pending line data + if (output && output.buffer && output.buffer.length) { + output(10); + } + }, + read: (stream, buffer, offset, length, pos /* ignored */) => { + var bytesRead = 0; + for (var i = 0; i < length; i++) { + var result; + try { + result = input(); + } catch (e) { + throw new FS.ErrnoError(29); + } + if (result === undefined && bytesRead === 0) { + throw new FS.ErrnoError(6); + } + if (result === null || result === undefined) break; + bytesRead++; + buffer[offset+i] = result; + } + if (bytesRead) { + stream.node.timestamp = Date.now(); + } + return bytesRead; + }, + write: (stream, buffer, offset, length, pos) => { + for (var i = 0; i < length; i++) { + try { + output(buffer[offset+i]); + } catch (e) { + throw new FS.ErrnoError(29); + } + } + if (length) { + stream.node.timestamp = Date.now(); + } + return i; + } + }); + return FS.mkdev(path, mode, dev); + }, + forceLoadFile:(obj) => { + if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true; + if (typeof XMLHttpRequest != 'undefined') { + throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread."); + } else if (read_) { + // Command-line. + try { + // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as + // read() will try to parse UTF8. + obj.contents = intArrayFromString(read_(obj.url), true); + obj.usedBytes = obj.contents.length; + } catch (e) { + throw new FS.ErrnoError(29); + } + } else { + throw new Error('Cannot load without read() or XMLHttpRequest.'); + } + }, + createLazyFile:(parent, name, url, canRead, canWrite) => { + // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse. + /** @constructor */ + function LazyUint8Array() { + this.lengthKnown = false; + this.chunks = []; // Loaded chunks. Index is the chunk number + } + LazyUint8Array.prototype.get = /** @this{Object} */ function LazyUint8Array_get(idx) { + if (idx > this.length-1 || idx < 0) { + return undefined; + } + var chunkOffset = idx % this.chunkSize; + var chunkNum = (idx / this.chunkSize)|0; + return this.getter(chunkNum)[chunkOffset]; + }; + LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) { + this.getter = getter; + }; + LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() { + // Find length + var xhr = new XMLHttpRequest(); + xhr.open('HEAD', url, false); + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + var datalength = Number(xhr.getResponseHeader("Content-length")); + var header; + var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes"; + var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip"; + + var chunkSize = 1024*1024; // Chunk size in bytes + + if (!hasByteServing) chunkSize = datalength; + + // Function to get a range from the remote URL. + var doXHR = (from, to) => { + if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!"); + if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); + + // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); + + // Some hints to the browser that we want binary data. + xhr.responseType = 'arraybuffer'; + if (xhr.overrideMimeType) { + xhr.overrideMimeType('text/plain; charset=x-user-defined'); + } + + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + if (xhr.response !== undefined) { + return new Uint8Array(/** @type{Array} */(xhr.response || [])); + } + return intArrayFromString(xhr.responseText || '', true); + }; + var lazyArray = this; + lazyArray.setDataGetter((chunkNum) => { + var start = chunkNum * chunkSize; + var end = (chunkNum+1) * chunkSize - 1; // including this byte + end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block + if (typeof lazyArray.chunks[chunkNum] == 'undefined') { + lazyArray.chunks[chunkNum] = doXHR(start, end); + } + if (typeof lazyArray.chunks[chunkNum] == 'undefined') throw new Error('doXHR failed!'); + return lazyArray.chunks[chunkNum]; + }); + + if (usesGzip || !datalength) { + // if the server uses gzip or doesn't supply the length, we have to download the whole file to get the (uncompressed) length + chunkSize = datalength = 1; // this will force getter(0)/doXHR do download the whole file + datalength = this.getter(0).length; + chunkSize = datalength; + out("LazyFiles on gzip forces download of the whole file when length is accessed"); + } + + this._length = datalength; + this._chunkSize = chunkSize; + this.lengthKnown = true; + }; + if (typeof XMLHttpRequest != 'undefined') { + if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc'; + var lazyArray = new LazyUint8Array(); + Object.defineProperties(lazyArray, { + length: { + get: /** @this{Object} */ function() { + if (!this.lengthKnown) { + this.cacheLength(); + } + return this._length; + } + }, + chunkSize: { + get: /** @this{Object} */ function() { + if (!this.lengthKnown) { + this.cacheLength(); + } + return this._chunkSize; + } + } + }); + + var properties = { isDevice: false, contents: lazyArray }; + } else { + var properties = { isDevice: false, url: url }; + } + + var node = FS.createFile(parent, name, properties, canRead, canWrite); + // This is a total hack, but I want to get this lazy file code out of the + // core of MEMFS. If we want to keep this lazy file concept I feel it should + // be its own thin LAZYFS proxying calls to MEMFS. + if (properties.contents) { + node.contents = properties.contents; + } else if (properties.url) { + node.contents = null; + node.url = properties.url; + } + // Add a function that defers querying the file size until it is asked the first time. + Object.defineProperties(node, { + usedBytes: { + get: /** @this {FSNode} */ function() { return this.contents.length; } + } + }); + // override each stream op with one that tries to force load the lazy file first + var stream_ops = {}; + var keys = Object.keys(node.stream_ops); + keys.forEach((key) => { + var fn = node.stream_ops[key]; + stream_ops[key] = function forceLoadLazyFile() { + FS.forceLoadFile(node); + return fn.apply(null, arguments); + }; + }); + function writeChunks(stream, buffer, offset, length, position) { + var contents = stream.node.contents; + if (position >= contents.length) + return 0; + var size = Math.min(contents.length - position, length); + assert(size >= 0); + if (contents.slice) { // normal array + for (var i = 0; i < size; i++) { + buffer[offset + i] = contents[position + i]; + } + } else { + for (var i = 0; i < size; i++) { // LazyUint8Array from sync binary XHR + buffer[offset + i] = contents.get(position + i); + } + } + return size; + } + // use a custom read function + stream_ops.read = (stream, buffer, offset, length, position) => { + FS.forceLoadFile(node); + return writeChunks(stream, buffer, offset, length, position) + }; + // use a custom mmap function + stream_ops.mmap = (stream, length, position, prot, flags) => { + FS.forceLoadFile(node); + var ptr = mmapAlloc(length); + if (!ptr) { + throw new FS.ErrnoError(48); + } + writeChunks(stream, HEAP8, ptr, length, position); + return { ptr, allocated: true }; + }; + node.stream_ops = stream_ops; + return node; + }, + absolutePath:() => { + abort('FS.absolutePath has been removed; use PATH_FS.resolve instead'); + }, + createFolder:() => { + abort('FS.createFolder has been removed; use FS.mkdir instead'); + }, + createLink:() => { + abort('FS.createLink has been removed; use FS.symlink instead'); + }, + joinPath:() => { + abort('FS.joinPath has been removed; use PATH.join instead'); + }, + mmapAlloc:() => { + abort('FS.mmapAlloc has been replaced by the top level function mmapAlloc'); + }, + standardizePath:() => { + abort('FS.standardizePath has been removed; use PATH.normalize instead'); + }, + }; + + var SYSCALLS = { + DEFAULT_POLLMASK:5, + calculateAt:function(dirfd, path, allowEmpty) { + if (PATH.isAbs(path)) { + return path; + } + // relative path + var dir; + if (dirfd === -100) { + dir = FS.cwd(); + } else { + var dirstream = SYSCALLS.getStreamFromFD(dirfd); + dir = dirstream.path; + } + if (path.length == 0) { + if (!allowEmpty) { + throw new FS.ErrnoError(44);; + } + return dir; + } + return PATH.join2(dir, path); + }, + doStat:function(func, path, buf) { + try { + var stat = func(path); + } catch (e) { + if (e && e.node && PATH.normalize(path) !== PATH.normalize(FS.getPath(e.node))) { + // an error occurred while trying to look up the path; we should just report ENOTDIR + return -54; + } + throw e; + } + HEAP32[((buf)>>2)] = stat.dev; + HEAP32[(((buf)+(4))>>2)] = stat.mode; + HEAPU32[(((buf)+(8))>>2)] = stat.nlink; + HEAP32[(((buf)+(12))>>2)] = stat.uid; + HEAP32[(((buf)+(16))>>2)] = stat.gid; + HEAP32[(((buf)+(20))>>2)] = stat.rdev; + (tempI64 = [stat.size>>>0,(tempDouble=stat.size,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(24))>>2)] = tempI64[0],HEAP32[(((buf)+(28))>>2)] = tempI64[1]); + HEAP32[(((buf)+(32))>>2)] = 4096; + HEAP32[(((buf)+(36))>>2)] = stat.blocks; + var atime = stat.atime.getTime(); + var mtime = stat.mtime.getTime(); + var ctime = stat.ctime.getTime(); + (tempI64 = [Math.floor(atime / 1000)>>>0,(tempDouble=Math.floor(atime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(40))>>2)] = tempI64[0],HEAP32[(((buf)+(44))>>2)] = tempI64[1]); + HEAPU32[(((buf)+(48))>>2)] = (atime % 1000) * 1000; + (tempI64 = [Math.floor(mtime / 1000)>>>0,(tempDouble=Math.floor(mtime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(56))>>2)] = tempI64[0],HEAP32[(((buf)+(60))>>2)] = tempI64[1]); + HEAPU32[(((buf)+(64))>>2)] = (mtime % 1000) * 1000; + (tempI64 = [Math.floor(ctime / 1000)>>>0,(tempDouble=Math.floor(ctime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(72))>>2)] = tempI64[0],HEAP32[(((buf)+(76))>>2)] = tempI64[1]); + HEAPU32[(((buf)+(80))>>2)] = (ctime % 1000) * 1000; + (tempI64 = [stat.ino>>>0,(tempDouble=stat.ino,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(88))>>2)] = tempI64[0],HEAP32[(((buf)+(92))>>2)] = tempI64[1]); + return 0; + }, + doMsync:function(addr, stream, len, flags, offset) { + if (!FS.isFile(stream.node.mode)) { + throw new FS.ErrnoError(43); + } + if (flags & 2) { + // MAP_PRIVATE calls need not to be synced back to underlying fs + return 0; + } + var buffer = HEAPU8.slice(addr, addr + len); + FS.msync(stream, buffer, offset, len, flags); + }, + varargs:undefined, + get() { + assert(SYSCALLS.varargs != undefined); + SYSCALLS.varargs += 4; + var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)]; + return ret; + }, + getStr(ptr) { + var ret = UTF8ToString(ptr); + return ret; + }, + getStreamFromFD:function(fd) { + var stream = FS.getStreamChecked(fd); + return stream; + }, + }; + var _environ_get = (__environ, environ_buf) => { + var bufSize = 0; + getEnvStrings().forEach(function(string, i) { + var ptr = environ_buf + bufSize; + HEAPU32[(((__environ)+(i*4))>>2)] = ptr; + stringToAscii(string, ptr); + bufSize += string.length + 1; + }); + return 0; + }; + + + var _environ_sizes_get = (penviron_count, penviron_buf_size) => { + var strings = getEnvStrings(); + HEAPU32[((penviron_count)>>2)] = strings.length; + var bufSize = 0; + strings.forEach(function(string) { + bufSize += string.length + 1; + }); + HEAPU32[((penviron_buf_size)>>2)] = bufSize; + return 0; + }; + + function _fd_close(fd) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + FS.close(stream); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + } + + /** @param {number=} offset */ + var doReadv = (stream, iov, iovcnt, offset) => { + var ret = 0; + for (var i = 0; i < iovcnt; i++) { + var ptr = HEAPU32[((iov)>>2)]; + var len = HEAPU32[(((iov)+(4))>>2)]; + iov += 8; + var curr = FS.read(stream, HEAP8,ptr, len, offset); + if (curr < 0) return -1; + ret += curr; + if (curr < len) break; // nothing more to read + if (typeof offset !== 'undefined') { + offset += curr; + } + } + return ret; + }; + + function _fd_read(fd, iov, iovcnt, pnum) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + var num = doReadv(stream, iov, iovcnt); + HEAPU32[((pnum)>>2)] = num; + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + } + + + function convertI32PairToI53Checked(lo, hi) { + assert(lo == (lo >>> 0) || lo == (lo|0)); // lo should either be a i32 or a u32 + assert(hi === (hi|0)); // hi should be a i32 + return ((hi + 0x200000) >>> 0 < 0x400001 - !!lo) ? (lo >>> 0) + hi * 4294967296 : NaN; + } + function _fd_seek(fd,offset_low, offset_high,whence,newOffset) { + var offset = convertI32PairToI53Checked(offset_low, offset_high);; + + + try { + + if (isNaN(offset)) return 61; + var stream = SYSCALLS.getStreamFromFD(fd); + FS.llseek(stream, offset, whence); + (tempI64 = [stream.position>>>0,(tempDouble=stream.position,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[((newOffset)>>2)] = tempI64[0],HEAP32[(((newOffset)+(4))>>2)] = tempI64[1]); + if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; // reset readdir state + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + ; + } + + /** @param {number=} offset */ + var doWritev = (stream, iov, iovcnt, offset) => { + var ret = 0; + for (var i = 0; i < iovcnt; i++) { + var ptr = HEAPU32[((iov)>>2)]; + var len = HEAPU32[(((iov)+(4))>>2)]; + iov += 8; + var curr = FS.write(stream, HEAP8,ptr, len, offset); + if (curr < 0) return -1; + ret += curr; + if (typeof offset !== 'undefined') { + offset += curr; + } + } + return ret; + }; + + function _fd_write(fd, iov, iovcnt, pnum) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + var num = doWritev(stream, iov, iovcnt); + HEAPU32[((pnum)>>2)] = num; + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + } + + var isLeapYear = (year) => { + return year%4 === 0 && (year%100 !== 0 || year%400 === 0); + }; + + var arraySum = (array, index) => { + var sum = 0; + for (var i = 0; i <= index; sum += array[i++]) { + // no-op + } + return sum; + }; + + + var MONTH_DAYS_LEAP = [31,29,31,30,31,30,31,31,30,31,30,31]; + + var MONTH_DAYS_REGULAR = [31,28,31,30,31,30,31,31,30,31,30,31]; + var addDays = (date, days) => { + var newDate = new Date(date.getTime()); + while (days > 0) { + var leap = isLeapYear(newDate.getFullYear()); + var currentMonth = newDate.getMonth(); + var daysInCurrentMonth = (leap ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR)[currentMonth]; + + if (days > daysInCurrentMonth-newDate.getDate()) { + // we spill over to next month + days -= (daysInCurrentMonth-newDate.getDate()+1); + newDate.setDate(1); + if (currentMonth < 11) { + newDate.setMonth(currentMonth+1) + } else { + newDate.setMonth(0); + newDate.setFullYear(newDate.getFullYear()+1); + } + } else { + // we stay in current month + newDate.setDate(newDate.getDate()+days); + return newDate; + } + } + + return newDate; + }; + + + + + var writeArrayToMemory = (array, buffer) => { + assert(array.length >= 0, 'writeArrayToMemory array must have a length (should be an array or typed array)') + HEAP8.set(array, buffer); + }; + + var _strftime = (s, maxsize, format, tm) => { + // size_t strftime(char *restrict s, size_t maxsize, const char *restrict format, const struct tm *restrict timeptr); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html + + var tm_zone = HEAP32[(((tm)+(40))>>2)]; + + var date = { + tm_sec: HEAP32[((tm)>>2)], + tm_min: HEAP32[(((tm)+(4))>>2)], + tm_hour: HEAP32[(((tm)+(8))>>2)], + tm_mday: HEAP32[(((tm)+(12))>>2)], + tm_mon: HEAP32[(((tm)+(16))>>2)], + tm_year: HEAP32[(((tm)+(20))>>2)], + tm_wday: HEAP32[(((tm)+(24))>>2)], + tm_yday: HEAP32[(((tm)+(28))>>2)], + tm_isdst: HEAP32[(((tm)+(32))>>2)], + tm_gmtoff: HEAP32[(((tm)+(36))>>2)], + tm_zone: tm_zone ? UTF8ToString(tm_zone) : '' + }; + + var pattern = UTF8ToString(format); + + // expand format + var EXPANSION_RULES_1 = { + '%c': '%a %b %d %H:%M:%S %Y', // Replaced by the locale's appropriate date and time representation - e.g., Mon Aug 3 14:02:01 2013 + '%D': '%m/%d/%y', // Equivalent to %m / %d / %y + '%F': '%Y-%m-%d', // Equivalent to %Y - %m - %d + '%h': '%b', // Equivalent to %b + '%r': '%I:%M:%S %p', // Replaced by the time in a.m. and p.m. notation + '%R': '%H:%M', // Replaced by the time in 24-hour notation + '%T': '%H:%M:%S', // Replaced by the time + '%x': '%m/%d/%y', // Replaced by the locale's appropriate date representation + '%X': '%H:%M:%S', // Replaced by the locale's appropriate time representation + // Modified Conversion Specifiers + '%Ec': '%c', // Replaced by the locale's alternative appropriate date and time representation. + '%EC': '%C', // Replaced by the name of the base year (period) in the locale's alternative representation. + '%Ex': '%m/%d/%y', // Replaced by the locale's alternative date representation. + '%EX': '%H:%M:%S', // Replaced by the locale's alternative time representation. + '%Ey': '%y', // Replaced by the offset from %EC (year only) in the locale's alternative representation. + '%EY': '%Y', // Replaced by the full alternative year representation. + '%Od': '%d', // Replaced by the day of the month, using the locale's alternative numeric symbols, filled as needed with leading zeros if there is any alternative symbol for zero; otherwise, with leading characters. + '%Oe': '%e', // Replaced by the day of the month, using the locale's alternative numeric symbols, filled as needed with leading characters. + '%OH': '%H', // Replaced by the hour (24-hour clock) using the locale's alternative numeric symbols. + '%OI': '%I', // Replaced by the hour (12-hour clock) using the locale's alternative numeric symbols. + '%Om': '%m', // Replaced by the month using the locale's alternative numeric symbols. + '%OM': '%M', // Replaced by the minutes using the locale's alternative numeric symbols. + '%OS': '%S', // Replaced by the seconds using the locale's alternative numeric symbols. + '%Ou': '%u', // Replaced by the weekday as a number in the locale's alternative representation (Monday=1). + '%OU': '%U', // Replaced by the week number of the year (Sunday as the first day of the week, rules corresponding to %U ) using the locale's alternative numeric symbols. + '%OV': '%V', // Replaced by the week number of the year (Monday as the first day of the week, rules corresponding to %V ) using the locale's alternative numeric symbols. + '%Ow': '%w', // Replaced by the number of the weekday (Sunday=0) using the locale's alternative numeric symbols. + '%OW': '%W', // Replaced by the week number of the year (Monday as the first day of the week) using the locale's alternative numeric symbols. + '%Oy': '%y', // Replaced by the year (offset from %C ) using the locale's alternative numeric symbols. + }; + for (var rule in EXPANSION_RULES_1) { + pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_1[rule]); + } + + var WEEKDAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; + var MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + + function leadingSomething(value, digits, character) { + var str = typeof value == 'number' ? value.toString() : (value || ''); + while (str.length < digits) { + str = character[0]+str; + } + return str; + } + + function leadingNulls(value, digits) { + return leadingSomething(value, digits, '0'); + } + + function compareByDay(date1, date2) { + function sgn(value) { + return value < 0 ? -1 : (value > 0 ? 1 : 0); + } + + var compare; + if ((compare = sgn(date1.getFullYear()-date2.getFullYear())) === 0) { + if ((compare = sgn(date1.getMonth()-date2.getMonth())) === 0) { + compare = sgn(date1.getDate()-date2.getDate()); + } + } + return compare; + } + + function getFirstWeekStartDate(janFourth) { + switch (janFourth.getDay()) { + case 0: // Sunday + return new Date(janFourth.getFullYear()-1, 11, 29); + case 1: // Monday + return janFourth; + case 2: // Tuesday + return new Date(janFourth.getFullYear(), 0, 3); + case 3: // Wednesday + return new Date(janFourth.getFullYear(), 0, 2); + case 4: // Thursday + return new Date(janFourth.getFullYear(), 0, 1); + case 5: // Friday + return new Date(janFourth.getFullYear()-1, 11, 31); + case 6: // Saturday + return new Date(janFourth.getFullYear()-1, 11, 30); + } + } + + function getWeekBasedYear(date) { + var thisDate = addDays(new Date(date.tm_year+1900, 0, 1), date.tm_yday); + + var janFourthThisYear = new Date(thisDate.getFullYear(), 0, 4); + var janFourthNextYear = new Date(thisDate.getFullYear()+1, 0, 4); + + var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear); + var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear); + + if (compareByDay(firstWeekStartThisYear, thisDate) <= 0) { + // this date is after the start of the first week of this year + if (compareByDay(firstWeekStartNextYear, thisDate) <= 0) { + return thisDate.getFullYear()+1; + } + return thisDate.getFullYear(); + } + return thisDate.getFullYear()-1; + } + + var EXPANSION_RULES_2 = { + '%a': (date) => WEEKDAYS[date.tm_wday].substring(0,3) , + '%A': (date) => WEEKDAYS[date.tm_wday], + '%b': (date) => MONTHS[date.tm_mon].substring(0,3), + '%B': (date) => MONTHS[date.tm_mon], + '%C': (date) => { + var year = date.tm_year+1900; + return leadingNulls((year/100)|0,2); + }, + '%d': (date) => leadingNulls(date.tm_mday, 2), + '%e': (date) => leadingSomething(date.tm_mday, 2, ' '), + '%g': (date) => { + // %g, %G, and %V give values according to the ISO 8601:2000 standard week-based year. + // In this system, weeks begin on a Monday and week 1 of the year is the week that includes + // January 4th, which is also the week that includes the first Thursday of the year, and + // is also the first week that contains at least four days in the year. + // If the first Monday of January is the 2nd, 3rd, or 4th, the preceding days are part of + // the last week of the preceding year; thus, for Saturday 2nd January 1999, + // %G is replaced by 1998 and %V is replaced by 53. If December 29th, 30th, + // or 31st is a Monday, it and any following days are part of week 1 of the following year. + // Thus, for Tuesday 30th December 1997, %G is replaced by 1998 and %V is replaced by 01. + + return getWeekBasedYear(date).toString().substring(2); + }, + '%G': (date) => getWeekBasedYear(date), + '%H': (date) => leadingNulls(date.tm_hour, 2), + '%I': (date) => { + var twelveHour = date.tm_hour; + if (twelveHour == 0) twelveHour = 12; + else if (twelveHour > 12) twelveHour -= 12; + return leadingNulls(twelveHour, 2); + }, + '%j': (date) => { + // Day of the year (001-366) + return leadingNulls(date.tm_mday + arraySum(isLeapYear(date.tm_year+1900) ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, date.tm_mon-1), 3); + }, + '%m': (date) => leadingNulls(date.tm_mon+1, 2), + '%M': (date) => leadingNulls(date.tm_min, 2), + '%n': () => '\n', + '%p': (date) => { + if (date.tm_hour >= 0 && date.tm_hour < 12) { + return 'AM'; + } + return 'PM'; + }, + '%S': (date) => leadingNulls(date.tm_sec, 2), + '%t': () => '\t', + '%u': (date) => date.tm_wday || 7, + '%U': (date) => { + var days = date.tm_yday + 7 - date.tm_wday; + return leadingNulls(Math.floor(days / 7), 2); + }, + '%V': (date) => { + // Replaced by the week number of the year (Monday as the first day of the week) + // as a decimal number [01,53]. If the week containing 1 January has four + // or more days in the new year, then it is considered week 1. + // Otherwise, it is the last week of the previous year, and the next week is week 1. + // Both January 4th and the first Thursday of January are always in week 1. [ tm_year, tm_wday, tm_yday] + var val = Math.floor((date.tm_yday + 7 - (date.tm_wday + 6) % 7 ) / 7); + // If 1 Jan is just 1-3 days past Monday, the previous week + // is also in this year. + if ((date.tm_wday + 371 - date.tm_yday - 2) % 7 <= 2) { + val++; + } + if (!val) { + val = 52; + // If 31 December of prev year a Thursday, or Friday of a + // leap year, then the prev year has 53 weeks. + var dec31 = (date.tm_wday + 7 - date.tm_yday - 1) % 7; + if (dec31 == 4 || (dec31 == 5 && isLeapYear(date.tm_year%400-1))) { + val++; + } + } else if (val == 53) { + // If 1 January is not a Thursday, and not a Wednesday of a + // leap year, then this year has only 52 weeks. + var jan1 = (date.tm_wday + 371 - date.tm_yday) % 7; + if (jan1 != 4 && (jan1 != 3 || !isLeapYear(date.tm_year))) + val = 1; + } + return leadingNulls(val, 2); + }, + '%w': (date) => date.tm_wday, + '%W': (date) => { + var days = date.tm_yday + 7 - ((date.tm_wday + 6) % 7); + return leadingNulls(Math.floor(days / 7), 2); + }, + '%y': (date) => { + // Replaced by the last two digits of the year as a decimal number [00,99]. [ tm_year] + return (date.tm_year+1900).toString().substring(2); + }, + // Replaced by the year as a decimal number (for example, 1997). [ tm_year] + '%Y': (date) => date.tm_year+1900, + '%z': (date) => { + // Replaced by the offset from UTC in the ISO 8601:2000 standard format ( +hhmm or -hhmm ). + // For example, "-0430" means 4 hours 30 minutes behind UTC (west of Greenwich). + var off = date.tm_gmtoff; + var ahead = off >= 0; + off = Math.abs(off) / 60; + // convert from minutes into hhmm format (which means 60 minutes = 100 units) + off = (off / 60)*100 + (off % 60); + return (ahead ? '+' : '-') + String("0000" + off).slice(-4); + }, + '%Z': (date) => date.tm_zone, + '%%': () => '%' + }; + + // Replace %% with a pair of NULLs (which cannot occur in a C string), then + // re-inject them after processing. + pattern = pattern.replace(/%%/g, '\0\0') + for (var rule in EXPANSION_RULES_2) { + if (pattern.includes(rule)) { + pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_2[rule](date)); + } + } + pattern = pattern.replace(/\0\0/g, '%') + + var bytes = intArrayFromString(pattern, false); + if (bytes.length > maxsize) { + return 0; + } + + writeArrayToMemory(bytes, s); + return bytes.length-1; + }; + var _strftime_l = (s, maxsize, format, tm, loc) => { + return _strftime(s, maxsize, format, tm); // no locale support yet + }; +handleAllocatorInit(); +BindingError = Module['BindingError'] = class BindingError extends Error { constructor(message) { super(message); this.name = 'BindingError'; }}; +init_emval();; +PureVirtualError = Module['PureVirtualError'] = extendError(Error, 'PureVirtualError');; +embind_init_charCodes(); +init_embind();; +InternalError = Module['InternalError'] = class InternalError extends Error { constructor(message) { super(message); this.name = 'InternalError'; }}; +init_ClassHandle(); +init_RegisteredPointer(); +UnboundTypeError = Module['UnboundTypeError'] = extendError(Error, 'UnboundTypeError');; + + var FSNode = /** @constructor */ function(parent, name, mode, rdev) { + if (!parent) { + parent = this; // root node sets parent to itself + } + this.parent = parent; + this.mount = parent.mount; + this.mounted = null; + this.id = FS.nextInode++; + this.name = name; + this.mode = mode; + this.node_ops = {}; + this.stream_ops = {}; + this.rdev = rdev; + }; + var readMode = 292/*292*/ | 73/*73*/; + var writeMode = 146/*146*/; + Object.defineProperties(FSNode.prototype, { + read: { + get: /** @this{FSNode} */function() { + return (this.mode & readMode) === readMode; + }, + set: /** @this{FSNode} */function(val) { + val ? this.mode |= readMode : this.mode &= ~readMode; + } + }, + write: { + get: /** @this{FSNode} */function() { + return (this.mode & writeMode) === writeMode; + }, + set: /** @this{FSNode} */function(val) { + val ? this.mode |= writeMode : this.mode &= ~writeMode; + } + }, + isFolder: { + get: /** @this{FSNode} */function() { + return FS.isDir(this.mode); + } + }, + isDevice: { + get: /** @this{FSNode} */function() { + return FS.isChrdev(this.mode); + } + } + }); + FS.FSNode = FSNode; + FS.createPreloadedFile = FS_createPreloadedFile; + FS.staticInit();; +ERRNO_CODES = { + 'EPERM': 63, + 'ENOENT': 44, + 'ESRCH': 71, + 'EINTR': 27, + 'EIO': 29, + 'ENXIO': 60, + 'E2BIG': 1, + 'ENOEXEC': 45, + 'EBADF': 8, + 'ECHILD': 12, + 'EAGAIN': 6, + 'EWOULDBLOCK': 6, + 'ENOMEM': 48, + 'EACCES': 2, + 'EFAULT': 21, + 'ENOTBLK': 105, + 'EBUSY': 10, + 'EEXIST': 20, + 'EXDEV': 75, + 'ENODEV': 43, + 'ENOTDIR': 54, + 'EISDIR': 31, + 'EINVAL': 28, + 'ENFILE': 41, + 'EMFILE': 33, + 'ENOTTY': 59, + 'ETXTBSY': 74, + 'EFBIG': 22, + 'ENOSPC': 51, + 'ESPIPE': 70, + 'EROFS': 69, + 'EMLINK': 34, + 'EPIPE': 64, + 'EDOM': 18, + 'ERANGE': 68, + 'ENOMSG': 49, + 'EIDRM': 24, + 'ECHRNG': 106, + 'EL2NSYNC': 156, + 'EL3HLT': 107, + 'EL3RST': 108, + 'ELNRNG': 109, + 'EUNATCH': 110, + 'ENOCSI': 111, + 'EL2HLT': 112, + 'EDEADLK': 16, + 'ENOLCK': 46, + 'EBADE': 113, + 'EBADR': 114, + 'EXFULL': 115, + 'ENOANO': 104, + 'EBADRQC': 103, + 'EBADSLT': 102, + 'EDEADLOCK': 16, + 'EBFONT': 101, + 'ENOSTR': 100, + 'ENODATA': 116, + 'ETIME': 117, + 'ENOSR': 118, + 'ENONET': 119, + 'ENOPKG': 120, + 'EREMOTE': 121, + 'ENOLINK': 47, + 'EADV': 122, + 'ESRMNT': 123, + 'ECOMM': 124, + 'EPROTO': 65, + 'EMULTIHOP': 36, + 'EDOTDOT': 125, + 'EBADMSG': 9, + 'ENOTUNIQ': 126, + 'EBADFD': 127, + 'EREMCHG': 128, + 'ELIBACC': 129, + 'ELIBBAD': 130, + 'ELIBSCN': 131, + 'ELIBMAX': 132, + 'ELIBEXEC': 133, + 'ENOSYS': 52, + 'ENOTEMPTY': 55, + 'ENAMETOOLONG': 37, + 'ELOOP': 32, + 'EOPNOTSUPP': 138, + 'EPFNOSUPPORT': 139, + 'ECONNRESET': 15, + 'ENOBUFS': 42, + 'EAFNOSUPPORT': 5, + 'EPROTOTYPE': 67, + 'ENOTSOCK': 57, + 'ENOPROTOOPT': 50, + 'ESHUTDOWN': 140, + 'ECONNREFUSED': 14, + 'EADDRINUSE': 3, + 'ECONNABORTED': 13, + 'ENETUNREACH': 40, + 'ENETDOWN': 38, + 'ETIMEDOUT': 73, + 'EHOSTDOWN': 142, + 'EHOSTUNREACH': 23, + 'EINPROGRESS': 26, + 'EALREADY': 7, + 'EDESTADDRREQ': 17, + 'EMSGSIZE': 35, + 'EPROTONOSUPPORT': 66, + 'ESOCKTNOSUPPORT': 137, + 'EADDRNOTAVAIL': 4, + 'ENETRESET': 39, + 'EISCONN': 30, + 'ENOTCONN': 53, + 'ETOOMANYREFS': 141, + 'EUSERS': 136, + 'EDQUOT': 19, + 'ESTALE': 72, + 'ENOTSUP': 138, + 'ENOMEDIUM': 148, + 'EILSEQ': 25, + 'EOVERFLOW': 61, + 'ECANCELED': 11, + 'ENOTRECOVERABLE': 56, + 'EOWNERDEAD': 62, + 'ESTRPIPE': 135, + };; +function checkIncomingModuleAPI() { + ignoredModuleProp('fetchSettings'); +} +var wasmImports = { + __assert_fail: ___assert_fail, + __cxa_throw: ___cxa_throw, + _embind_create_inheriting_constructor: __embind_create_inheriting_constructor, + _embind_finalize_value_array: __embind_finalize_value_array, + _embind_finalize_value_object: __embind_finalize_value_object, + _embind_register_bigint: __embind_register_bigint, + _embind_register_bool: __embind_register_bool, + _embind_register_class: __embind_register_class, + _embind_register_class_class_function: __embind_register_class_class_function, + _embind_register_class_class_property: __embind_register_class_class_property, + _embind_register_class_constructor: __embind_register_class_constructor, + _embind_register_class_function: __embind_register_class_function, + _embind_register_class_property: __embind_register_class_property, + _embind_register_constant: __embind_register_constant, + _embind_register_emval: __embind_register_emval, + _embind_register_enum: __embind_register_enum, + _embind_register_enum_value: __embind_register_enum_value, + _embind_register_float: __embind_register_float, + _embind_register_function: __embind_register_function, + _embind_register_integer: __embind_register_integer, + _embind_register_memory_view: __embind_register_memory_view, + _embind_register_smart_ptr: __embind_register_smart_ptr, + _embind_register_std_string: __embind_register_std_string, + _embind_register_std_wstring: __embind_register_std_wstring, + _embind_register_value_array: __embind_register_value_array, + _embind_register_value_array_element: __embind_register_value_array_element, + _embind_register_value_object: __embind_register_value_object, + _embind_register_value_object_field: __embind_register_value_object_field, + _embind_register_void: __embind_register_void, + _emval_as: __emval_as, + _emval_as_int64: __emval_as_int64, + _emval_as_uint64: __emval_as_uint64, + _emval_await: __emval_await, + _emval_call: __emval_call, + _emval_call_method: __emval_call_method, + _emval_call_void_method: __emval_call_void_method, + _emval_decref: __emval_decref, + _emval_delete: __emval_delete, + _emval_equals: __emval_equals, + _emval_get_global: __emval_get_global, + _emval_get_method_caller: __emval_get_method_caller, + _emval_get_module_property: __emval_get_module_property, + _emval_get_property: __emval_get_property, + _emval_in: __emval_in, + _emval_incref: __emval_incref, + _emval_instanceof: __emval_instanceof, + _emval_is_number: __emval_is_number, + _emval_is_string: __emval_is_string, + _emval_new: __emval_new, + _emval_new_array: __emval_new_array, + _emval_new_array_from_memory_view: __emval_new_array_from_memory_view, + _emval_new_cstring: __emval_new_cstring, + _emval_new_object: __emval_new_object, + _emval_new_u16string: __emval_new_u16string, + _emval_new_u8string: __emval_new_u8string, + _emval_register_symbol: __emval_register_symbol, + _emval_run_destructors: __emval_run_destructors, + _emval_set_property: __emval_set_property, + _emval_strictly_equals: __emval_strictly_equals, + _emval_take_value: __emval_take_value, + _emval_throw: __emval_throw, + _emval_typeof: __emval_typeof, + abort: _abort, + emscripten_memcpy_big: _emscripten_memcpy_big, + emscripten_resize_heap: _emscripten_resize_heap, + environ_get: _environ_get, + environ_sizes_get: _environ_sizes_get, + fd_close: _fd_close, + fd_read: _fd_read, + fd_seek: _fd_seek, + fd_write: _fd_write, + strftime_l: _strftime_l +}; +var asm = createWasm(); +var ___wasm_call_ctors = createExportWrapper('__wasm_call_ctors'); +var _malloc = Module['_malloc'] = createExportWrapper('malloc'); +var _set_c_u64 = Module['_set_c_u64'] = createExportWrapper('set_c_u64'); +var _set_c_u32 = Module['_set_c_u32'] = createExportWrapper('set_c_u32'); +var ___getTypeName = createExportWrapper('__getTypeName'); +var __embind_initialize_bindings = Module['__embind_initialize_bindings'] = createExportWrapper('_embind_initialize_bindings'); +var ___errno_location = createExportWrapper('__errno_location'); +var _fflush = Module['_fflush'] = createExportWrapper('fflush'); +var _free = Module['_free'] = createExportWrapper('free'); +var setTempRet0 = createExportWrapper('setTempRet0'); +var _emscripten_stack_init = () => (_emscripten_stack_init = wasmExports['emscripten_stack_init'])(); +var _emscripten_stack_get_free = () => (_emscripten_stack_get_free = wasmExports['emscripten_stack_get_free'])(); +var _emscripten_stack_get_base = () => (_emscripten_stack_get_base = wasmExports['emscripten_stack_get_base'])(); +var _emscripten_stack_get_end = () => (_emscripten_stack_get_end = wasmExports['emscripten_stack_get_end'])(); +var stackSave = createExportWrapper('stackSave'); +var stackRestore = createExportWrapper('stackRestore'); +var stackAlloc = createExportWrapper('stackAlloc'); +var _emscripten_stack_get_current = () => (_emscripten_stack_get_current = wasmExports['emscripten_stack_get_current'])(); +var ___cxa_is_pointer_type = createExportWrapper('__cxa_is_pointer_type'); +var dynCall_jj = Module['dynCall_jj'] = createExportWrapper('dynCall_jj'); +var dynCall_jij = Module['dynCall_jij'] = createExportWrapper('dynCall_jij'); +var dynCall_ji = Module['dynCall_ji'] = createExportWrapper('dynCall_ji'); +var dynCall_jii = Module['dynCall_jii'] = createExportWrapper('dynCall_jii'); +var dynCall_jiji = Module['dynCall_jiji'] = createExportWrapper('dynCall_jiji'); +var dynCall_viijii = Module['dynCall_viijii'] = createExportWrapper('dynCall_viijii'); +var dynCall_iiiiij = Module['dynCall_iiiiij'] = createExportWrapper('dynCall_iiiiij'); +var dynCall_iiiiijj = Module['dynCall_iiiiijj'] = createExportWrapper('dynCall_iiiiijj'); +var dynCall_iiiiiijj = Module['dynCall_iiiiiijj'] = createExportWrapper('dynCall_iiiiiijj'); + + +// include: postamble.js +// === Auto-generated postamble setup entry stuff === + +var missingLibrarySymbols = [ + 'writeI53ToI64', + 'writeI53ToI64Clamped', + 'writeI53ToI64Signaling', + 'writeI53ToU64Clamped', + 'writeI53ToU64Signaling', + 'readI53FromI64', + 'readI53FromU64', + 'convertI32PairToI53', + 'convertU32PairToI53', + 'exitJS', + 'growMemory', + 'ydayFromDate', + 'setErrNo', + 'inetPton4', + 'inetNtop4', + 'inetPton6', + 'inetNtop6', + 'readSockaddr', + 'writeSockaddr', + 'getHostByName', + 'getCallstack', + 'emscriptenLog', + 'convertPCtoSourceLocation', + 'readEmAsmArgs', + 'jstoi_q', + 'jstoi_s', + 'listenOnce', + 'autoResumeAudioContext', + 'handleException', + 'runtimeKeepalivePush', + 'runtimeKeepalivePop', + 'callUserCallback', + 'maybeExit', + 'safeSetTimeout', + 'asmjsMangle', + 'getNativeTypeSize', + 'STACK_SIZE', + 'STACK_ALIGN', + 'POINTER_SIZE', + 'ASSERTIONS', + 'getCFunc', + 'ccall', + 'cwrap', + 'uleb128Encode', + 'sigToWasmTypes', + 'generateFuncType', + 'convertJsFunctionToWasm', + 'getEmptyTableSlot', + 'updateTableMap', + 'getFunctionAddress', + 'addFunction', + 'removeFunction', + 'reallyNegative', + 'unSign', + 'strLen', + 'reSign', + 'formatString', + 'intArrayToString', + 'AsciiToString', + 'stringToNewUTF8', + 'stringToUTF8OnStack', + 'registerKeyEventCallback', + 'maybeCStringToJsString', + 'findEventTarget', + 'findCanvasEventTarget', + 'getBoundingClientRect', + 'fillMouseEventData', + 'registerMouseEventCallback', + 'registerWheelEventCallback', + 'registerUiEventCallback', + 'registerFocusEventCallback', + 'fillDeviceOrientationEventData', + 'registerDeviceOrientationEventCallback', + 'fillDeviceMotionEventData', + 'registerDeviceMotionEventCallback', + 'screenOrientation', + 'fillOrientationChangeEventData', + 'registerOrientationChangeEventCallback', + 'fillFullscreenChangeEventData', + 'registerFullscreenChangeEventCallback', + 'JSEvents_requestFullscreen', + 'JSEvents_resizeCanvasForFullscreen', + 'registerRestoreOldStyle', + 'hideEverythingExceptGivenElement', + 'restoreHiddenElements', + 'setLetterbox', + 'softFullscreenResizeWebGLRenderTarget', + 'doRequestFullscreen', + 'fillPointerlockChangeEventData', + 'registerPointerlockChangeEventCallback', + 'registerPointerlockErrorEventCallback', + 'requestPointerLock', + 'fillVisibilityChangeEventData', + 'registerVisibilityChangeEventCallback', + 'registerTouchEventCallback', + 'fillGamepadEventData', + 'registerGamepadEventCallback', + 'registerBeforeUnloadEventCallback', + 'fillBatteryEventData', + 'battery', + 'registerBatteryEventCallback', + 'setCanvasElementSize', + 'getCanvasElementSize', + 'jsStackTrace', + 'stackTrace', + 'checkWasiClock', + 'wasiRightsToMuslOFlags', + 'wasiOFlagsToMuslOFlags', + 'createDyncallWrapper', + 'setImmediateWrapped', + 'clearImmediateWrapped', + 'polyfillSetImmediate', + 'getPromise', + 'makePromise', + 'idsToPromises', + 'makePromiseCallback', + 'findMatchingCatch', + 'setMainLoop', + 'getSocketFromFD', + 'getSocketAddress', + '_setNetworkCallback', + 'heapObjectForWebGLType', + 'heapAccessShiftForWebGLHeap', + 'webgl_enable_ANGLE_instanced_arrays', + 'webgl_enable_OES_vertex_array_object', + 'webgl_enable_WEBGL_draw_buffers', + 'webgl_enable_WEBGL_multi_draw', + 'emscriptenWebGLGet', + 'computeUnpackAlignedImageSize', + 'colorChannelsInGlTextureFormat', + 'emscriptenWebGLGetTexPixelData', + '__glGenObject', + 'emscriptenWebGLGetUniform', + 'webglGetUniformLocation', + 'webglPrepareUniformLocationsBeforeFirstUse', + 'webglGetLeftBracePos', + 'emscriptenWebGLGetVertexAttrib', + '__glGetActiveAttribOrUniform', + 'writeGLArray', + 'registerWebGlEventCallback', + 'runAndAbortIfError', + 'SDL_unicode', + 'SDL_ttfContext', + 'SDL_audio', + 'GLFW_Window', + 'ALLOC_NORMAL', + 'ALLOC_STACK', + 'allocate', + 'writeStringToMemory', + 'writeAsciiToMemory', +]; +missingLibrarySymbols.forEach(missingLibrarySymbol) + +var unexportedSymbols = [ + 'run', + 'addOnPreRun', + 'addOnInit', + 'addOnPreMain', + 'addOnExit', + 'addOnPostRun', + 'addRunDependency', + 'removeRunDependency', + 'FS_createFolder', + 'FS_createPath', + 'FS_createDataFile', + 'FS_createLazyFile', + 'FS_createLink', + 'FS_createDevice', + 'FS_unlink', + 'out', + 'err', + 'callMain', + 'abort', + 'keepRuntimeAlive', + 'wasmMemory', + 'wasmTable', + 'wasmExports', + 'stackAlloc', + 'stackSave', + 'stackRestore', + 'getTempRet0', + 'setTempRet0', + 'writeStackCookie', + 'checkStackCookie', + 'convertI32PairToI53Checked', + 'ptrToString', + 'zeroMemory', + 'getHeapMax', + 'abortOnCannotGrowMemory', + 'ENV', + 'MONTH_DAYS_REGULAR', + 'MONTH_DAYS_LEAP', + 'MONTH_DAYS_REGULAR_CUMULATIVE', + 'MONTH_DAYS_LEAP_CUMULATIVE', + 'isLeapYear', + 'arraySum', + 'addDays', + 'ERRNO_CODES', + 'ERRNO_MESSAGES', + 'DNS', + 'Protocols', + 'Sockets', + 'initRandomFill', + 'randomFill', + 'timers', + 'warnOnce', + 'UNWIND_CACHE', + 'readEmAsmArgsArray', + 'getExecutableName', + 'dynCallLegacy', + 'getDynCaller', + 'dynCall', + 'asyncLoad', + 'alignMemory', + 'mmapAlloc', + 'handleAllocatorInit', + 'HandleAllocator', + 'freeTableIndexes', + 'functionsInTableMap', + 'setValue', + 'getValue', + 'PATH', + 'PATH_FS', + 'UTF8Decoder', + 'UTF8ArrayToString', + 'UTF8ToString', + 'stringToUTF8Array', + 'stringToUTF8', + 'lengthBytesUTF8', + 'intArrayFromString', + 'stringToAscii', + 'UTF16Decoder', + 'UTF16ToString', + 'stringToUTF16', + 'lengthBytesUTF16', + 'UTF32ToString', + 'stringToUTF32', + 'lengthBytesUTF32', + 'writeArrayToMemory', + 'JSEvents', + 'specialHTMLTargets', + 'currentFullscreenStrategy', + 'restoreOldWindowedStyle', + 'demangle', + 'demangleAll', + 'ExitStatus', + 'getEnvStrings', + 'doReadv', + 'doWritev', + 'promiseMap', + 'uncaughtExceptionCount', + 'exceptionLast', + 'exceptionCaught', + 'ExceptionInfo', + 'Browser', + 'wget', + 'SYSCALLS', + 'preloadPlugins', + 'FS_createPreloadedFile', + 'FS_modeStringToFlags', + 'FS_getMode', + 'FS_stdin_getChar_buffer', + 'FS_stdin_getChar', + 'FS', + 'MEMFS', + 'TTY', + 'PIPEFS', + 'SOCKFS', + 'tempFixedLengthArray', + 'miniTempWebGLFloatBuffers', + 'miniTempWebGLIntBuffers', + 'GL', + 'emscripten_webgl_power_preferences', + 'AL', + 'GLUT', + 'EGL', + 'GLEW', + 'IDBStore', + 'SDL', + 'SDL_gfx', + 'GLFW', + 'allocateUTF8', + 'allocateUTF8OnStack', + 'InternalError', + 'BindingError', + 'throwInternalError', + 'throwBindingError', + 'registeredTypes', + 'awaitingDependencies', + 'typeDependencies', + 'tupleRegistrations', + 'structRegistrations', + 'sharedRegisterType', + 'whenDependentTypesAreResolved', + 'embind_charCodes', + 'embind_init_charCodes', + 'readLatin1String', + 'getTypeName', + 'heap32VectorToArray', + 'requireRegisteredType', + 'UnboundTypeError', + 'PureVirtualError', + 'init_embind', + 'throwUnboundTypeError', + 'ensureOverloadTable', + 'exposePublicSymbol', + 'replacePublicSymbol', + 'extendError', + 'createNamedFunction', + 'embindRepr', + 'registeredInstances', + 'getBasestPointer', + 'registerInheritedInstance', + 'unregisterInheritedInstance', + 'getInheritedInstance', + 'getInheritedInstanceCount', + 'getLiveInheritedInstances', + 'registeredPointers', + 'registerType', + 'getShiftFromSize', + 'integerReadValueFromPointer', + 'enumReadValueFromPointer', + 'floatReadValueFromPointer', + 'simpleReadValueFromPointer', + 'runDestructors', + 'newFunc', + 'craftInvokerFunction', + 'embind__requireFunction', + 'genericPointerToWireType', + 'constNoSmartPtrRawPointerToWireType', + 'nonConstNoSmartPtrRawPointerToWireType', + 'init_RegisteredPointer', + 'RegisteredPointer', + 'RegisteredPointer_getPointee', + 'RegisteredPointer_destructor', + 'RegisteredPointer_deleteObject', + 'RegisteredPointer_fromWireType', + 'runDestructor', + 'releaseClassHandle', + 'finalizationRegistry', + 'detachFinalizer_deps', + 'detachFinalizer', + 'attachFinalizer', + 'makeClassHandle', + 'init_ClassHandle', + 'ClassHandle', + 'ClassHandle_isAliasOf', + 'throwInstanceAlreadyDeleted', + 'ClassHandle_clone', + 'ClassHandle_delete', + 'deletionQueue', + 'ClassHandle_isDeleted', + 'ClassHandle_deleteLater', + 'flushPendingDeletes', + 'delayFunction', + 'setDelayFunction', + 'RegisteredClass', + 'shallowCopyInternalPointer', + 'downcastPointer', + 'upcastPointer', + 'validateThis', + 'char_0', + 'char_9', + 'makeLegalFunctionName', + 'emval_handles', + 'emval_symbols', + 'init_emval', + 'count_emval_handles', + 'getStringOrSymbol', + 'Emval', + 'emval_newers', + 'craftEmvalAllocator', + 'emval_get_global', + 'emval_lookupTypes', + 'emval_allocateDestructors', + 'emval_methodCallers', + 'emval_addMethodCaller', + 'emval_registeredMethods', +]; +unexportedSymbols.forEach(unexportedRuntimeSymbol); + + + +var calledRun; + +dependenciesFulfilled = function runCaller() { + // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) + if (!calledRun) run(); + if (!calledRun) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled +}; + +function stackCheckInit() { + // This is normally called automatically during __wasm_call_ctors but need to + // get these values before even running any of the ctors so we call it redundantly + // here. + _emscripten_stack_init(); + // TODO(sbc): Move writeStackCookie to native to to avoid this. + writeStackCookie(); +} + +function run() { + + if (runDependencies > 0) { + return; + } + + stackCheckInit(); + + preRun(); + + // a preRun added a dependency, run will be called later + if (runDependencies > 0) { + return; + } + + function doRun() { + // run may have just been called through dependencies being fulfilled just in this very frame, + // or while the async setStatus time below was happening + if (calledRun) return; + calledRun = true; + Module['calledRun'] = true; + + if (ABORT) return; + + initRuntime(); + + if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized'](); + + assert(!Module['_main'], 'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]'); + + postRun(); + } + + if (Module['setStatus']) { + Module['setStatus']('Running...'); + setTimeout(function() { + setTimeout(function() { + Module['setStatus'](''); + }, 1); + doRun(); + }, 1); + } else + { + doRun(); + } + checkStackCookie(); +} + +function checkUnflushedContent() { + // Compiler settings do not allow exiting the runtime, so flushing + // the streams is not possible. but in ASSERTIONS mode we check + // if there was something to flush, and if so tell the user they + // should request that the runtime be exitable. + // Normally we would not even include flush() at all, but in ASSERTIONS + // builds we do so just for this check, and here we see if there is any + // content to flush, that is, we check if there would have been + // something a non-ASSERTIONS build would have not seen. + // How we flush the streams depends on whether we are in SYSCALLS_REQUIRE_FILESYSTEM=0 + // mode (which has its own special function for this; otherwise, all + // the code is inside libc) + var oldOut = out; + var oldErr = err; + var has = false; + out = err = (x) => { + has = true; + } + try { // it doesn't matter if it fails + _fflush(0); + // also flush in the JS FS layer + ['stdout', 'stderr'].forEach(function(name) { + var info = FS.analyzePath('/dev/' + name); + if (!info) return; + var stream = info.object; + var rdev = stream.rdev; + var tty = TTY.ttys[rdev]; + if (tty && tty.output && tty.output.length) { + has = true; + } + }); + } catch(e) {} + out = oldOut; + err = oldErr; + if (has) { + warnOnce('stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1 (see the Emscripten FAQ), or make sure to emit a newline when you printf etc.'); + } +} + +if (Module['preInit']) { + if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; + while (Module['preInit'].length > 0) { + Module['preInit'].pop()(); + } +} + +run(); + + +// end include: postamble.js diff --git a/testdata/wasm/tests.wasm b/testdata/wasm/tests.wasm new file mode 100755 index 0000000..1438fc1 Binary files /dev/null and b/testdata/wasm/tests.wasm differ diff --git a/tests/generated/classes.go b/tests/generated/classes.go new file mode 100644 index 0000000..18fc882 --- /dev/null +++ b/tests/generated/classes.go @@ -0,0 +1,9066 @@ +// Code generated by wazero-emscripten-embind, DO NOT EDIT. +package generated + +import ( + "context" + + "github.com/jerbob92/wazero-emscripten-embind" +) + +type ClassAbstractClass struct { + embind.ClassBase +} + +func (class *ClassAbstractClass) Clone(ctx context.Context) (*ClassAbstractClass, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassAbstractClass), nil +} + +func (class *ClassAbstractClass) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassAbstractClass) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassAbstractClass) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassAbstractClass) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassAbstractClass) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassAbstractClass) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassAbstractClass) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassAbstractClass) AbstractMethod(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "abstractMethod") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassAbstractClass) ConcreteMethod(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "concreteMethod") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassAbstractClass) OptionalMethod(ctx context.Context, arg0 string) (string, error) { + res, err := class.CallMethod(ctx, "optionalMethod", arg0) + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassAbstractClass) PassShared(ctx context.Context, arg0 embind.ClassBase) error { + _, err := class.CallMethod(ctx, "passShared", arg0) + return err +} + +func (class *ClassAbstractClass) PassVal(ctx context.Context, arg0 any) error { + _, err := class.CallMethod(ctx, "passVal", arg0) + return err +} + +func (class *ClassAbstractClass) StaticExtend(ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := class.CallInstanceMethod(ctx, nil, "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} +func ClassAbstractClassStaticExtend(e embind.Engine, ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := e.CallStaticClassMethod(ctx, "AbstractClass", "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassAbstractClass) StaticImplement(ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassAbstractClassStaticImplement(e embind.Engine, ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "AbstractClass", "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +type ClassAbstractClassWithConstructor struct { + embind.ClassBase +} + +func (class *ClassAbstractClassWithConstructor) Clone(ctx context.Context) (*ClassAbstractClassWithConstructor, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassAbstractClassWithConstructor), nil +} + +func (class *ClassAbstractClassWithConstructor) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassAbstractClassWithConstructor) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassAbstractClassWithConstructor) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassAbstractClassWithConstructor) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassAbstractClassWithConstructor) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassAbstractClassWithConstructor) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassAbstractClassWithConstructor) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassAbstractClassWithConstructor) AbstractMethod(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "abstractMethod") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassAbstractClassWithConstructor) ConcreteMethod(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "concreteMethod") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassAbstractClassWithConstructor) StaticExtend(ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := class.CallInstanceMethod(ctx, nil, "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} +func ClassAbstractClassWithConstructorStaticExtend(e embind.Engine, ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := e.CallStaticClassMethod(ctx, "AbstractClassWithConstructor", "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassAbstractClassWithConstructor) StaticImplement(ctx context.Context, arg0 any, arg1 string) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "implement", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassAbstractClassWithConstructorStaticImplement(e embind.Engine, ctx context.Context, arg0 any, arg1 string) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "AbstractClassWithConstructor", "implement", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +type ClassAbstractClassWithConstructorWrapper struct { + embind.ClassBase +} + +func (class *ClassAbstractClassWithConstructorWrapper) Clone(ctx context.Context) (*ClassAbstractClassWithConstructorWrapper, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassAbstractClassWithConstructorWrapper), nil +} + +func (class *ClassAbstractClassWithConstructorWrapper) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassAbstractClassWithConstructorWrapper) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassAbstractClassWithConstructorWrapper) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassAbstractClassWithConstructorWrapper) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassAbstractClassWithConstructorWrapper) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassAbstractClassWithConstructorWrapper) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassAbstractClassWithConstructorWrapper) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassAbstractClassWithConstructorWrapper) AbstractMethod(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "abstractMethod") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassAbstractClassWithConstructorWrapper) ConcreteMethod(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "concreteMethod") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassAbstractClassWithConstructorWrapper) NotifyOnDestruction(ctx context.Context) error { + _, err := class.CallMethod(ctx, "notifyOnDestruction") + return err +} + +func (class *ClassAbstractClassWithConstructorWrapper) StaticExtend(ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := class.CallInstanceMethod(ctx, nil, "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} +func ClassAbstractClassWithConstructorWrapperStaticExtend(e embind.Engine, ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := e.CallStaticClassMethod(ctx, "AbstractClassWithConstructorWrapper", "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassAbstractClassWithConstructorWrapper) StaticImplement(ctx context.Context, arg0 any, arg1 string) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "implement", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassAbstractClassWithConstructorWrapperStaticImplement(e embind.Engine, ctx context.Context, arg0 any, arg1 string) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "AbstractClassWithConstructorWrapper", "implement", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +type ClassAbstractClassWrapper struct { + embind.ClassBase +} + +func (class *ClassAbstractClassWrapper) Clone(ctx context.Context) (*ClassAbstractClassWrapper, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassAbstractClassWrapper), nil +} + +func (class *ClassAbstractClassWrapper) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassAbstractClassWrapper) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassAbstractClassWrapper) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassAbstractClassWrapper) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassAbstractClassWrapper) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassAbstractClassWrapper) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassAbstractClassWrapper) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassAbstractClassWrapper) AbstractMethod(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "abstractMethod") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassAbstractClassWrapper) ConcreteMethod(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "concreteMethod") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassAbstractClassWrapper) NotifyOnDestruction(ctx context.Context) error { + _, err := class.CallMethod(ctx, "notifyOnDestruction") + return err +} + +func (class *ClassAbstractClassWrapper) OptionalMethod(ctx context.Context, arg0 string) (string, error) { + res, err := class.CallMethod(ctx, "optionalMethod", arg0) + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassAbstractClassWrapper) PassShared(ctx context.Context, arg0 embind.ClassBase) error { + _, err := class.CallMethod(ctx, "passShared", arg0) + return err +} + +func (class *ClassAbstractClassWrapper) PassVal(ctx context.Context, arg0 any) error { + _, err := class.CallMethod(ctx, "passVal", arg0) + return err +} + +func (class *ClassAbstractClassWrapper) StaticExtend(ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := class.CallInstanceMethod(ctx, nil, "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} +func ClassAbstractClassWrapperStaticExtend(e embind.Engine, ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := e.CallStaticClassMethod(ctx, "AbstractClassWrapper", "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassAbstractClassWrapper) StaticImplement(ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassAbstractClassWrapperStaticImplement(e embind.Engine, ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "AbstractClassWrapper", "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +type ClassBase struct { + embind.ClassBase +} + +func (class *ClassBase) Clone(ctx context.Context) (*ClassBase, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassBase), nil +} + +func (class *ClassBase) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassBase) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassBase) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassBase) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassBase) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassBase) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassBase) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassBase) GetPropertyBaseMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "baseMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassBase) SetPropertyBaseMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "baseMember", val) +} + +func (class *ClassBase) GetPropertyMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "member") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassBase) SetPropertyMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "member", val) +} + +func (class *ClassBase) GetBaseMember(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getBaseMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassBase) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassBase) GetClassNameFromBase(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassNameFromBase") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassBase) GetClassNameNotAvailableInDerivedClasses(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassNameNotAvailableInDerivedClasses") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassBase) GetMember(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassBase) SetBaseMember(ctx context.Context, arg0 int32) error { + _, err := class.CallMethod(ctx, "setBaseMember", arg0) + return err +} + +func (class *ClassBase) SetMember(ctx context.Context, arg0 int32) error { + _, err := class.CallMethod(ctx, "setMember", arg0) + return err +} + +func (class *ClassBase) StaticClassFunction(ctx context.Context) (string, error) { + res, err := class.CallInstanceMethod(ctx, nil, "classFunction") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} +func ClassBaseStaticClassFunction(e embind.Engine, ctx context.Context) (string, error) { + res, err := e.CallStaticClassMethod(ctx, "Base", "classFunction") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassBase(e embind.Engine, ctx context.Context) (*ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "Base") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassBase), nil +} + +type ClassBase1 struct { + embind.ClassBase +} + +func (class *ClassBase1) Clone(ctx context.Context) (*ClassBase1, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassBase1), nil +} + +func (class *ClassBase1) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassBase1) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassBase1) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassBase1) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassBase1) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassBase1) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassBase1) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassBase1) GetField(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getField") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassBase1(e embind.Engine, ctx context.Context) (*ClassBase1, error) { + res, err := e.CallPublicSymbol(ctx, "Base1") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassBase1), nil +} + +type ClassBase2 struct { + embind.ClassBase +} + +func (class *ClassBase2) Clone(ctx context.Context) (*ClassBase2, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassBase2), nil +} + +func (class *ClassBase2) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassBase2) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassBase2) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassBase2) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassBase2) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassBase2) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassBase2) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassBase2) GetPropertyField(ctx context.Context) (string, error) { + res, err := class.GetProperty(ctx, "field") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} +func (class *ClassBase2) SetPropertyField(ctx context.Context, val string) error { + return class.SetProperty(ctx, "field", val) +} + +func (class *ClassBase2) GetField(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getField") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +type ClassBaseClass struct { + embind.ClassBase +} + +func (class *ClassBaseClass) Clone(ctx context.Context) (*ClassBaseClass, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassBaseClass), nil +} + +func (class *ClassBaseClass) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassBaseClass) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassBaseClass) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassBaseClass) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassBaseClass) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassBaseClass) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassBaseClass) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassBaseClass) Invoke(ctx context.Context, arg0 string) error { + _, err := class.CallMethod(ctx, "invoke", arg0) + return err +} + +func (class *ClassBaseClass) StaticExtend(ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := class.CallInstanceMethod(ctx, nil, "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} +func ClassBaseClassStaticExtend(e embind.Engine, ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := e.CallStaticClassMethod(ctx, "BaseClass", "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassBaseClass) StaticImplement(ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassBaseClassStaticImplement(e embind.Engine, ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "BaseClass", "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +type ClassBaseClassWrapper struct { + embind.ClassBase +} + +func (class *ClassBaseClassWrapper) Clone(ctx context.Context) (*ClassBaseClassWrapper, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassBaseClassWrapper), nil +} + +func (class *ClassBaseClassWrapper) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassBaseClassWrapper) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassBaseClassWrapper) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassBaseClassWrapper) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassBaseClassWrapper) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassBaseClassWrapper) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassBaseClassWrapper) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassBaseClassWrapper) Invoke(ctx context.Context, arg0 string) error { + _, err := class.CallMethod(ctx, "invoke", arg0) + return err +} + +func (class *ClassBaseClassWrapper) NotifyOnDestruction(ctx context.Context) error { + _, err := class.CallMethod(ctx, "notifyOnDestruction") + return err +} + +func (class *ClassBaseClassWrapper) StaticExtend(ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := class.CallInstanceMethod(ctx, nil, "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} +func ClassBaseClassWrapperStaticExtend(e embind.Engine, ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := e.CallStaticClassMethod(ctx, "BaseClassWrapper", "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassBaseClassWrapper) StaticImplement(ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassBaseClassWrapperStaticImplement(e embind.Engine, ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "BaseClassWrapper", "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +type ClassBigClass struct { + embind.ClassBase +} + +func (class *ClassBigClass) Clone(ctx context.Context) (*ClassBigClass, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassBigClass), nil +} + +func (class *ClassBigClass) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassBigClass) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassBigClass) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassBigClass) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassBigClass) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassBigClass) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassBigClass) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassBigClass) GetPropertyMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "member") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassBigClass) SetPropertyMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "member", val) +} + +func (class *ClassBigClass) GetPropertyOtherMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "otherMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassBigClass) SetPropertyOtherMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "otherMember", val) +} + +func (class *ClassBigClass) GetPropertyYetAnotherMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "yetAnotherMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassBigClass) SetPropertyYetAnotherMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "yetAnotherMember", val) +} + +func (class *ClassBigClass) GetMember(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func NewClassBigClass(e embind.Engine, ctx context.Context) (*ClassBigClass, error) { + res, err := e.CallPublicSymbol(ctx, "BigClass") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassBigClass), nil +} + +type ClassBoundClass struct { + embind.ClassBase +} + +func (class *ClassBoundClass) Clone(ctx context.Context) (*ClassBoundClass, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassBoundClass), nil +} + +func (class *ClassBoundClass) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassBoundClass) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassBoundClass) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassBoundClass) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassBoundClass) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassBoundClass) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassBoundClass) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassBoundClass) GetPropertyProperty(ctx context.Context) (any, error) { + res, err := class.GetProperty(ctx, "property") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} +func (class *ClassBoundClass) SetPropertyProperty(ctx context.Context, val any) error { + return class.SetProperty(ctx, "property", val) +} + +func (class *ClassBoundClass) Method(ctx context.Context, arg0 any) (any, error) { + res, err := class.CallMethod(ctx, "method", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassBoundClass) StaticClassfunction(ctx context.Context, arg0 any) (any, error) { + res, err := class.CallInstanceMethod(ctx, nil, "classfunction", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} +func ClassBoundClassStaticClassfunction(e embind.Engine, ctx context.Context, arg0 any) (any, error) { + res, err := e.CallStaticClassMethod(ctx, "BoundClass", "classfunction", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func NewClassBoundClass(e embind.Engine, ctx context.Context) (*ClassBoundClass, error) { + res, err := e.CallPublicSymbol(ctx, "BoundClass") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassBoundClass), nil +} + +type ClassC struct { + embind.ClassBase +} + +func (class *ClassC) Clone(ctx context.Context) (*ClassC, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassC), nil +} + +func (class *ClassC) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassC) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassC) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassC) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassC) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassC) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassC) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func NewClassC(e embind.Engine, ctx context.Context) (*ClassC, error) { + res, err := e.CallPublicSymbol(ctx, "C") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassC), nil +} + +type ClassCharVector struct { + embind.ClassBase +} + +func (class *ClassCharVector) Clone(ctx context.Context) (*ClassCharVector, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassCharVector), nil +} + +func (class *ClassCharVector) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassCharVector) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassCharVector) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassCharVector) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassCharVector) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassCharVector) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassCharVector) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassCharVector) Get(ctx context.Context, arg0 uint32) (any, error) { + res, err := class.CallMethod(ctx, "get", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassCharVector) Push_back(ctx context.Context, arg0 int8) error { + _, err := class.CallMethod(ctx, "push_back", arg0) + return err +} + +func (class *ClassCharVector) Resize(ctx context.Context, arg0 uint32, arg1 int8) error { + _, err := class.CallMethod(ctx, "resize", arg0, arg1) + return err +} + +func (class *ClassCharVector) Set(ctx context.Context, arg0 uint32, arg1 int8) (bool, error) { + res, err := class.CallMethod(ctx, "set", arg0, arg1) + if err != nil { + return bool(false), err + } + + if res == nil { + return bool(false), nil + } + + return res.(bool), nil +} + +func (class *ClassCharVector) Size(ctx context.Context) (uint32, error) { + res, err := class.CallMethod(ctx, "size") + if err != nil { + return uint32(0), err + } + + if res == nil { + return uint32(0), nil + } + + return res.(uint32), nil +} + +func NewClassCharVector(e embind.Engine, ctx context.Context) (*ClassCharVector, error) { + res, err := e.CallPublicSymbol(ctx, "CharVector") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassCharVector), nil +} + +type ClassConstAndNonConst struct { + embind.ClassBase +} + +func (class *ClassConstAndNonConst) Clone(ctx context.Context) (*ClassConstAndNonConst, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassConstAndNonConst), nil +} + +func (class *ClassConstAndNonConst) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassConstAndNonConst) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassConstAndNonConst) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassConstAndNonConst) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassConstAndNonConst) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassConstAndNonConst) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassConstAndNonConst) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassConstAndNonConst) Method(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "method") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +type ClassConstructFromFunctionObject struct { + embind.ClassBase +} + +func (class *ClassConstructFromFunctionObject) Clone(ctx context.Context) (*ClassConstructFromFunctionObject, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassConstructFromFunctionObject), nil +} + +func (class *ClassConstructFromFunctionObject) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassConstructFromFunctionObject) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassConstructFromFunctionObject) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassConstructFromFunctionObject) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassConstructFromFunctionObject) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassConstructFromFunctionObject) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassConstructFromFunctionObject) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassConstructFromFunctionObject) GetA(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getA") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassConstructFromFunctionObject) GetVal(ctx context.Context) (any, error) { + res, err := class.CallMethod(ctx, "getVal") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func NewClassConstructFromFunctionObject(e embind.Engine, ctx context.Context, arg0 any, arg1 int32) (*ClassConstructFromFunctionObject, error) { + res, err := e.CallPublicSymbol(ctx, "ConstructFromFunctionObject", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassConstructFromFunctionObject), nil +} + +type ClassConstructFromStdFunction struct { + embind.ClassBase +} + +func (class *ClassConstructFromStdFunction) Clone(ctx context.Context) (*ClassConstructFromStdFunction, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassConstructFromStdFunction), nil +} + +func (class *ClassConstructFromStdFunction) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassConstructFromStdFunction) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassConstructFromStdFunction) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassConstructFromStdFunction) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassConstructFromStdFunction) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassConstructFromStdFunction) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassConstructFromStdFunction) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassConstructFromStdFunction) GetA(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getA") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassConstructFromStdFunction) GetVal(ctx context.Context) (any, error) { + res, err := class.CallMethod(ctx, "getVal") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func NewClassConstructFromStdFunction(e embind.Engine, ctx context.Context, arg0 any, arg1 int32) (*ClassConstructFromStdFunction, error) { + res, err := e.CallPublicSymbol(ctx, "ConstructFromStdFunction", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassConstructFromStdFunction), nil +} + +type ClassContainsTemplatedMemberClass struct { + embind.ClassBase +} + +func (class *ClassContainsTemplatedMemberClass) Clone(ctx context.Context) (*ClassContainsTemplatedMemberClass, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassContainsTemplatedMemberClass), nil +} + +func (class *ClassContainsTemplatedMemberClass) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassContainsTemplatedMemberClass) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassContainsTemplatedMemberClass) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassContainsTemplatedMemberClass) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassContainsTemplatedMemberClass) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassContainsTemplatedMemberClass) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassContainsTemplatedMemberClass) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassContainsTemplatedMemberClass) GetTestTemplate(ctx context.Context) (embind.ClassBase, error) { + res, err := class.CallMethod(ctx, "getTestTemplate") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +func NewClassContainsTemplatedMemberClass(e embind.Engine, ctx context.Context) (*ClassContainsTemplatedMemberClass, error) { + res, err := e.CallPublicSymbol(ctx, "ContainsTemplatedMemberClass") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassContainsTemplatedMemberClass), nil +} + +type ClassCustomStruct struct { + embind.ClassBase +} + +func (class *ClassCustomStruct) Clone(ctx context.Context) (*ClassCustomStruct, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassCustomStruct), nil +} + +func (class *ClassCustomStruct) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassCustomStruct) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassCustomStruct) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassCustomStruct) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassCustomStruct) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassCustomStruct) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassCustomStruct) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassCustomStruct) GetPropertyField(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "field") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassCustomStruct) SetPropertyField(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "field", val) +} + +func (class *ClassCustomStruct) GetField(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getField") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func NewClassCustomStruct(e embind.Engine, ctx context.Context) (*ClassCustomStruct, error) { + res, err := e.CallPublicSymbol(ctx, "CustomStruct") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassCustomStruct), nil +} + +type ClassDerived struct { + embind.ClassBase +} + +func (class *ClassDerived) Clone(ctx context.Context) (*ClassDerived, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassDerived), nil +} + +func (class *ClassDerived) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassDerived) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassDerived) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassDerived) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassDerived) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassDerived) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassDerived) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassDerived) GetPropertyBaseMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "baseMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassDerived) SetPropertyBaseMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "baseMember", val) +} + +func (class *ClassDerived) GetPropertyMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "member") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassDerived) SetPropertyMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "member", val) +} + +func (class *ClassDerived) GetBaseMember(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getBaseMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassDerived) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassDerived) GetClassNameFromBase(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassNameFromBase") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassDerived) GetClassNameNotAvailableInDerivedClasses(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassNameNotAvailableInDerivedClasses") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassDerived) GetMember(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassDerived) SetBaseMember(ctx context.Context, arg0 int32) error { + _, err := class.CallMethod(ctx, "setBaseMember", arg0) + return err +} + +func (class *ClassDerived) SetMember(ctx context.Context, arg0 int32) error { + _, err := class.CallMethod(ctx, "setMember", arg0) + return err +} + +func (class *ClassDerived) StaticClassFunction(ctx context.Context) (string, error) { + res, err := class.CallInstanceMethod(ctx, nil, "classFunction") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} +func ClassDerivedStaticClassFunction(e embind.Engine, ctx context.Context) (string, error) { + res, err := e.CallStaticClassMethod(ctx, "Derived", "classFunction") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassDerived(e embind.Engine, ctx context.Context) (*ClassDerived, error) { + res, err := e.CallPublicSymbol(ctx, "Derived") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassDerived), nil +} + +type ClassDerivedClass struct { + embind.ClassBase +} + +func (class *ClassDerivedClass) Clone(ctx context.Context) (*ClassDerivedClass, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassDerivedClass), nil +} + +func (class *ClassDerivedClass) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassDerivedClass) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassDerivedClass) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassDerivedClass) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassDerivedClass) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassDerivedClass) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassDerivedClass) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassDerivedClass) Invoke(ctx context.Context, arg0 string) error { + _, err := class.CallMethod(ctx, "invoke", arg0) + return err +} + +func (class *ClassDerivedClass) StaticExtend(ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := class.CallInstanceMethod(ctx, nil, "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} +func ClassDerivedClassStaticExtend(e embind.Engine, ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := e.CallStaticClassMethod(ctx, "DerivedClass", "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassDerivedClass) StaticImplement(ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassDerivedClassStaticImplement(e embind.Engine, ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "DerivedClass", "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +type ClassDerivedHolder struct { + embind.ClassBase +} + +func (class *ClassDerivedHolder) Clone(ctx context.Context) (*ClassDerivedHolder, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassDerivedHolder), nil +} + +func (class *ClassDerivedHolder) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassDerivedHolder) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassDerivedHolder) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassDerivedHolder) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassDerivedHolder) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassDerivedHolder) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassDerivedHolder) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassDerivedHolder) DeleteDerived(ctx context.Context) error { + _, err := class.CallMethod(ctx, "deleteDerived") + return err +} + +func (class *ClassDerivedHolder) GetDerived(ctx context.Context) (embind.ClassBase, error) { + res, err := class.CallMethod(ctx, "getDerived") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +func (class *ClassDerivedHolder) GetDerivedClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getDerivedClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassDerivedHolder) NewDerived(ctx context.Context) error { + _, err := class.CallMethod(ctx, "newDerived") + return err +} + +func NewClassDerivedHolder(e embind.Engine, ctx context.Context) (*ClassDerivedHolder, error) { + res, err := e.CallPublicSymbol(ctx, "DerivedHolder") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassDerivedHolder), nil +} + +type ClassDerivedThrice struct { + embind.ClassBase +} + +func (class *ClassDerivedThrice) Clone(ctx context.Context) (*ClassDerivedThrice, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassDerivedThrice), nil +} + +func (class *ClassDerivedThrice) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassDerivedThrice) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassDerivedThrice) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassDerivedThrice) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassDerivedThrice) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassDerivedThrice) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassDerivedThrice) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassDerivedThrice) GetPropertyBaseMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "baseMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassDerivedThrice) SetPropertyBaseMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "baseMember", val) +} + +func (class *ClassDerivedThrice) GetPropertyMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "member") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassDerivedThrice) SetPropertyMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "member", val) +} + +func (class *ClassDerivedThrice) GetBaseMember(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getBaseMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassDerivedThrice) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassDerivedThrice) GetClassNameFromBase(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassNameFromBase") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassDerivedThrice) GetClassNameNotAvailableInDerivedClasses(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassNameNotAvailableInDerivedClasses") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassDerivedThrice) GetMember(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassDerivedThrice) SetBaseMember(ctx context.Context, arg0 int32) error { + _, err := class.CallMethod(ctx, "setBaseMember", arg0) + return err +} + +func (class *ClassDerivedThrice) SetMember(ctx context.Context, arg0 int32) error { + _, err := class.CallMethod(ctx, "setMember", arg0) + return err +} + +func (class *ClassDerivedThrice) StaticClassFunction(ctx context.Context) (string, error) { + res, err := class.CallInstanceMethod(ctx, nil, "classFunction") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} +func ClassDerivedThriceStaticClassFunction(e embind.Engine, ctx context.Context) (string, error) { + res, err := e.CallStaticClassMethod(ctx, "DerivedThrice", "classFunction") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassDerivedThrice(e embind.Engine, ctx context.Context) (*ClassDerivedThrice, error) { + res, err := e.CallPublicSymbol(ctx, "DerivedThrice") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassDerivedThrice), nil +} + +type ClassDerivedTwice struct { + embind.ClassBase +} + +func (class *ClassDerivedTwice) Clone(ctx context.Context) (*ClassDerivedTwice, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassDerivedTwice), nil +} + +func (class *ClassDerivedTwice) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassDerivedTwice) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassDerivedTwice) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassDerivedTwice) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassDerivedTwice) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassDerivedTwice) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassDerivedTwice) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassDerivedTwice) GetPropertyBaseMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "baseMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassDerivedTwice) SetPropertyBaseMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "baseMember", val) +} + +func (class *ClassDerivedTwice) GetPropertyMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "member") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassDerivedTwice) SetPropertyMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "member", val) +} + +func (class *ClassDerivedTwice) GetBaseMember(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getBaseMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassDerivedTwice) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassDerivedTwice) GetClassNameFromBase(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassNameFromBase") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassDerivedTwice) GetClassNameNotAvailableInDerivedClasses(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassNameNotAvailableInDerivedClasses") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassDerivedTwice) GetMember(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassDerivedTwice) SetBaseMember(ctx context.Context, arg0 int32) error { + _, err := class.CallMethod(ctx, "setBaseMember", arg0) + return err +} + +func (class *ClassDerivedTwice) SetMember(ctx context.Context, arg0 int32) error { + _, err := class.CallMethod(ctx, "setMember", arg0) + return err +} + +func (class *ClassDerivedTwice) StaticClassFunction(ctx context.Context) (string, error) { + res, err := class.CallInstanceMethod(ctx, nil, "classFunction") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} +func ClassDerivedTwiceStaticClassFunction(e embind.Engine, ctx context.Context) (string, error) { + res, err := e.CallStaticClassMethod(ctx, "DerivedTwice", "classFunction") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassDerivedTwice(e embind.Engine, ctx context.Context) (*ClassDerivedTwice, error) { + res, err := e.CallPublicSymbol(ctx, "DerivedTwice") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassDerivedTwice), nil +} + +type ClassDerivedWithMixin struct { + embind.ClassBase +} + +func (class *ClassDerivedWithMixin) Clone(ctx context.Context) (*ClassDerivedWithMixin, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassDerivedWithMixin), nil +} + +func (class *ClassDerivedWithMixin) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassDerivedWithMixin) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassDerivedWithMixin) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassDerivedWithMixin) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassDerivedWithMixin) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassDerivedWithMixin) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassDerivedWithMixin) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassDerivedWithMixin) GetPropertyBaseMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "baseMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassDerivedWithMixin) SetPropertyBaseMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "baseMember", val) +} + +func (class *ClassDerivedWithMixin) GetPropertyMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "member") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassDerivedWithMixin) SetPropertyMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "member", val) +} + +func (class *ClassDerivedWithMixin) Get10(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "get10") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassDerivedWithMixin) GetBaseMember(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getBaseMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassDerivedWithMixin) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassDerivedWithMixin) GetClassNameFromBase(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassNameFromBase") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassDerivedWithMixin) GetClassNameNotAvailableInDerivedClasses(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassNameNotAvailableInDerivedClasses") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassDerivedWithMixin) GetMember(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassDerivedWithMixin) SetBaseMember(ctx context.Context, arg0 int32) error { + _, err := class.CallMethod(ctx, "setBaseMember", arg0) + return err +} + +func (class *ClassDerivedWithMixin) SetMember(ctx context.Context, arg0 int32) error { + _, err := class.CallMethod(ctx, "setMember", arg0) + return err +} + +func (class *ClassDerivedWithMixin) StaticClassFunction(ctx context.Context) (string, error) { + res, err := class.CallInstanceMethod(ctx, nil, "classFunction") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} +func ClassDerivedWithMixinStaticClassFunction(e embind.Engine, ctx context.Context) (string, error) { + res, err := e.CallStaticClassMethod(ctx, "DerivedWithMixin", "classFunction") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassDerivedWithMixin(e embind.Engine, ctx context.Context) (*ClassDerivedWithMixin, error) { + res, err := e.CallPublicSymbol(ctx, "DerivedWithMixin") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassDerivedWithMixin), nil +} + +type ClassDerivedWithOffset struct { + embind.ClassBase +} + +func (class *ClassDerivedWithOffset) Clone(ctx context.Context) (*ClassDerivedWithOffset, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassDerivedWithOffset), nil +} + +func (class *ClassDerivedWithOffset) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassDerivedWithOffset) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassDerivedWithOffset) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassDerivedWithOffset) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassDerivedWithOffset) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassDerivedWithOffset) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassDerivedWithOffset) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassDerivedWithOffset) GetPropertyBaseMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "baseMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassDerivedWithOffset) SetPropertyBaseMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "baseMember", val) +} + +func (class *ClassDerivedWithOffset) GetPropertyMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "member") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassDerivedWithOffset) SetPropertyMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "member", val) +} + +func (class *ClassDerivedWithOffset) GetBaseMember(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getBaseMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassDerivedWithOffset) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassDerivedWithOffset) GetClassNameFromBase(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassNameFromBase") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassDerivedWithOffset) GetClassNameNotAvailableInDerivedClasses(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassNameNotAvailableInDerivedClasses") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassDerivedWithOffset) GetMember(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassDerivedWithOffset) SetBaseMember(ctx context.Context, arg0 int32) error { + _, err := class.CallMethod(ctx, "setBaseMember", arg0) + return err +} + +func (class *ClassDerivedWithOffset) SetMember(ctx context.Context, arg0 int32) error { + _, err := class.CallMethod(ctx, "setMember", arg0) + return err +} + +func (class *ClassDerivedWithOffset) StaticClassFunction(ctx context.Context) (string, error) { + res, err := class.CallInstanceMethod(ctx, nil, "classFunction") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} +func ClassDerivedWithOffsetStaticClassFunction(e embind.Engine, ctx context.Context) (string, error) { + res, err := e.CallStaticClassMethod(ctx, "DerivedWithOffset", "classFunction") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassDerivedWithOffset(e embind.Engine, ctx context.Context) (*ClassDerivedWithOffset, error) { + res, err := e.CallPublicSymbol(ctx, "DerivedWithOffset") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassDerivedWithOffset), nil +} + +type ClassDummyForOverloads struct { + embind.ClassBase +} + +func (class *ClassDummyForOverloads) Clone(ctx context.Context) (*ClassDummyForOverloads, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassDummyForOverloads), nil +} + +func (class *ClassDummyForOverloads) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassDummyForOverloads) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassDummyForOverloads) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassDummyForOverloads) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassDummyForOverloads) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassDummyForOverloads) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassDummyForOverloads) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func NewClassDummyForOverloads(e embind.Engine, ctx context.Context) (*ClassDummyForOverloads, error) { + res, err := e.CallPublicSymbol(ctx, "DummyForOverloads") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassDummyForOverloads), nil +} + +type ClassDummyForPointer struct { + embind.ClassBase +} + +func (class *ClassDummyForPointer) Clone(ctx context.Context) (*ClassDummyForPointer, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassDummyForPointer), nil +} + +func (class *ClassDummyForPointer) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassDummyForPointer) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassDummyForPointer) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassDummyForPointer) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassDummyForPointer) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassDummyForPointer) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassDummyForPointer) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +type ClassEmValVector struct { + embind.ClassBase +} + +func (class *ClassEmValVector) Clone(ctx context.Context) (*ClassEmValVector, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassEmValVector), nil +} + +func (class *ClassEmValVector) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassEmValVector) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassEmValVector) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassEmValVector) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassEmValVector) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassEmValVector) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassEmValVector) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassEmValVector) Get(ctx context.Context, arg0 uint32) (any, error) { + res, err := class.CallMethod(ctx, "get", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassEmValVector) Push_back(ctx context.Context, arg0 any) error { + _, err := class.CallMethod(ctx, "push_back", arg0) + return err +} + +func (class *ClassEmValVector) Resize(ctx context.Context, arg0 uint32, arg1 any) error { + _, err := class.CallMethod(ctx, "resize", arg0, arg1) + return err +} + +func (class *ClassEmValVector) Set(ctx context.Context, arg0 uint32, arg1 any) (bool, error) { + res, err := class.CallMethod(ctx, "set", arg0, arg1) + if err != nil { + return bool(false), err + } + + if res == nil { + return bool(false), nil + } + + return res.(bool), nil +} + +func (class *ClassEmValVector) Size(ctx context.Context) (uint32, error) { + res, err := class.CallMethod(ctx, "size") + if err != nil { + return uint32(0), err + } + + if res == nil { + return uint32(0), nil + } + + return res.(uint32), nil +} + +func NewClassEmValVector(e embind.Engine, ctx context.Context) (*ClassEmValVector, error) { + res, err := e.CallPublicSymbol(ctx, "EmValVector") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassEmValVector), nil +} + +type ClassFirstElement struct { + embind.ClassBase +} + +func (class *ClassFirstElement) Clone(ctx context.Context) (*ClassFirstElement, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassFirstElement), nil +} + +func (class *ClassFirstElement) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassFirstElement) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassFirstElement) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassFirstElement) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassFirstElement) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassFirstElement) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassFirstElement) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +type ClassFloatVector struct { + embind.ClassBase +} + +func (class *ClassFloatVector) Clone(ctx context.Context) (*ClassFloatVector, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassFloatVector), nil +} + +func (class *ClassFloatVector) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassFloatVector) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassFloatVector) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassFloatVector) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassFloatVector) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassFloatVector) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassFloatVector) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassFloatVector) Get(ctx context.Context, arg0 uint32) (any, error) { + res, err := class.CallMethod(ctx, "get", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassFloatVector) Push_back(ctx context.Context, arg0 float32) error { + _, err := class.CallMethod(ctx, "push_back", arg0) + return err +} + +func (class *ClassFloatVector) Resize(ctx context.Context, arg0 uint32, arg1 float32) error { + _, err := class.CallMethod(ctx, "resize", arg0, arg1) + return err +} + +func (class *ClassFloatVector) Set(ctx context.Context, arg0 uint32, arg1 float32) (bool, error) { + res, err := class.CallMethod(ctx, "set", arg0, arg1) + if err != nil { + return bool(false), err + } + + if res == nil { + return bool(false), nil + } + + return res.(bool), nil +} + +func (class *ClassFloatVector) Size(ctx context.Context) (uint32, error) { + res, err := class.CallMethod(ctx, "size") + if err != nil { + return uint32(0), err + } + + if res == nil { + return uint32(0), nil + } + + return res.(uint32), nil +} + +func NewClassFloatVector(e embind.Engine, ctx context.Context) (*ClassFloatVector, error) { + res, err := e.CallPublicSymbol(ctx, "FloatVector") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassFloatVector), nil +} + +type ClassFoo struct { + embind.ClassBase +} + +func (class *ClassFoo) Clone(ctx context.Context) (*ClassFoo, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassFoo), nil +} + +func (class *ClassFoo) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassFoo) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassFoo) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassFoo) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassFoo) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassFoo) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassFoo) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func NewClassFoo(e embind.Engine, ctx context.Context, arg0 string) (*ClassFoo, error) { + res, err := e.CallPublicSymbol(ctx, "Foo", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassFoo), nil +} + +type ClassHasConstructorUsingUnboundArgument struct { + embind.ClassBase +} + +func (class *ClassHasConstructorUsingUnboundArgument) Clone(ctx context.Context) (*ClassHasConstructorUsingUnboundArgument, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassHasConstructorUsingUnboundArgument), nil +} + +func (class *ClassHasConstructorUsingUnboundArgument) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassHasConstructorUsingUnboundArgument) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassHasConstructorUsingUnboundArgument) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassHasConstructorUsingUnboundArgument) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassHasConstructorUsingUnboundArgument) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassHasConstructorUsingUnboundArgument) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassHasConstructorUsingUnboundArgument) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func NewClassHasConstructorUsingUnboundArgument(e embind.Engine, ctx context.Context, arg0 any) (*ClassHasConstructorUsingUnboundArgument, error) { + res, err := e.CallPublicSymbol(ctx, "HasConstructorUsingUnboundArgument", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassHasConstructorUsingUnboundArgument), nil +} + +type ClassHasExternalConstructor struct { + embind.ClassBase +} + +func (class *ClassHasExternalConstructor) Clone(ctx context.Context) (*ClassHasExternalConstructor, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassHasExternalConstructor), nil +} + +func (class *ClassHasExternalConstructor) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassHasExternalConstructor) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassHasExternalConstructor) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassHasExternalConstructor) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassHasExternalConstructor) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassHasExternalConstructor) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassHasExternalConstructor) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassHasExternalConstructor) GetString(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getString") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassHasExternalConstructor(e embind.Engine, ctx context.Context, arg0 string) (*ClassHasExternalConstructor, error) { + res, err := e.CallPublicSymbol(ctx, "HasExternalConstructor", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassHasExternalConstructor), nil +} + +type ClassHasReadOnlyProperty struct { + embind.ClassBase +} + +func (class *ClassHasReadOnlyProperty) Clone(ctx context.Context) (*ClassHasReadOnlyProperty, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassHasReadOnlyProperty), nil +} + +func (class *ClassHasReadOnlyProperty) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassHasReadOnlyProperty) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassHasReadOnlyProperty) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassHasReadOnlyProperty) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassHasReadOnlyProperty) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassHasReadOnlyProperty) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassHasReadOnlyProperty) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassHasReadOnlyProperty) GetPropertyI(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "i") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func NewClassHasReadOnlyProperty(e embind.Engine, ctx context.Context, arg0 int32) (*ClassHasReadOnlyProperty, error) { + res, err := e.CallPublicSymbol(ctx, "HasReadOnlyProperty", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassHasReadOnlyProperty), nil +} + +type ClassHasStaticMember struct { + embind.ClassBase +} + +func (class *ClassHasStaticMember) Clone(ctx context.Context) (*ClassHasStaticMember, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassHasStaticMember), nil +} + +func (class *ClassHasStaticMember) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassHasStaticMember) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassHasStaticMember) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassHasStaticMember) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassHasStaticMember) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassHasStaticMember) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassHasStaticMember) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassHasStaticMember) GetStaticPropertyC(ctx context.Context) (int32, error) { + res, err := class.GetInstanceProperty(ctx, nil, "c") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func ClassHasStaticMemberGetStaticPropertyC(e embind.Engine, ctx context.Context) (int32, error) { + res, err := e.GetStaticClassProperty(ctx, "HasStaticMember", "c") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassHasStaticMember) GetStaticPropertyV(ctx context.Context) (int32, error) { + res, err := class.GetInstanceProperty(ctx, nil, "v") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func ClassHasStaticMemberGetStaticPropertyV(e embind.Engine, ctx context.Context) (int32, error) { + res, err := e.GetStaticClassProperty(ctx, "HasStaticMember", "v") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassHasStaticMember) SetStaticPropertyV(ctx context.Context, val int32) error { + return class.SetInstanceProperty(ctx, nil, "v", val) +} +func ClassHasStaticMemberSetStaticPropertyV(e embind.Engine, ctx context.Context, val int32) error { + return e.SetStaticClassProperty(ctx, "HasStaticMember", "v", val) +} + +type ClassHasTwoBases struct { + embind.ClassBase +} + +func (class *ClassHasTwoBases) Clone(ctx context.Context) (*ClassHasTwoBases, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassHasTwoBases), nil +} + +func (class *ClassHasTwoBases) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassHasTwoBases) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassHasTwoBases) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassHasTwoBases) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassHasTwoBases) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassHasTwoBases) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassHasTwoBases) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassHasTwoBases) GetPropertyField(ctx context.Context) (string, error) { + res, err := class.GetProperty(ctx, "field") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} +func (class *ClassHasTwoBases) SetPropertyField(ctx context.Context, val string) error { + return class.SetProperty(ctx, "field", val) +} + +func (class *ClassHasTwoBases) GetField(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getField") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassHasTwoBases(e embind.Engine, ctx context.Context) (*ClassHasTwoBases, error) { + res, err := e.CallPublicSymbol(ctx, "HasTwoBases") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassHasTwoBases), nil +} + +type ClassHeldAbstractClass struct { + embind.ClassBase +} + +func (class *ClassHeldAbstractClass) Clone(ctx context.Context) (*ClassHeldAbstractClass, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassHeldAbstractClass), nil +} + +func (class *ClassHeldAbstractClass) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassHeldAbstractClass) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassHeldAbstractClass) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassHeldAbstractClass) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassHeldAbstractClass) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassHeldAbstractClass) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassHeldAbstractClass) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassHeldAbstractClass) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassHeldAbstractClass) Method(ctx context.Context) error { + _, err := class.CallMethod(ctx, "method") + return err +} + +func (class *ClassHeldAbstractClass) StaticExtend(ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := class.CallInstanceMethod(ctx, nil, "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} +func ClassHeldAbstractClassStaticExtend(e embind.Engine, ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := e.CallStaticClassMethod(ctx, "HeldAbstractClass", "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassHeldAbstractClass) StaticImplement(ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassHeldAbstractClassStaticImplement(e embind.Engine, ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "HeldAbstractClass", "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +type ClassHeldAbstractClassWrapper struct { + embind.ClassBase +} + +func (class *ClassHeldAbstractClassWrapper) Clone(ctx context.Context) (*ClassHeldAbstractClassWrapper, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassHeldAbstractClassWrapper), nil +} + +func (class *ClassHeldAbstractClassWrapper) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassHeldAbstractClassWrapper) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassHeldAbstractClassWrapper) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassHeldAbstractClassWrapper) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassHeldAbstractClassWrapper) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassHeldAbstractClassWrapper) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassHeldAbstractClassWrapper) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassHeldAbstractClassWrapper) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassHeldAbstractClassWrapper) Method(ctx context.Context) error { + _, err := class.CallMethod(ctx, "method") + return err +} + +func (class *ClassHeldAbstractClassWrapper) NotifyOnDestruction(ctx context.Context) error { + _, err := class.CallMethod(ctx, "notifyOnDestruction") + return err +} + +func (class *ClassHeldAbstractClassWrapper) StaticExtend(ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := class.CallInstanceMethod(ctx, nil, "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} +func ClassHeldAbstractClassWrapperStaticExtend(e embind.Engine, ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := e.CallStaticClassMethod(ctx, "HeldAbstractClassWrapper", "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassHeldAbstractClassWrapper) StaticImplement(ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassHeldAbstractClassWrapperStaticImplement(e embind.Engine, ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "HeldAbstractClassWrapper", "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +type ClassHeldByCustomSmartPtr struct { + embind.ClassBase +} + +func (class *ClassHeldByCustomSmartPtr) Clone(ctx context.Context) (*ClassHeldByCustomSmartPtr, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassHeldByCustomSmartPtr), nil +} + +func (class *ClassHeldByCustomSmartPtr) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassHeldByCustomSmartPtr) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassHeldByCustomSmartPtr) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassHeldByCustomSmartPtr) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassHeldByCustomSmartPtr) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassHeldByCustomSmartPtr) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassHeldByCustomSmartPtr) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassHeldByCustomSmartPtr) GetPropertyI(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "i") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassHeldByCustomSmartPtr) SetPropertyI(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "i", val) +} + +func (class *ClassHeldByCustomSmartPtr) GetPropertyS(ctx context.Context) (string, error) { + res, err := class.GetProperty(ctx, "s") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} +func (class *ClassHeldByCustomSmartPtr) SetPropertyS(ctx context.Context, val string) error { + return class.SetProperty(ctx, "s", val) +} + +func (class *ClassHeldByCustomSmartPtr) StaticCreateSharedPtr(ctx context.Context, arg0 int32, arg1 string) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "createSharedPtr", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassHeldByCustomSmartPtrStaticCreateSharedPtr(e embind.Engine, ctx context.Context, arg0 int32, arg1 string) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "HeldByCustomSmartPtr", "createSharedPtr", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +func NewClassHeldByCustomSmartPtr(e embind.Engine, ctx context.Context, arg0 int32, arg1 string) (*ClassHeldByCustomSmartPtr, error) { + res, err := e.CallPublicSymbol(ctx, "HeldByCustomSmartPtr", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassHeldByCustomSmartPtr), nil +} + +type ClassHeldBySmartPtr struct { + embind.ClassBase +} + +func (class *ClassHeldBySmartPtr) Clone(ctx context.Context) (*ClassHeldBySmartPtr, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassHeldBySmartPtr), nil +} + +func (class *ClassHeldBySmartPtr) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassHeldBySmartPtr) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassHeldBySmartPtr) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassHeldBySmartPtr) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassHeldBySmartPtr) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassHeldBySmartPtr) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassHeldBySmartPtr) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassHeldBySmartPtr) GetPropertyI(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "i") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassHeldBySmartPtr) SetPropertyI(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "i", val) +} + +func (class *ClassHeldBySmartPtr) GetPropertyS(ctx context.Context) (string, error) { + res, err := class.GetProperty(ctx, "s") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} +func (class *ClassHeldBySmartPtr) SetPropertyS(ctx context.Context, val string) error { + return class.SetProperty(ctx, "s", val) +} + +func (class *ClassHeldBySmartPtr) ReturnThis(ctx context.Context) (embind.ClassBase, error) { + res, err := class.CallMethod(ctx, "returnThis") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +func (class *ClassHeldBySmartPtr) StaticNewCustomPtr(ctx context.Context, arg0 int32, arg1 string) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "newCustomPtr", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassHeldBySmartPtrStaticNewCustomPtr(e embind.Engine, ctx context.Context, arg0 int32, arg1 string) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "HeldBySmartPtr", "newCustomPtr", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +func NewClassHeldBySmartPtr(e embind.Engine, ctx context.Context, arg0 int32, arg1 string) (*ClassHeldBySmartPtr, error) { + res, err := e.CallPublicSymbol(ctx, "HeldBySmartPtr", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassHeldBySmartPtr), nil +} + +type ClassIntTemplateClass struct { + embind.ClassBase +} + +func (class *ClassIntTemplateClass) Clone(ctx context.Context) (*ClassIntTemplateClass, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassIntTemplateClass), nil +} + +func (class *ClassIntTemplateClass) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassIntTemplateClass) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassIntTemplateClass) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassIntTemplateClass) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassIntTemplateClass) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassIntTemplateClass) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassIntTemplateClass) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassIntTemplateClass) GetMember(ctx context.Context, arg0 int32) (int32, error) { + res, err := class.CallMethod(ctx, "getMember", arg0) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func NewClassIntTemplateClass(e embind.Engine, ctx context.Context, arg0 int32, arg1 int32, arg2 int32) (*ClassIntTemplateClass, error) { + res, err := e.CallPublicSymbol(ctx, "IntTemplateClass", arg0, arg1, arg2) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassIntTemplateClass), nil +} + +type ClassIntegerVector struct { + embind.ClassBase +} + +func (class *ClassIntegerVector) Clone(ctx context.Context) (*ClassIntegerVector, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassIntegerVector), nil +} + +func (class *ClassIntegerVector) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassIntegerVector) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassIntegerVector) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassIntegerVector) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassIntegerVector) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassIntegerVector) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassIntegerVector) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassIntegerVector) Get(ctx context.Context, arg0 uint32) (any, error) { + res, err := class.CallMethod(ctx, "get", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassIntegerVector) Push_back(ctx context.Context, arg0 int32) error { + _, err := class.CallMethod(ctx, "push_back", arg0) + return err +} + +func (class *ClassIntegerVector) Resize(ctx context.Context, arg0 uint32, arg1 int32) error { + _, err := class.CallMethod(ctx, "resize", arg0, arg1) + return err +} + +func (class *ClassIntegerVector) Set(ctx context.Context, arg0 uint32, arg1 int32) (bool, error) { + res, err := class.CallMethod(ctx, "set", arg0, arg1) + if err != nil { + return bool(false), err + } + + if res == nil { + return bool(false), nil + } + + return res.(bool), nil +} + +func (class *ClassIntegerVector) Size(ctx context.Context) (uint32, error) { + res, err := class.CallMethod(ctx, "size") + if err != nil { + return uint32(0), err + } + + if res == nil { + return uint32(0), nil + } + + return res.(uint32), nil +} + +func NewClassIntegerVector(e embind.Engine, ctx context.Context) (*ClassIntegerVector, error) { + res, err := e.CallPublicSymbol(ctx, "IntegerVector") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassIntegerVector), nil +} + +type ClassIntegerVectorVector struct { + embind.ClassBase +} + +func (class *ClassIntegerVectorVector) Clone(ctx context.Context) (*ClassIntegerVectorVector, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassIntegerVectorVector), nil +} + +func (class *ClassIntegerVectorVector) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassIntegerVectorVector) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassIntegerVectorVector) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassIntegerVectorVector) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassIntegerVectorVector) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassIntegerVectorVector) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassIntegerVectorVector) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassIntegerVectorVector) Get(ctx context.Context, arg0 uint32) (any, error) { + res, err := class.CallMethod(ctx, "get", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassIntegerVectorVector) Push_back(ctx context.Context, arg0 embind.ClassBase) error { + _, err := class.CallMethod(ctx, "push_back", arg0) + return err +} + +func (class *ClassIntegerVectorVector) Resize(ctx context.Context, arg0 uint32, arg1 embind.ClassBase) error { + _, err := class.CallMethod(ctx, "resize", arg0, arg1) + return err +} + +func (class *ClassIntegerVectorVector) Set(ctx context.Context, arg0 uint32, arg1 embind.ClassBase) (bool, error) { + res, err := class.CallMethod(ctx, "set", arg0, arg1) + if err != nil { + return bool(false), err + } + + if res == nil { + return bool(false), nil + } + + return res.(bool), nil +} + +func (class *ClassIntegerVectorVector) Size(ctx context.Context) (uint32, error) { + res, err := class.CallMethod(ctx, "size") + if err != nil { + return uint32(0), err + } + + if res == nil { + return uint32(0), nil + } + + return res.(uint32), nil +} + +func NewClassIntegerVectorVector(e embind.Engine, ctx context.Context) (*ClassIntegerVectorVector, error) { + res, err := e.CallPublicSymbol(ctx, "IntegerVectorVector") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassIntegerVectorVector), nil +} + +type ClassInterface struct { + embind.ClassBase +} + +func (class *ClassInterface) Clone(ctx context.Context) (*ClassInterface, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassInterface), nil +} + +func (class *ClassInterface) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassInterface) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassInterface) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassInterface) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassInterface) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassInterface) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassInterface) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassInterface) Invoke(ctx context.Context, arg0 string) error { + _, err := class.CallMethod(ctx, "invoke", arg0) + return err +} + +func (class *ClassInterface) StaticExtend(ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := class.CallInstanceMethod(ctx, nil, "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} +func ClassInterfaceStaticExtend(e embind.Engine, ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := e.CallStaticClassMethod(ctx, "Interface", "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassInterface) StaticImplement(ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassInterfaceStaticImplement(e embind.Engine, ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "Interface", "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +type ClassInterfaceWrapper struct { + embind.ClassBase +} + +func (class *ClassInterfaceWrapper) Clone(ctx context.Context) (*ClassInterfaceWrapper, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassInterfaceWrapper), nil +} + +func (class *ClassInterfaceWrapper) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassInterfaceWrapper) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassInterfaceWrapper) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassInterfaceWrapper) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassInterfaceWrapper) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassInterfaceWrapper) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassInterfaceWrapper) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassInterfaceWrapper) Invoke(ctx context.Context, arg0 string) error { + _, err := class.CallMethod(ctx, "invoke", arg0) + return err +} + +func (class *ClassInterfaceWrapper) NotifyOnDestruction(ctx context.Context) error { + _, err := class.CallMethod(ctx, "notifyOnDestruction") + return err +} + +func (class *ClassInterfaceWrapper) StaticExtend(ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := class.CallInstanceMethod(ctx, nil, "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} +func ClassInterfaceWrapperStaticExtend(e embind.Engine, ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := e.CallStaticClassMethod(ctx, "InterfaceWrapper", "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassInterfaceWrapper) StaticImplement(ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassInterfaceWrapperStaticImplement(e embind.Engine, ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "InterfaceWrapper", "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +type ClassIntrusiveClass struct { + embind.ClassBase +} + +func (class *ClassIntrusiveClass) Clone(ctx context.Context) (*ClassIntrusiveClass, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassIntrusiveClass), nil +} + +func (class *ClassIntrusiveClass) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassIntrusiveClass) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassIntrusiveClass) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassIntrusiveClass) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassIntrusiveClass) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassIntrusiveClass) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassIntrusiveClass) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassIntrusiveClass) StaticExtend(ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := class.CallInstanceMethod(ctx, nil, "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} +func ClassIntrusiveClassStaticExtend(e embind.Engine, ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := e.CallStaticClassMethod(ctx, "IntrusiveClass", "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassIntrusiveClass) StaticImplement(ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassIntrusiveClassStaticImplement(e embind.Engine, ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "IntrusiveClass", "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +func NewClassIntrusiveClass(e embind.Engine, ctx context.Context) (*ClassIntrusiveClass, error) { + res, err := e.CallPublicSymbol(ctx, "IntrusiveClass") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassIntrusiveClass), nil +} + +type ClassIntrusiveClassHolder struct { + embind.ClassBase +} + +func (class *ClassIntrusiveClassHolder) Clone(ctx context.Context) (*ClassIntrusiveClassHolder, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassIntrusiveClassHolder), nil +} + +func (class *ClassIntrusiveClassHolder) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassIntrusiveClassHolder) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassIntrusiveClassHolder) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassIntrusiveClassHolder) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassIntrusiveClassHolder) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassIntrusiveClassHolder) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassIntrusiveClassHolder) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassIntrusiveClassHolder) Get(ctx context.Context) (embind.ClassBase, error) { + res, err := class.CallMethod(ctx, "get") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +func (class *ClassIntrusiveClassHolder) Set(ctx context.Context, arg0 embind.ClassBase) error { + _, err := class.CallMethod(ctx, "set", arg0) + return err +} + +func NewClassIntrusiveClassHolder(e embind.Engine, ctx context.Context) (*ClassIntrusiveClassHolder, error) { + res, err := e.CallPublicSymbol(ctx, "IntrusiveClassHolder") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassIntrusiveClassHolder), nil +} + +type ClassIntrusiveClassWrapper struct { + embind.ClassBase +} + +func (class *ClassIntrusiveClassWrapper) Clone(ctx context.Context) (*ClassIntrusiveClassWrapper, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassIntrusiveClassWrapper), nil +} + +func (class *ClassIntrusiveClassWrapper) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassIntrusiveClassWrapper) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassIntrusiveClassWrapper) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassIntrusiveClassWrapper) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassIntrusiveClassWrapper) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassIntrusiveClassWrapper) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassIntrusiveClassWrapper) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassIntrusiveClassWrapper) NotifyOnDestruction(ctx context.Context) error { + _, err := class.CallMethod(ctx, "notifyOnDestruction") + return err +} + +func (class *ClassIntrusiveClassWrapper) StaticExtend(ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := class.CallInstanceMethod(ctx, nil, "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} +func ClassIntrusiveClassWrapperStaticExtend(e embind.Engine, ctx context.Context, arg0 string, arg1 any) (any, error) { + res, err := e.CallStaticClassMethod(ctx, "IntrusiveClassWrapper", "extend", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassIntrusiveClassWrapper) StaticImplement(ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassIntrusiveClassWrapperStaticImplement(e embind.Engine, ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "IntrusiveClassWrapper", "implement", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +type ClassMap_int__string_ struct { + embind.ClassBase +} + +func (class *ClassMap_int__string_) Clone(ctx context.Context) (*ClassMap_int__string_, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassMap_int__string_), nil +} + +func (class *ClassMap_int__string_) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassMap_int__string_) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassMap_int__string_) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassMap_int__string_) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassMap_int__string_) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassMap_int__string_) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassMap_int__string_) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassMap_int__string_) Get(ctx context.Context, arg0 int32) (any, error) { + res, err := class.CallMethod(ctx, "get", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassMap_int__string_) Keys(ctx context.Context) (embind.ClassBase, error) { + res, err := class.CallMethod(ctx, "keys") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +func (class *ClassMap_int__string_) Set(ctx context.Context, arg0 int32, arg1 string) error { + _, err := class.CallMethod(ctx, "set", arg0, arg1) + return err +} + +func (class *ClassMap_int__string_) Size(ctx context.Context) (uint32, error) { + res, err := class.CallMethod(ctx, "size") + if err != nil { + return uint32(0), err + } + + if res == nil { + return uint32(0), nil + } + + return res.(uint32), nil +} + +func NewClassMap_int__string_(e embind.Engine, ctx context.Context) (*ClassMap_int__string_, error) { + res, err := e.CallPublicSymbol(ctx, "map_int__string_") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassMap_int__string_), nil +} + +type ClassMultipleAccessors struct { + embind.ClassBase +} + +func (class *ClassMultipleAccessors) Clone(ctx context.Context) (*ClassMultipleAccessors, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassMultipleAccessors), nil +} + +func (class *ClassMultipleAccessors) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassMultipleAccessors) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassMultipleAccessors) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassMultipleAccessors) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassMultipleAccessors) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassMultipleAccessors) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassMultipleAccessors) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassMultipleAccessors) GetConst(ctx context.Context, arg0 int32) (int32, error) { + res, err := class.CallMethod(ctx, "getConst", arg0) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +type ClassMultipleCtors struct { + embind.ClassBase +} + +func (class *ClassMultipleCtors) Clone(ctx context.Context) (*ClassMultipleCtors, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassMultipleCtors), nil +} + +func (class *ClassMultipleCtors) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassMultipleCtors) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassMultipleCtors) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassMultipleCtors) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassMultipleCtors) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassMultipleCtors) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassMultipleCtors) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassMultipleCtors) WhichCtorCalled(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "WhichCtorCalled") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func NewClassMultipleCtors1(e embind.Engine, ctx context.Context, arg0 int32) (*ClassMultipleCtors, error) { + res, err := e.CallPublicSymbol(ctx, "MultipleCtors", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassMultipleCtors), nil +} + +func NewClassMultipleCtors2(e embind.Engine, ctx context.Context, arg0 int32, arg1 int32) (*ClassMultipleCtors, error) { + res, err := e.CallPublicSymbol(ctx, "MultipleCtors", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassMultipleCtors), nil +} + +func NewClassMultipleCtors3(e embind.Engine, ctx context.Context, arg0 int32, arg1 int32, arg2 int32) (*ClassMultipleCtors, error) { + res, err := e.CallPublicSymbol(ctx, "MultipleCtors", arg0, arg1, arg2) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassMultipleCtors), nil +} + +type ClassMultipleOverloads struct { + embind.ClassBase +} + +func (class *ClassMultipleOverloads) Clone(ctx context.Context) (*ClassMultipleOverloads, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassMultipleOverloads), nil +} + +func (class *ClassMultipleOverloads) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassMultipleOverloads) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassMultipleOverloads) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassMultipleOverloads) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassMultipleOverloads) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassMultipleOverloads) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassMultipleOverloads) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassMultipleOverloads) Func1(ctx context.Context, arg0 int32) (int32, error) { + res, err := class.CallMethod(ctx, "Func", arg0) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassMultipleOverloads) Func2(ctx context.Context, arg0 int32, arg1 int32) (int32, error) { + res, err := class.CallMethod(ctx, "Func", arg0, arg1) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassMultipleOverloads) WhichFuncCalled(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "WhichFuncCalled") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassMultipleOverloads) StaticStaticFunc1(ctx context.Context, arg0 int32) (int32, error) { + res, err := class.CallInstanceMethod(ctx, nil, "StaticFunc", arg0) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func ClassMultipleOverloadsStaticStaticFunc1(e embind.Engine, ctx context.Context, arg0 int32) (int32, error) { + res, err := e.CallStaticClassMethod(ctx, "MultipleOverloads", "StaticFunc", arg0) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassMultipleOverloads) StaticStaticFunc2(ctx context.Context, arg0 int32, arg1 int32) (int32, error) { + res, err := class.CallInstanceMethod(ctx, nil, "StaticFunc", arg0, arg1) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func ClassMultipleOverloadsStaticStaticFunc2(e embind.Engine, ctx context.Context, arg0 int32, arg1 int32) (int32, error) { + res, err := e.CallStaticClassMethod(ctx, "MultipleOverloads", "StaticFunc", arg0, arg1) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassMultipleOverloads) StaticWhichStaticFuncCalled(ctx context.Context) (int32, error) { + res, err := class.CallInstanceMethod(ctx, nil, "WhichStaticFuncCalled") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func ClassMultipleOverloadsStaticWhichStaticFuncCalled(e embind.Engine, ctx context.Context) (int32, error) { + res, err := e.CallStaticClassMethod(ctx, "MultipleOverloads", "WhichStaticFuncCalled") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func NewClassMultipleOverloads(e embind.Engine, ctx context.Context) (*ClassMultipleOverloads, error) { + res, err := e.CallPublicSymbol(ctx, "MultipleOverloads") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassMultipleOverloads), nil +} + +type ClassMultipleOverloadsDependingOnDummy struct { + embind.ClassBase +} + +func (class *ClassMultipleOverloadsDependingOnDummy) Clone(ctx context.Context) (*ClassMultipleOverloadsDependingOnDummy, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassMultipleOverloadsDependingOnDummy), nil +} + +func (class *ClassMultipleOverloadsDependingOnDummy) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassMultipleOverloadsDependingOnDummy) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassMultipleOverloadsDependingOnDummy) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassMultipleOverloadsDependingOnDummy) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassMultipleOverloadsDependingOnDummy) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassMultipleOverloadsDependingOnDummy) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassMultipleOverloadsDependingOnDummy) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassMultipleOverloadsDependingOnDummy) Dummy0(ctx context.Context) (embind.ClassBase, error) { + res, err := class.CallMethod(ctx, "dummy") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +func (class *ClassMultipleOverloadsDependingOnDummy) Dummy1(ctx context.Context, arg0 embind.ClassBase) (embind.ClassBase, error) { + res, err := class.CallMethod(ctx, "dummy", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +func (class *ClassMultipleOverloadsDependingOnDummy) StaticStaticDummy0(ctx context.Context) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "staticDummy") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassMultipleOverloadsDependingOnDummyStaticStaticDummy0(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "MultipleOverloadsDependingOnDummy", "staticDummy") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +func (class *ClassMultipleOverloadsDependingOnDummy) StaticStaticDummy1(ctx context.Context, arg0 embind.ClassBase) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "staticDummy", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassMultipleOverloadsDependingOnDummyStaticStaticDummy1(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "MultipleOverloadsDependingOnDummy", "staticDummy", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +func NewClassMultipleOverloadsDependingOnDummy(e embind.Engine, ctx context.Context) (*ClassMultipleOverloadsDependingOnDummy, error) { + res, err := e.CallPublicSymbol(ctx, "MultipleOverloadsDependingOnDummy") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassMultipleOverloadsDependingOnDummy), nil +} + +type ClassMultipleOverloadsDerived struct { + embind.ClassBase +} + +func (class *ClassMultipleOverloadsDerived) Clone(ctx context.Context) (*ClassMultipleOverloadsDerived, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassMultipleOverloadsDerived), nil +} + +func (class *ClassMultipleOverloadsDerived) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassMultipleOverloadsDerived) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassMultipleOverloadsDerived) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassMultipleOverloadsDerived) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassMultipleOverloadsDerived) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassMultipleOverloadsDerived) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassMultipleOverloadsDerived) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassMultipleOverloadsDerived) Func1(ctx context.Context, arg0 int32) (int32, error) { + res, err := class.CallMethod(ctx, "Func", arg0) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassMultipleOverloadsDerived) Func2(ctx context.Context, arg0 int32, arg1 int32) (int32, error) { + res, err := class.CallMethod(ctx, "Func", arg0, arg1) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassMultipleOverloadsDerived) Func3(ctx context.Context, arg0 int32, arg1 int32, arg2 int32) (int32, error) { + res, err := class.CallMethod(ctx, "Func", arg0, arg1, arg2) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassMultipleOverloadsDerived) Func4(ctx context.Context, arg0 int32, arg1 int32, arg2 int32, arg3 int32) (int32, error) { + res, err := class.CallMethod(ctx, "Func", arg0, arg1, arg2, arg3) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassMultipleOverloadsDerived) WhichFuncCalled(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "WhichFuncCalled") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassMultipleOverloadsDerived) StaticStaticFunc1(ctx context.Context, arg0 int32) (int32, error) { + res, err := class.CallInstanceMethod(ctx, nil, "StaticFunc", arg0) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func ClassMultipleOverloadsDerivedStaticStaticFunc1(e embind.Engine, ctx context.Context, arg0 int32) (int32, error) { + res, err := e.CallStaticClassMethod(ctx, "MultipleOverloadsDerived", "StaticFunc", arg0) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassMultipleOverloadsDerived) StaticStaticFunc2(ctx context.Context, arg0 int32, arg1 int32) (int32, error) { + res, err := class.CallInstanceMethod(ctx, nil, "StaticFunc", arg0, arg1) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func ClassMultipleOverloadsDerivedStaticStaticFunc2(e embind.Engine, ctx context.Context, arg0 int32, arg1 int32) (int32, error) { + res, err := e.CallStaticClassMethod(ctx, "MultipleOverloadsDerived", "StaticFunc", arg0, arg1) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassMultipleOverloadsDerived) StaticStaticFunc3(ctx context.Context, arg0 int32, arg1 int32, arg2 int32) (int32, error) { + res, err := class.CallInstanceMethod(ctx, nil, "StaticFunc", arg0, arg1, arg2) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func ClassMultipleOverloadsDerivedStaticStaticFunc3(e embind.Engine, ctx context.Context, arg0 int32, arg1 int32, arg2 int32) (int32, error) { + res, err := e.CallStaticClassMethod(ctx, "MultipleOverloadsDerived", "StaticFunc", arg0, arg1, arg2) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassMultipleOverloadsDerived) StaticStaticFunc4(ctx context.Context, arg0 int32, arg1 int32, arg2 int32, arg3 int32) (int32, error) { + res, err := class.CallInstanceMethod(ctx, nil, "StaticFunc", arg0, arg1, arg2, arg3) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func ClassMultipleOverloadsDerivedStaticStaticFunc4(e embind.Engine, ctx context.Context, arg0 int32, arg1 int32, arg2 int32, arg3 int32) (int32, error) { + res, err := e.CallStaticClassMethod(ctx, "MultipleOverloadsDerived", "StaticFunc", arg0, arg1, arg2, arg3) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassMultipleOverloadsDerived) StaticWhichStaticFuncCalled(ctx context.Context) (int32, error) { + res, err := class.CallInstanceMethod(ctx, nil, "WhichStaticFuncCalled") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func ClassMultipleOverloadsDerivedStaticWhichStaticFuncCalled(e embind.Engine, ctx context.Context) (int32, error) { + res, err := e.CallStaticClassMethod(ctx, "MultipleOverloadsDerived", "WhichStaticFuncCalled") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func NewClassMultipleOverloadsDerived(e embind.Engine, ctx context.Context) (*ClassMultipleOverloadsDerived, error) { + res, err := e.CallPublicSymbol(ctx, "MultipleOverloadsDerived") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassMultipleOverloadsDerived), nil +} + +type ClassMultipleSmartCtors struct { + embind.ClassBase +} + +func (class *ClassMultipleSmartCtors) Clone(ctx context.Context) (*ClassMultipleSmartCtors, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassMultipleSmartCtors), nil +} + +func (class *ClassMultipleSmartCtors) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassMultipleSmartCtors) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassMultipleSmartCtors) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassMultipleSmartCtors) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassMultipleSmartCtors) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassMultipleSmartCtors) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassMultipleSmartCtors) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassMultipleSmartCtors) WhichCtorCalled(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "WhichCtorCalled") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func NewClassMultipleSmartCtors1(e embind.Engine, ctx context.Context, arg0 int32) (*ClassMultipleSmartCtors, error) { + res, err := e.CallPublicSymbol(ctx, "MultipleSmartCtors", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassMultipleSmartCtors), nil +} + +func NewClassMultipleSmartCtors2(e embind.Engine, ctx context.Context, arg0 int32, arg1 int32) (*ClassMultipleSmartCtors, error) { + res, err := e.CallPublicSymbol(ctx, "MultipleSmartCtors", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassMultipleSmartCtors), nil +} + +type ClassMultiplyDerived struct { + embind.ClassBase +} + +func (class *ClassMultiplyDerived) Clone(ctx context.Context) (*ClassMultiplyDerived, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassMultiplyDerived), nil +} + +func (class *ClassMultiplyDerived) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassMultiplyDerived) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassMultiplyDerived) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassMultiplyDerived) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassMultiplyDerived) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassMultiplyDerived) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassMultiplyDerived) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassMultiplyDerived) GetPropertyBaseMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "baseMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassMultiplyDerived) SetPropertyBaseMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "baseMember", val) +} + +func (class *ClassMultiplyDerived) GetPropertyMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "member") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassMultiplyDerived) SetPropertyMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "member", val) +} + +func (class *ClassMultiplyDerived) GetBaseMember(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getBaseMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassMultiplyDerived) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassMultiplyDerived) GetClassNameFromBase(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassNameFromBase") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassMultiplyDerived) GetClassNameNotAvailableInDerivedClasses(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassNameNotAvailableInDerivedClasses") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassMultiplyDerived) GetMember(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassMultiplyDerived) SetBaseMember(ctx context.Context, arg0 int32) error { + _, err := class.CallMethod(ctx, "setBaseMember", arg0) + return err +} + +func (class *ClassMultiplyDerived) SetMember(ctx context.Context, arg0 int32) error { + _, err := class.CallMethod(ctx, "setMember", arg0) + return err +} + +func (class *ClassMultiplyDerived) StaticClassFunction(ctx context.Context) (string, error) { + res, err := class.CallInstanceMethod(ctx, nil, "classFunction") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} +func ClassMultiplyDerivedStaticClassFunction(e embind.Engine, ctx context.Context) (string, error) { + res, err := e.CallStaticClassMethod(ctx, "MultiplyDerived", "classFunction") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassMultiplyDerived) StaticGetInstanceCount(ctx context.Context) (int32, error) { + res, err := class.CallInstanceMethod(ctx, nil, "getInstanceCount") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func ClassMultiplyDerivedStaticGetInstanceCount(e embind.Engine, ctx context.Context) (int32, error) { + res, err := e.CallStaticClassMethod(ctx, "MultiplyDerived", "getInstanceCount") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func NewClassMultiplyDerived(e embind.Engine, ctx context.Context) (*ClassMultiplyDerived, error) { + res, err := e.CallPublicSymbol(ctx, "MultiplyDerived") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassMultiplyDerived), nil +} + +type ClassMyClass struct { + embind.ClassBase +} + +func (class *ClassMyClass) Clone(ctx context.Context) (*ClassMyClass, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassMyClass), nil +} + +func (class *ClassMyClass) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassMyClass) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassMyClass) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassMyClass) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassMyClass) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassMyClass) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassMyClass) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassMyClass) GetPropertyX(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "x") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassMyClass) SetPropertyX(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "x", val) +} + +func (class *ClassMyClass) GetPropertyY(ctx context.Context) (string, error) { + res, err := class.GetProperty(ctx, "y") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassMyClass) CombineY(ctx context.Context, arg0 string) (string, error) { + res, err := class.CallMethod(ctx, "combineY", arg0) + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassMyClass) IncrementX0(ctx context.Context) error { + _, err := class.CallMethod(ctx, "incrementX") + return err +} + +func (class *ClassMyClass) IncrementX1(ctx context.Context, arg0 int32) error { + _, err := class.CallMethod(ctx, "incrementX", arg0) + return err +} + +func (class *ClassMyClass) StaticGetStringFromInstance(ctx context.Context, arg0 embind.ClassBase) (string, error) { + res, err := class.CallInstanceMethod(ctx, nil, "getStringFromInstance", arg0) + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} +func ClassMyClassStaticGetStringFromInstance(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (string, error) { + res, err := e.CallStaticClassMethod(ctx, "MyClass", "getStringFromInstance", arg0) + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassMyClass1(e embind.Engine, ctx context.Context, arg0 int32) (*ClassMyClass, error) { + res, err := e.CallPublicSymbol(ctx, "MyClass", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassMyClass), nil +} + +func NewClassMyClass2(e embind.Engine, ctx context.Context, arg0 int32, arg1 string) (*ClassMyClass, error) { + res, err := e.CallPublicSymbol(ctx, "MyClass", arg0, arg1) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassMyClass), nil +} + +type ClassNoExceptClass struct { + embind.ClassBase +} + +func (class *ClassNoExceptClass) Clone(ctx context.Context) (*ClassNoExceptClass, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassNoExceptClass), nil +} + +func (class *ClassNoExceptClass) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassNoExceptClass) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassNoExceptClass) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassNoExceptClass) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassNoExceptClass) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassNoExceptClass) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassNoExceptClass) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassNoExceptClass) GetPropertyX(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "x") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassNoExceptClass) SetPropertyX(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "x", val) +} + +func (class *ClassNoExceptClass) Embind_test_no_except_function(ctx context.Context) error { + _, err := class.CallMethod(ctx, "embind_test_no_except_function") + return err +} + +func (class *ClassNoExceptClass) GetValue(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getValue") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassNoExceptClass) GetValueConst(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getValueConst") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +type ClassNoncopyable struct { + embind.ClassBase +} + +func (class *ClassNoncopyable) Clone(ctx context.Context) (*ClassNoncopyable, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassNoncopyable), nil +} + +func (class *ClassNoncopyable) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassNoncopyable) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassNoncopyable) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassNoncopyable) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassNoncopyable) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassNoncopyable) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassNoncopyable) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassNoncopyable) Method(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "method") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassNoncopyable(e embind.Engine, ctx context.Context) (*ClassNoncopyable, error) { + res, err := e.CallPublicSymbol(ctx, "Noncopyable") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassNoncopyable), nil +} + +type ClassParentClass struct { + embind.ClassBase +} + +func (class *ClassParentClass) Clone(ctx context.Context) (*ClassParentClass, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassParentClass), nil +} + +func (class *ClassParentClass) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassParentClass) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassParentClass) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassParentClass) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassParentClass) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassParentClass) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassParentClass) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassParentClass) GetBigClass(ctx context.Context) (embind.ClassBase, error) { + res, err := class.CallMethod(ctx, "getBigClass") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +func NewClassParentClass(e embind.Engine, ctx context.Context) (*ClassParentClass, error) { + res, err := e.CallPublicSymbol(ctx, "ParentClass") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassParentClass), nil +} + +type ClassPolyBase struct { + embind.ClassBase +} + +func (class *ClassPolyBase) Clone(ctx context.Context) (*ClassPolyBase, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassPolyBase), nil +} + +func (class *ClassPolyBase) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassPolyBase) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassPolyBase) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassPolyBase) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassPolyBase) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassPolyBase) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassPolyBase) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassPolyBase) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassPolyBase) VirtualGetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "virtualGetClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassPolyBase(e embind.Engine, ctx context.Context) (*ClassPolyBase, error) { + res, err := e.CallPublicSymbol(ctx, "PolyBase") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassPolyBase), nil +} + +type ClassPolyDerived struct { + embind.ClassBase +} + +func (class *ClassPolyDerived) Clone(ctx context.Context) (*ClassPolyDerived, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassPolyDerived), nil +} + +func (class *ClassPolyDerived) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassPolyDerived) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassPolyDerived) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassPolyDerived) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassPolyDerived) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassPolyDerived) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassPolyDerived) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassPolyDerived) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassPolyDerived) VirtualGetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "virtualGetClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassPolyDerived) StaticGetPtr(ctx context.Context) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "getPtr") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassPolyDerivedStaticGetPtr(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "PolyDerived", "getPtr") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +func (class *ClassPolyDerived) StaticGetPtrClassName(ctx context.Context) (string, error) { + res, err := class.CallInstanceMethod(ctx, nil, "getPtrClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} +func ClassPolyDerivedStaticGetPtrClassName(e embind.Engine, ctx context.Context) (string, error) { + res, err := e.CallStaticClassMethod(ctx, "PolyDerived", "getPtrClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassPolyDerived) StaticReleasePtr(ctx context.Context) error { + _, err := class.CallInstanceMethod(ctx, nil, "releasePtr") + return err +} +func ClassPolyDerivedStaticReleasePtr(e embind.Engine, ctx context.Context) error { + _, err := e.CallStaticClassMethod(ctx, "PolyDerived", "releasePtr") + return err +} + +func (class *ClassPolyDerived) StaticSetPtrDerived(ctx context.Context) error { + _, err := class.CallInstanceMethod(ctx, nil, "setPtrDerived") + return err +} +func ClassPolyDerivedStaticSetPtrDerived(e embind.Engine, ctx context.Context) error { + _, err := e.CallStaticClassMethod(ctx, "PolyDerived", "setPtrDerived") + return err +} + +func NewClassPolyDerived(e embind.Engine, ctx context.Context) (*ClassPolyDerived, error) { + res, err := e.CallPublicSymbol(ctx, "PolyDerived") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassPolyDerived), nil +} + +type ClassPolyDerivedThrice struct { + embind.ClassBase +} + +func (class *ClassPolyDerivedThrice) Clone(ctx context.Context) (*ClassPolyDerivedThrice, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassPolyDerivedThrice), nil +} + +func (class *ClassPolyDerivedThrice) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassPolyDerivedThrice) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassPolyDerivedThrice) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassPolyDerivedThrice) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassPolyDerivedThrice) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassPolyDerivedThrice) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassPolyDerivedThrice) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassPolyDerivedThrice) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassPolyDerivedThrice) VirtualGetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "virtualGetClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassPolyDerivedThrice) StaticGetPtrClassName(ctx context.Context) (string, error) { + res, err := class.CallInstanceMethod(ctx, nil, "getPtrClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} +func ClassPolyDerivedThriceStaticGetPtrClassName(e embind.Engine, ctx context.Context) (string, error) { + res, err := e.CallStaticClassMethod(ctx, "PolyDerivedThrice", "getPtrClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassPolyDerivedThrice) StaticReleasePtr(ctx context.Context) error { + _, err := class.CallInstanceMethod(ctx, nil, "releasePtr") + return err +} +func ClassPolyDerivedThriceStaticReleasePtr(e embind.Engine, ctx context.Context) error { + _, err := e.CallStaticClassMethod(ctx, "PolyDerivedThrice", "releasePtr") + return err +} + +func (class *ClassPolyDerivedThrice) StaticSetPtrDerived(ctx context.Context) error { + _, err := class.CallInstanceMethod(ctx, nil, "setPtrDerived") + return err +} +func ClassPolyDerivedThriceStaticSetPtrDerived(e embind.Engine, ctx context.Context) error { + _, err := e.CallStaticClassMethod(ctx, "PolyDerivedThrice", "setPtrDerived") + return err +} + +func NewClassPolyDerivedThrice(e embind.Engine, ctx context.Context) (*ClassPolyDerivedThrice, error) { + res, err := e.CallPublicSymbol(ctx, "PolyDerivedThrice") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassPolyDerivedThrice), nil +} + +type ClassPolyDiamondBase struct { + embind.ClassBase +} + +func (class *ClassPolyDiamondBase) Clone(ctx context.Context) (*ClassPolyDiamondBase, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassPolyDiamondBase), nil +} + +func (class *ClassPolyDiamondBase) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassPolyDiamondBase) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassPolyDiamondBase) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassPolyDiamondBase) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassPolyDiamondBase) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassPolyDiamondBase) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassPolyDiamondBase) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassPolyDiamondBase) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassPolyDiamondBase(e embind.Engine, ctx context.Context) (*ClassPolyDiamondBase, error) { + res, err := e.CallPublicSymbol(ctx, "PolyDiamondBase") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassPolyDiamondBase), nil +} + +type ClassPolyDiamondDerived struct { + embind.ClassBase +} + +func (class *ClassPolyDiamondDerived) Clone(ctx context.Context) (*ClassPolyDiamondDerived, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassPolyDiamondDerived), nil +} + +func (class *ClassPolyDiamondDerived) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassPolyDiamondDerived) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassPolyDiamondDerived) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassPolyDiamondDerived) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassPolyDiamondDerived) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassPolyDiamondDerived) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassPolyDiamondDerived) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassPolyDiamondDerived) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassPolyDiamondDerived(e embind.Engine, ctx context.Context) (*ClassPolyDiamondDerived, error) { + res, err := e.CallPublicSymbol(ctx, "PolyDiamondDerived") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassPolyDiamondDerived), nil +} + +type ClassPolyDiamondMultiplyDerived struct { + embind.ClassBase +} + +func (class *ClassPolyDiamondMultiplyDerived) Clone(ctx context.Context) (*ClassPolyDiamondMultiplyDerived, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassPolyDiamondMultiplyDerived), nil +} + +func (class *ClassPolyDiamondMultiplyDerived) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassPolyDiamondMultiplyDerived) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassPolyDiamondMultiplyDerived) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassPolyDiamondMultiplyDerived) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassPolyDiamondMultiplyDerived) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassPolyDiamondMultiplyDerived) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassPolyDiamondMultiplyDerived) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassPolyDiamondMultiplyDerived) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassPolyDiamondMultiplyDerived(e embind.Engine, ctx context.Context) (*ClassPolyDiamondMultiplyDerived, error) { + res, err := e.CallPublicSymbol(ctx, "PolyDiamondMultiplyDerived") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassPolyDiamondMultiplyDerived), nil +} + +type ClassPolyDiamondSiblingDerived struct { + embind.ClassBase +} + +func (class *ClassPolyDiamondSiblingDerived) Clone(ctx context.Context) (*ClassPolyDiamondSiblingDerived, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassPolyDiamondSiblingDerived), nil +} + +func (class *ClassPolyDiamondSiblingDerived) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassPolyDiamondSiblingDerived) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassPolyDiamondSiblingDerived) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassPolyDiamondSiblingDerived) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassPolyDiamondSiblingDerived) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassPolyDiamondSiblingDerived) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassPolyDiamondSiblingDerived) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassPolyDiamondSiblingDerived) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassPolyDiamondSiblingDerived(e embind.Engine, ctx context.Context) (*ClassPolyDiamondSiblingDerived, error) { + res, err := e.CallPublicSymbol(ctx, "PolyDiamondSiblingDerived") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassPolyDiamondSiblingDerived), nil +} + +type ClassPolyMultiplyDerived struct { + embind.ClassBase +} + +func (class *ClassPolyMultiplyDerived) Clone(ctx context.Context) (*ClassPolyMultiplyDerived, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassPolyMultiplyDerived), nil +} + +func (class *ClassPolyMultiplyDerived) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassPolyMultiplyDerived) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassPolyMultiplyDerived) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassPolyMultiplyDerived) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassPolyMultiplyDerived) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassPolyMultiplyDerived) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassPolyMultiplyDerived) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassPolyMultiplyDerived) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassPolyMultiplyDerived) VirtualGetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "virtualGetClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassPolyMultiplyDerived(e embind.Engine, ctx context.Context) (*ClassPolyMultiplyDerived, error) { + res, err := e.CallPublicSymbol(ctx, "PolyMultiplyDerived") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassPolyMultiplyDerived), nil +} + +type ClassPolySecondBase struct { + embind.ClassBase +} + +func (class *ClassPolySecondBase) Clone(ctx context.Context) (*ClassPolySecondBase, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassPolySecondBase), nil +} + +func (class *ClassPolySecondBase) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassPolySecondBase) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassPolySecondBase) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassPolySecondBase) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassPolySecondBase) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassPolySecondBase) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassPolySecondBase) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassPolySecondBase) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassPolySecondBase(e embind.Engine, ctx context.Context) (*ClassPolySecondBase, error) { + res, err := e.CallPublicSymbol(ctx, "PolySecondBase") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassPolySecondBase), nil +} + +type ClassPolySiblingDerived struct { + embind.ClassBase +} + +func (class *ClassPolySiblingDerived) Clone(ctx context.Context) (*ClassPolySiblingDerived, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassPolySiblingDerived), nil +} + +func (class *ClassPolySiblingDerived) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassPolySiblingDerived) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassPolySiblingDerived) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassPolySiblingDerived) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassPolySiblingDerived) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassPolySiblingDerived) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassPolySiblingDerived) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassPolySiblingDerived) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassPolySiblingDerived) VirtualGetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "virtualGetClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassPolySiblingDerived(e embind.Engine, ctx context.Context) (*ClassPolySiblingDerived, error) { + res, err := e.CallPublicSymbol(ctx, "PolySiblingDerived") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassPolySiblingDerived), nil +} + +type ClassSecondBase struct { + embind.ClassBase +} + +func (class *ClassSecondBase) Clone(ctx context.Context) (*ClassSecondBase, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassSecondBase), nil +} + +func (class *ClassSecondBase) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassSecondBase) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassSecondBase) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassSecondBase) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassSecondBase) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassSecondBase) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassSecondBase) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassSecondBase) GetPropertyMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "member") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassSecondBase) SetPropertyMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "member", val) +} + +func (class *ClassSecondBase) GetPropertySecondBaseMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "secondBaseMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassSecondBase) SetPropertySecondBaseMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "secondBaseMember", val) +} + +func (class *ClassSecondBase) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassSecondBase) GetClassNameFromSecondBase(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassNameFromSecondBase") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassSecondBase) GetClassNameNotAvailableInDerivedClasses(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassNameNotAvailableInDerivedClasses") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassSecondBase) GetMember(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassSecondBase) GetSecondBaseMember(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getSecondBaseMember") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassSecondBase) SetMember(ctx context.Context, arg0 int32) error { + _, err := class.CallMethod(ctx, "setMember", arg0) + return err +} + +func (class *ClassSecondBase) SetSecondBaseMember(ctx context.Context, arg0 int32) error { + _, err := class.CallMethod(ctx, "setSecondBaseMember", arg0) + return err +} + +func NewClassSecondBase(e embind.Engine, ctx context.Context) (*ClassSecondBase, error) { + res, err := e.CallPublicSymbol(ctx, "SecondBase") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassSecondBase), nil +} + +type ClassSecondElement struct { + embind.ClassBase +} + +func (class *ClassSecondElement) Clone(ctx context.Context) (*ClassSecondElement, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassSecondElement), nil +} + +func (class *ClassSecondElement) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassSecondElement) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassSecondElement) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassSecondElement) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassSecondElement) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassSecondElement) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassSecondElement) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +type ClassSharedPtrHolder struct { + embind.ClassBase +} + +func (class *ClassSharedPtrHolder) Clone(ctx context.Context) (*ClassSharedPtrHolder, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassSharedPtrHolder), nil +} + +func (class *ClassSharedPtrHolder) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassSharedPtrHolder) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassSharedPtrHolder) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassSharedPtrHolder) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassSharedPtrHolder) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassSharedPtrHolder) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassSharedPtrHolder) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassSharedPtrHolder) Get(ctx context.Context) (embind.ClassBase, error) { + res, err := class.CallMethod(ctx, "get") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +func (class *ClassSharedPtrHolder) Set(ctx context.Context, arg0 embind.ClassBase) error { + _, err := class.CallMethod(ctx, "set", arg0) + return err +} + +func NewClassSharedPtrHolder(e embind.Engine, ctx context.Context) (*ClassSharedPtrHolder, error) { + res, err := e.CallPublicSymbol(ctx, "SharedPtrHolder") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassSharedPtrHolder), nil +} + +type ClassSharedPtrVector struct { + embind.ClassBase +} + +func (class *ClassSharedPtrVector) Clone(ctx context.Context) (*ClassSharedPtrVector, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassSharedPtrVector), nil +} + +func (class *ClassSharedPtrVector) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassSharedPtrVector) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassSharedPtrVector) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassSharedPtrVector) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassSharedPtrVector) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassSharedPtrVector) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassSharedPtrVector) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassSharedPtrVector) Get(ctx context.Context, arg0 uint32) (any, error) { + res, err := class.CallMethod(ctx, "get", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassSharedPtrVector) Push_back(ctx context.Context, arg0 embind.ClassBase) error { + _, err := class.CallMethod(ctx, "push_back", arg0) + return err +} + +func (class *ClassSharedPtrVector) Resize(ctx context.Context, arg0 uint32, arg1 embind.ClassBase) error { + _, err := class.CallMethod(ctx, "resize", arg0, arg1) + return err +} + +func (class *ClassSharedPtrVector) Set(ctx context.Context, arg0 uint32, arg1 embind.ClassBase) (bool, error) { + res, err := class.CallMethod(ctx, "set", arg0, arg1) + if err != nil { + return bool(false), err + } + + if res == nil { + return bool(false), nil + } + + return res.(bool), nil +} + +func (class *ClassSharedPtrVector) Size(ctx context.Context) (uint32, error) { + res, err := class.CallMethod(ctx, "size") + if err != nil { + return uint32(0), err + } + + if res == nil { + return uint32(0), nil + } + + return res.(uint32), nil +} + +func NewClassSharedPtrVector(e embind.Engine, ctx context.Context) (*ClassSharedPtrVector, error) { + res, err := e.CallPublicSymbol(ctx, "SharedPtrVector") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassSharedPtrVector), nil +} + +type ClassSiblingDerived struct { + embind.ClassBase +} + +func (class *ClassSiblingDerived) Clone(ctx context.Context) (*ClassSiblingDerived, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassSiblingDerived), nil +} + +func (class *ClassSiblingDerived) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassSiblingDerived) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassSiblingDerived) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassSiblingDerived) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassSiblingDerived) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassSiblingDerived) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassSiblingDerived) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassSiblingDerived) GetClassName(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "getClassName") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassSiblingDerived(e embind.Engine, ctx context.Context) (*ClassSiblingDerived, error) { + res, err := e.CallPublicSymbol(ctx, "SiblingDerived") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassSiblingDerived), nil +} + +type ClassSmallClass struct { + embind.ClassBase +} + +func (class *ClassSmallClass) Clone(ctx context.Context) (*ClassSmallClass, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassSmallClass), nil +} + +func (class *ClassSmallClass) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassSmallClass) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassSmallClass) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassSmallClass) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassSmallClass) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassSmallClass) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassSmallClass) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassSmallClass) GetPropertyMember(ctx context.Context) (int32, error) { + res, err := class.GetProperty(ctx, "member") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func (class *ClassSmallClass) SetPropertyMember(ctx context.Context, val int32) error { + return class.SetProperty(ctx, "member", val) +} + +func NewClassSmallClass(e embind.Engine, ctx context.Context) (*ClassSmallClass, error) { + res, err := e.CallPublicSymbol(ctx, "SmallClass") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassSmallClass), nil +} + +type ClassStringFunctorString struct { + embind.ClassBase +} + +func (class *ClassStringFunctorString) Clone(ctx context.Context) (*ClassStringFunctorString, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassStringFunctorString), nil +} + +func (class *ClassStringFunctorString) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassStringFunctorString) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassStringFunctorString) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassStringFunctorString) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassStringFunctorString) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassStringFunctorString) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassStringFunctorString) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassStringFunctorString) Opcall(ctx context.Context, arg0 string) (string, error) { + res, err := class.CallMethod(ctx, "opcall", arg0) + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func NewClassStringFunctorString(e embind.Engine, ctx context.Context) (*ClassStringFunctorString, error) { + res, err := e.CallPublicSymbol(ctx, "StringFunctorString") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassStringFunctorString), nil +} + +type ClassStringHolder struct { + embind.ClassBase +} + +func (class *ClassStringHolder) Clone(ctx context.Context) (*ClassStringHolder, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassStringHolder), nil +} + +func (class *ClassStringHolder) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassStringHolder) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassStringHolder) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassStringHolder) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassStringHolder) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassStringHolder) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassStringHolder) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassStringHolder) Get(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "get") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassStringHolder) Get_const_ref(ctx context.Context) (string, error) { + res, err := class.CallMethod(ctx, "get_const_ref") + if err != nil { + return "", err + } + + if res == nil { + return "", nil + } + + return res.(string), nil +} + +func (class *ClassStringHolder) Set(ctx context.Context, arg0 string) error { + _, err := class.CallMethod(ctx, "set", arg0) + return err +} + +func NewClassStringHolder(e embind.Engine, ctx context.Context, arg0 string) (*ClassStringHolder, error) { + res, err := e.CallPublicSymbol(ctx, "StringHolder", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassStringHolder), nil +} + +type ClassStringHolderVector struct { + embind.ClassBase +} + +func (class *ClassStringHolderVector) Clone(ctx context.Context) (*ClassStringHolderVector, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassStringHolderVector), nil +} + +func (class *ClassStringHolderVector) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassStringHolderVector) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassStringHolderVector) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassStringHolderVector) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassStringHolderVector) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassStringHolderVector) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassStringHolderVector) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassStringHolderVector) Get(ctx context.Context, arg0 uint32) (any, error) { + res, err := class.CallMethod(ctx, "get", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassStringHolderVector) Push_back(ctx context.Context, arg0 embind.ClassBase) error { + _, err := class.CallMethod(ctx, "push_back", arg0) + return err +} + +func (class *ClassStringHolderVector) Resize(ctx context.Context, arg0 uint32, arg1 embind.ClassBase) error { + _, err := class.CallMethod(ctx, "resize", arg0, arg1) + return err +} + +func (class *ClassStringHolderVector) Set(ctx context.Context, arg0 uint32, arg1 embind.ClassBase) (bool, error) { + res, err := class.CallMethod(ctx, "set", arg0, arg1) + if err != nil { + return bool(false), err + } + + if res == nil { + return bool(false), nil + } + + return res.(bool), nil +} + +func (class *ClassStringHolderVector) Size(ctx context.Context) (uint32, error) { + res, err := class.CallMethod(ctx, "size") + if err != nil { + return uint32(0), err + } + + if res == nil { + return uint32(0), nil + } + + return res.(uint32), nil +} + +func NewClassStringHolderVector(e embind.Engine, ctx context.Context) (*ClassStringHolderVector, error) { + res, err := e.CallPublicSymbol(ctx, "StringHolderVector") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassStringHolderVector), nil +} + +type ClassStringIntMap struct { + embind.ClassBase +} + +func (class *ClassStringIntMap) Clone(ctx context.Context) (*ClassStringIntMap, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassStringIntMap), nil +} + +func (class *ClassStringIntMap) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassStringIntMap) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassStringIntMap) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassStringIntMap) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassStringIntMap) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassStringIntMap) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassStringIntMap) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassStringIntMap) Get(ctx context.Context, arg0 string) (any, error) { + res, err := class.CallMethod(ctx, "get", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassStringIntMap) Keys(ctx context.Context) (embind.ClassBase, error) { + res, err := class.CallMethod(ctx, "keys") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +func (class *ClassStringIntMap) Set(ctx context.Context, arg0 string, arg1 int32) error { + _, err := class.CallMethod(ctx, "set", arg0, arg1) + return err +} + +func (class *ClassStringIntMap) Size(ctx context.Context) (uint32, error) { + res, err := class.CallMethod(ctx, "size") + if err != nil { + return uint32(0), err + } + + if res == nil { + return uint32(0), nil + } + + return res.(uint32), nil +} + +func NewClassStringIntMap(e embind.Engine, ctx context.Context) (*ClassStringIntMap, error) { + res, err := e.CallPublicSymbol(ctx, "StringIntMap") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassStringIntMap), nil +} + +type ClassStringVector struct { + embind.ClassBase +} + +func (class *ClassStringVector) Clone(ctx context.Context) (*ClassStringVector, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassStringVector), nil +} + +func (class *ClassStringVector) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassStringVector) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassStringVector) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassStringVector) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassStringVector) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassStringVector) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassStringVector) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassStringVector) Get(ctx context.Context, arg0 uint32) (any, error) { + res, err := class.CallMethod(ctx, "get", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassStringVector) Push_back(ctx context.Context, arg0 string) error { + _, err := class.CallMethod(ctx, "push_back", arg0) + return err +} + +func (class *ClassStringVector) Resize(ctx context.Context, arg0 uint32, arg1 string) error { + _, err := class.CallMethod(ctx, "resize", arg0, arg1) + return err +} + +func (class *ClassStringVector) Set(ctx context.Context, arg0 uint32, arg1 string) (bool, error) { + res, err := class.CallMethod(ctx, "set", arg0, arg1) + if err != nil { + return bool(false), err + } + + if res == nil { + return bool(false), nil + } + + return res.(bool), nil +} + +func (class *ClassStringVector) Size(ctx context.Context) (uint32, error) { + res, err := class.CallMethod(ctx, "size") + if err != nil { + return uint32(0), err + } + + if res == nil { + return uint32(0), nil + } + + return res.(uint32), nil +} + +func NewClassStringVector(e embind.Engine, ctx context.Context) (*ClassStringVector, error) { + res, err := e.CallPublicSymbol(ctx, "StringVector") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassStringVector), nil +} + +type ClassUniquePtrLifetimeMock struct { + embind.ClassBase +} + +func (class *ClassUniquePtrLifetimeMock) Clone(ctx context.Context) (*ClassUniquePtrLifetimeMock, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassUniquePtrLifetimeMock), nil +} + +func (class *ClassUniquePtrLifetimeMock) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassUniquePtrLifetimeMock) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassUniquePtrLifetimeMock) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassUniquePtrLifetimeMock) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassUniquePtrLifetimeMock) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassUniquePtrLifetimeMock) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassUniquePtrLifetimeMock) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +type ClassUniquePtrToConstructor struct { + embind.ClassBase +} + +func (class *ClassUniquePtrToConstructor) Clone(ctx context.Context) (*ClassUniquePtrToConstructor, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassUniquePtrToConstructor), nil +} + +func (class *ClassUniquePtrToConstructor) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassUniquePtrToConstructor) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassUniquePtrToConstructor) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassUniquePtrToConstructor) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassUniquePtrToConstructor) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassUniquePtrToConstructor) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassUniquePtrToConstructor) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassUniquePtrToConstructor) GetValue(ctx context.Context) (int32, error) { + res, err := class.CallMethod(ctx, "getValue") + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +type ClassValHolder struct { + embind.ClassBase +} + +func (class *ClassValHolder) Clone(ctx context.Context) (*ClassValHolder, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassValHolder), nil +} + +func (class *ClassValHolder) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassValHolder) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassValHolder) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassValHolder) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassValHolder) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassValHolder) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassValHolder) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassValHolder) GetPropertyFunction_val(ctx context.Context) (any, error) { + res, err := class.GetProperty(ctx, "function_val") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} +func (class *ClassValHolder) SetPropertyFunction_val(ctx context.Context, val any) error { + return class.SetProperty(ctx, "function_val", val) +} + +func (class *ClassValHolder) GetPropertyFunctor_val(ctx context.Context) (any, error) { + res, err := class.GetProperty(ctx, "functor_val") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} +func (class *ClassValHolder) SetPropertyFunctor_val(ctx context.Context, val any) error { + return class.SetProperty(ctx, "functor_val", val) +} + +func (class *ClassValHolder) GetPropertyReadonly_function_val(ctx context.Context) (any, error) { + res, err := class.GetProperty(ctx, "readonly_function_val") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassValHolder) GetPropertyReadonly_functor_val(ctx context.Context) (any, error) { + res, err := class.GetProperty(ctx, "readonly_functor_val") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassValHolder) GetPropertyVal(ctx context.Context) (any, error) { + res, err := class.GetProperty(ctx, "val") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} +func (class *ClassValHolder) SetPropertyVal(ctx context.Context, val any) error { + return class.SetProperty(ctx, "val", val) +} + +func (class *ClassValHolder) GetPropertyVal_readonly(ctx context.Context) (any, error) { + res, err := class.GetProperty(ctx, "val_readonly") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassValHolder) GetConstVal(ctx context.Context) (any, error) { + res, err := class.CallMethod(ctx, "getConstVal") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassValHolder) GetVal(ctx context.Context) (any, error) { + res, err := class.CallMethod(ctx, "getVal") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassValHolder) GetValConstRef(ctx context.Context) (any, error) { + res, err := class.CallMethod(ctx, "getValConstRef") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassValHolder) GetValFunction(ctx context.Context) (any, error) { + res, err := class.CallMethod(ctx, "getValFunction") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassValHolder) GetValFunctor(ctx context.Context) (any, error) { + res, err := class.CallMethod(ctx, "getValFunctor") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassValHolder) GetValNonConst(ctx context.Context) (any, error) { + res, err := class.CallMethod(ctx, "getValNonConst") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassValHolder) GetValNonMember(ctx context.Context) (any, error) { + res, err := class.CallMethod(ctx, "getValNonMember") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassValHolder) SetEmpty(ctx context.Context) error { + _, err := class.CallMethod(ctx, "setEmpty") + return err +} + +func (class *ClassValHolder) SetVal(ctx context.Context, arg0 any) error { + _, err := class.CallMethod(ctx, "setVal", arg0) + return err +} + +func (class *ClassValHolder) SetValFunction(ctx context.Context, arg0 any) error { + _, err := class.CallMethod(ctx, "setValFunction", arg0) + return err +} + +func (class *ClassValHolder) SetValFunctor(ctx context.Context, arg0 any) error { + _, err := class.CallMethod(ctx, "setValFunctor", arg0) + return err +} + +func (class *ClassValHolder) StaticGet_via_raw_pointer(ctx context.Context, arg0 embind.ClassBase) (any, error) { + res, err := class.CallInstanceMethod(ctx, nil, "get_via_raw_pointer", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} +func ClassValHolderStaticGet_via_raw_pointer(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (any, error) { + res, err := e.CallStaticClassMethod(ctx, "ValHolder", "get_via_raw_pointer", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassValHolder) StaticMakeConst(ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "makeConst", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassValHolderStaticMakeConst(e embind.Engine, ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "ValHolder", "makeConst", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +func (class *ClassValHolder) StaticMakeValHolder(ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := class.CallInstanceMethod(ctx, nil, "makeValHolder", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} +func ClassValHolderStaticMakeValHolder(e embind.Engine, ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := e.CallStaticClassMethod(ctx, "ValHolder", "makeValHolder", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +func (class *ClassValHolder) StaticSet_via_raw_pointer(ctx context.Context, arg0 embind.ClassBase, arg1 any) error { + _, err := class.CallInstanceMethod(ctx, nil, "set_via_raw_pointer", arg0, arg1) + return err +} +func ClassValHolderStaticSet_via_raw_pointer(e embind.Engine, ctx context.Context, arg0 embind.ClassBase, arg1 any) error { + _, err := e.CallStaticClassMethod(ctx, "ValHolder", "set_via_raw_pointer", arg0, arg1) + return err +} + +func (class *ClassValHolder) StaticSome_class_method(ctx context.Context, arg0 int32) (int32, error) { + res, err := class.CallInstanceMethod(ctx, nil, "some_class_method", arg0) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} +func ClassValHolderStaticSome_class_method(e embind.Engine, ctx context.Context, arg0 int32) (int32, error) { + res, err := e.CallStaticClassMethod(ctx, "ValHolder", "some_class_method", arg0) + if err != nil { + return int32(0), err + } + + if res == nil { + return int32(0), nil + } + + return res.(int32), nil +} + +func (class *ClassValHolder) StaticTransfer_via_raw_pointer(ctx context.Context, arg0 embind.ClassBase, arg1 embind.ClassBase) error { + _, err := class.CallInstanceMethod(ctx, nil, "transfer_via_raw_pointer", arg0, arg1) + return err +} +func ClassValHolderStaticTransfer_via_raw_pointer(e embind.Engine, ctx context.Context, arg0 embind.ClassBase, arg1 embind.ClassBase) error { + _, err := e.CallStaticClassMethod(ctx, "ValHolder", "transfer_via_raw_pointer", arg0, arg1) + return err +} + +func NewClassValHolder(e embind.Engine, ctx context.Context, arg0 any) (*ClassValHolder, error) { + res, err := e.CallPublicSymbol(ctx, "ValHolder", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassValHolder), nil +} + +type ClassVectorHolder struct { + embind.ClassBase +} + +func (class *ClassVectorHolder) Clone(ctx context.Context) (*ClassVectorHolder, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassVectorHolder), nil +} + +func (class *ClassVectorHolder) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassVectorHolder) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassVectorHolder) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassVectorHolder) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassVectorHolder) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassVectorHolder) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassVectorHolder) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassVectorHolder) Get(ctx context.Context) (embind.ClassBase, error) { + res, err := class.CallMethod(ctx, "get") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(embind.ClassBase), nil +} + +func (class *ClassVectorHolder) Set(ctx context.Context, arg0 embind.ClassBase) error { + _, err := class.CallMethod(ctx, "set", arg0) + return err +} + +func NewClassVectorHolder(e embind.Engine, ctx context.Context) (*ClassVectorHolder, error) { + res, err := e.CallPublicSymbol(ctx, "VectorHolder") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassVectorHolder), nil +} + +type ClassVectorUnsigned struct { + embind.ClassBase +} + +func (class *ClassVectorUnsigned) Clone(ctx context.Context) (*ClassVectorUnsigned, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassVectorUnsigned), nil +} + +func (class *ClassVectorUnsigned) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassVectorUnsigned) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassVectorUnsigned) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassVectorUnsigned) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassVectorUnsigned) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassVectorUnsigned) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassVectorUnsigned) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassVectorUnsigned) Get(ctx context.Context, arg0 uint32) (any, error) { + res, err := class.CallMethod(ctx, "get", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassVectorUnsigned) Push_back(ctx context.Context, arg0 uint32) error { + _, err := class.CallMethod(ctx, "push_back", arg0) + return err +} + +func (class *ClassVectorUnsigned) Resize(ctx context.Context, arg0 uint32, arg1 uint32) error { + _, err := class.CallMethod(ctx, "resize", arg0, arg1) + return err +} + +func (class *ClassVectorUnsigned) Set(ctx context.Context, arg0 uint32, arg1 uint32) (bool, error) { + res, err := class.CallMethod(ctx, "set", arg0, arg1) + if err != nil { + return bool(false), err + } + + if res == nil { + return bool(false), nil + } + + return res.(bool), nil +} + +func (class *ClassVectorUnsigned) Size(ctx context.Context) (uint32, error) { + res, err := class.CallMethod(ctx, "size") + if err != nil { + return uint32(0), err + } + + if res == nil { + return uint32(0), nil + } + + return res.(uint32), nil +} + +func NewClassVectorUnsigned(e embind.Engine, ctx context.Context) (*ClassVectorUnsigned, error) { + res, err := e.CallPublicSymbol(ctx, "VectorUnsigned") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassVectorUnsigned), nil +} + +type ClassVectorUnsignedChar struct { + embind.ClassBase +} + +func (class *ClassVectorUnsignedChar) Clone(ctx context.Context) (*ClassVectorUnsignedChar, error) { + res, err := class.CloneInstance(ctx, class) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(*ClassVectorUnsignedChar), nil +} + +func (class *ClassVectorUnsignedChar) Delete(ctx context.Context) error { + return class.DeleteInstance(ctx, class) +} + +func (class *ClassVectorUnsignedChar) DeleteLater(ctx context.Context) (embind.ClassBase, error) { + return class.DeleteInstanceLater(ctx, class) +} + +func (class *ClassVectorUnsignedChar) IsDeleted(ctx context.Context) bool { + return class.IsInstanceDeleted(ctx, class) +} + +func (class *ClassVectorUnsignedChar) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) { + return class.IsAliasOfInstance(ctx, class, second) +} + +func (class *ClassVectorUnsignedChar) CallMethod(ctx context.Context, name string, arguments ...any) (any, error) { + return class.CallInstanceMethod(ctx, class, name, arguments...) +} + +func (class *ClassVectorUnsignedChar) SetProperty(ctx context.Context, name string, value any) error { + return class.SetInstanceProperty(ctx, class, name, value) +} + +func (class *ClassVectorUnsignedChar) GetProperty(ctx context.Context, name string) (any, error) { + return class.GetInstanceProperty(ctx, class, name) +} + +func (class *ClassVectorUnsignedChar) Get(ctx context.Context, arg0 uint32) (any, error) { + res, err := class.CallMethod(ctx, "get", arg0) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(any), nil +} + +func (class *ClassVectorUnsignedChar) Push_back(ctx context.Context, arg0 uint8) error { + _, err := class.CallMethod(ctx, "push_back", arg0) + return err +} + +func (class *ClassVectorUnsignedChar) Resize(ctx context.Context, arg0 uint32, arg1 uint8) error { + _, err := class.CallMethod(ctx, "resize", arg0, arg1) + return err +} + +func (class *ClassVectorUnsignedChar) Set(ctx context.Context, arg0 uint32, arg1 uint8) (bool, error) { + res, err := class.CallMethod(ctx, "set", arg0, arg1) + if err != nil { + return bool(false), err + } + + if res == nil { + return bool(false), nil + } + + return res.(bool), nil +} + +func (class *ClassVectorUnsignedChar) Size(ctx context.Context) (uint32, error) { + res, err := class.CallMethod(ctx, "size") + if err != nil { + return uint32(0), err + } + + if res == nil { + return uint32(0), nil + } + + return res.(uint32), nil +} + +func NewClassVectorUnsignedChar(e embind.Engine, ctx context.Context) (*ClassVectorUnsignedChar, error) { + res, err := e.CallPublicSymbol(ctx, "VectorUnsignedChar") + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return res.(*ClassVectorUnsignedChar), nil +} diff --git a/tests/generated/constants.go b/tests/generated/constants.go new file mode 100644 index 0000000..a6de19c --- /dev/null +++ b/tests/generated/constants.go @@ -0,0 +1,46 @@ +// Code generated by wazero-emscripten-embind, DO NOT EDIT. +package generated + +const Constant_INT_CONSTANT = int32(10) + +const Constant_SOME_CONSTANT_1 = bool(false) + +const Constant_SOME_CONSTANT_10 = uint16(10) + +const Constant_SOME_CONSTANT_11 = uint8(11) + +const Constant_SOME_CONSTANT_12 = uint32(12) + +const Constant_SOME_CONSTANT_13 = string("TestWideString") + +const Constant_SOME_CONSTANT_14 = bool(true) + +const Constant_SOME_CONSTANT_15 = uint64(15) + +const Constant_SOME_CONSTANT_2 = float32(2) + +const Constant_SOME_CONSTANT_3 = float64(3) + +const Constant_SOME_CONSTANT_4 = int32(4) + +const Constant_SOME_CONSTANT_5 = string("TestString") + +const Constant_SOME_CONSTANT_6 = int8(67) + +const Constant_SOME_CONSTANT_7 = int64(7) + +const Constant_SOME_CONSTANT_8 = uint16(8) + +const Constant_SOME_CONSTANT_9 = uint32(9) + +const Constant_STATIC_CONST_INTEGER_VALUE_1 = int32(1) + +const Constant_STATIC_CONST_INTEGER_VALUE_1000 = int32(1000) + +const Constant_STRING_CONSTANT = string("some string") + +var Constant_VALUE_ARRAY_CONSTANT = []interface{}{1, 2, 3, 4} // Not all types can be actual constants in Go. + +var Constant_VALUE_OBJECT_CONSTANT = map[string]interface{}{"w": 4, "x": 1, "y": 2, "z": 3} // Not all types can be actual constants in Go. + +const Constant_hasUnboundTypeNames = bool(true) diff --git a/tests/generated/engine.go b/tests/generated/engine.go new file mode 100644 index 0000000..f3f5219 --- /dev/null +++ b/tests/generated/engine.go @@ -0,0 +1,347 @@ +// Code generated by wazero-emscripten-embind, DO NOT EDIT. +package generated + +import "github.com/jerbob92/wazero-emscripten-embind" + +func Attach(e embind.Engine) error { + if err := e.RegisterConstant("INT_CONSTANT", Constant_INT_CONSTANT); err != nil { + return err + } + if err := e.RegisterConstant("SOME_CONSTANT_1", Constant_SOME_CONSTANT_1); err != nil { + return err + } + if err := e.RegisterConstant("SOME_CONSTANT_10", Constant_SOME_CONSTANT_10); err != nil { + return err + } + if err := e.RegisterConstant("SOME_CONSTANT_11", Constant_SOME_CONSTANT_11); err != nil { + return err + } + if err := e.RegisterConstant("SOME_CONSTANT_12", Constant_SOME_CONSTANT_12); err != nil { + return err + } + if err := e.RegisterConstant("SOME_CONSTANT_13", Constant_SOME_CONSTANT_13); err != nil { + return err + } + if err := e.RegisterConstant("SOME_CONSTANT_14", Constant_SOME_CONSTANT_14); err != nil { + return err + } + if err := e.RegisterConstant("SOME_CONSTANT_15", Constant_SOME_CONSTANT_15); err != nil { + return err + } + if err := e.RegisterConstant("SOME_CONSTANT_2", Constant_SOME_CONSTANT_2); err != nil { + return err + } + if err := e.RegisterConstant("SOME_CONSTANT_3", Constant_SOME_CONSTANT_3); err != nil { + return err + } + if err := e.RegisterConstant("SOME_CONSTANT_4", Constant_SOME_CONSTANT_4); err != nil { + return err + } + if err := e.RegisterConstant("SOME_CONSTANT_5", Constant_SOME_CONSTANT_5); err != nil { + return err + } + if err := e.RegisterConstant("SOME_CONSTANT_6", Constant_SOME_CONSTANT_6); err != nil { + return err + } + if err := e.RegisterConstant("SOME_CONSTANT_7", Constant_SOME_CONSTANT_7); err != nil { + return err + } + if err := e.RegisterConstant("SOME_CONSTANT_8", Constant_SOME_CONSTANT_8); err != nil { + return err + } + if err := e.RegisterConstant("SOME_CONSTANT_9", Constant_SOME_CONSTANT_9); err != nil { + return err + } + if err := e.RegisterConstant("STATIC_CONST_INTEGER_VALUE_1", Constant_STATIC_CONST_INTEGER_VALUE_1); err != nil { + return err + } + if err := e.RegisterConstant("STATIC_CONST_INTEGER_VALUE_1000", Constant_STATIC_CONST_INTEGER_VALUE_1000); err != nil { + return err + } + if err := e.RegisterConstant("STRING_CONSTANT", Constant_STRING_CONSTANT); err != nil { + return err + } + if err := e.RegisterConstant("VALUE_ARRAY_CONSTANT", Constant_VALUE_ARRAY_CONSTANT); err != nil { + return err + } + if err := e.RegisterConstant("VALUE_OBJECT_CONSTANT", Constant_VALUE_OBJECT_CONSTANT); err != nil { + return err + } + if err := e.RegisterConstant("hasUnboundTypeNames", Constant_hasUnboundTypeNames); err != nil { + return err + } + if err := e.RegisterClass("AbstractClass", &ClassAbstractClass{}); err != nil { + return err + } + if err := e.RegisterClass("AbstractClassWithConstructor", &ClassAbstractClassWithConstructor{}); err != nil { + return err + } + if err := e.RegisterClass("AbstractClassWithConstructorWrapper", &ClassAbstractClassWithConstructorWrapper{}); err != nil { + return err + } + if err := e.RegisterClass("AbstractClassWrapper", &ClassAbstractClassWrapper{}); err != nil { + return err + } + if err := e.RegisterClass("Base", &ClassBase{}); err != nil { + return err + } + if err := e.RegisterClass("Base1", &ClassBase1{}); err != nil { + return err + } + if err := e.RegisterClass("Base2", &ClassBase2{}); err != nil { + return err + } + if err := e.RegisterClass("BaseClass", &ClassBaseClass{}); err != nil { + return err + } + if err := e.RegisterClass("BaseClassWrapper", &ClassBaseClassWrapper{}); err != nil { + return err + } + if err := e.RegisterClass("BigClass", &ClassBigClass{}); err != nil { + return err + } + if err := e.RegisterClass("BoundClass", &ClassBoundClass{}); err != nil { + return err + } + if err := e.RegisterClass("C", &ClassC{}); err != nil { + return err + } + if err := e.RegisterClass("CharVector", &ClassCharVector{}); err != nil { + return err + } + if err := e.RegisterClass("ConstAndNonConst", &ClassConstAndNonConst{}); err != nil { + return err + } + if err := e.RegisterClass("ConstructFromFunctionObject", &ClassConstructFromFunctionObject{}); err != nil { + return err + } + if err := e.RegisterClass("ConstructFromStdFunction", &ClassConstructFromStdFunction{}); err != nil { + return err + } + if err := e.RegisterClass("ContainsTemplatedMemberClass", &ClassContainsTemplatedMemberClass{}); err != nil { + return err + } + if err := e.RegisterClass("CustomStruct", &ClassCustomStruct{}); err != nil { + return err + } + if err := e.RegisterClass("Derived", &ClassDerived{}); err != nil { + return err + } + if err := e.RegisterClass("DerivedClass", &ClassDerivedClass{}); err != nil { + return err + } + if err := e.RegisterClass("DerivedHolder", &ClassDerivedHolder{}); err != nil { + return err + } + if err := e.RegisterClass("DerivedThrice", &ClassDerivedThrice{}); err != nil { + return err + } + if err := e.RegisterClass("DerivedTwice", &ClassDerivedTwice{}); err != nil { + return err + } + if err := e.RegisterClass("DerivedWithMixin", &ClassDerivedWithMixin{}); err != nil { + return err + } + if err := e.RegisterClass("DerivedWithOffset", &ClassDerivedWithOffset{}); err != nil { + return err + } + if err := e.RegisterClass("DummyForOverloads", &ClassDummyForOverloads{}); err != nil { + return err + } + if err := e.RegisterClass("DummyForPointer", &ClassDummyForPointer{}); err != nil { + return err + } + if err := e.RegisterClass("EmValVector", &ClassEmValVector{}); err != nil { + return err + } + if err := e.RegisterClass("FirstElement", &ClassFirstElement{}); err != nil { + return err + } + if err := e.RegisterClass("FloatVector", &ClassFloatVector{}); err != nil { + return err + } + if err := e.RegisterClass("Foo", &ClassFoo{}); err != nil { + return err + } + if err := e.RegisterClass("HasConstructorUsingUnboundArgument", &ClassHasConstructorUsingUnboundArgument{}); err != nil { + return err + } + if err := e.RegisterClass("HasExternalConstructor", &ClassHasExternalConstructor{}); err != nil { + return err + } + if err := e.RegisterClass("HasReadOnlyProperty", &ClassHasReadOnlyProperty{}); err != nil { + return err + } + if err := e.RegisterClass("HasStaticMember", &ClassHasStaticMember{}); err != nil { + return err + } + if err := e.RegisterClass("HasTwoBases", &ClassHasTwoBases{}); err != nil { + return err + } + if err := e.RegisterClass("HeldAbstractClass", &ClassHeldAbstractClass{}); err != nil { + return err + } + if err := e.RegisterClass("HeldAbstractClassWrapper", &ClassHeldAbstractClassWrapper{}); err != nil { + return err + } + if err := e.RegisterClass("HeldByCustomSmartPtr", &ClassHeldByCustomSmartPtr{}); err != nil { + return err + } + if err := e.RegisterClass("HeldBySmartPtr", &ClassHeldBySmartPtr{}); err != nil { + return err + } + if err := e.RegisterClass("IntTemplateClass", &ClassIntTemplateClass{}); err != nil { + return err + } + if err := e.RegisterClass("IntegerVector", &ClassIntegerVector{}); err != nil { + return err + } + if err := e.RegisterClass("IntegerVectorVector", &ClassIntegerVectorVector{}); err != nil { + return err + } + if err := e.RegisterClass("Interface", &ClassInterface{}); err != nil { + return err + } + if err := e.RegisterClass("InterfaceWrapper", &ClassInterfaceWrapper{}); err != nil { + return err + } + if err := e.RegisterClass("IntrusiveClass", &ClassIntrusiveClass{}); err != nil { + return err + } + if err := e.RegisterClass("IntrusiveClassHolder", &ClassIntrusiveClassHolder{}); err != nil { + return err + } + if err := e.RegisterClass("IntrusiveClassWrapper", &ClassIntrusiveClassWrapper{}); err != nil { + return err + } + if err := e.RegisterClass("map_int__string_", &ClassMap_int__string_{}); err != nil { + return err + } + if err := e.RegisterClass("MultipleAccessors", &ClassMultipleAccessors{}); err != nil { + return err + } + if err := e.RegisterClass("MultipleCtors", &ClassMultipleCtors{}); err != nil { + return err + } + if err := e.RegisterClass("MultipleOverloads", &ClassMultipleOverloads{}); err != nil { + return err + } + if err := e.RegisterClass("MultipleOverloadsDependingOnDummy", &ClassMultipleOverloadsDependingOnDummy{}); err != nil { + return err + } + if err := e.RegisterClass("MultipleOverloadsDerived", &ClassMultipleOverloadsDerived{}); err != nil { + return err + } + if err := e.RegisterClass("MultipleSmartCtors", &ClassMultipleSmartCtors{}); err != nil { + return err + } + if err := e.RegisterClass("MultiplyDerived", &ClassMultiplyDerived{}); err != nil { + return err + } + if err := e.RegisterClass("MyClass", &ClassMyClass{}); err != nil { + return err + } + if err := e.RegisterClass("NoExceptClass", &ClassNoExceptClass{}); err != nil { + return err + } + if err := e.RegisterClass("Noncopyable", &ClassNoncopyable{}); err != nil { + return err + } + if err := e.RegisterClass("ParentClass", &ClassParentClass{}); err != nil { + return err + } + if err := e.RegisterClass("PolyBase", &ClassPolyBase{}); err != nil { + return err + } + if err := e.RegisterClass("PolyDerived", &ClassPolyDerived{}); err != nil { + return err + } + if err := e.RegisterClass("PolyDerivedThrice", &ClassPolyDerivedThrice{}); err != nil { + return err + } + if err := e.RegisterClass("PolyDiamondBase", &ClassPolyDiamondBase{}); err != nil { + return err + } + if err := e.RegisterClass("PolyDiamondDerived", &ClassPolyDiamondDerived{}); err != nil { + return err + } + if err := e.RegisterClass("PolyDiamondMultiplyDerived", &ClassPolyDiamondMultiplyDerived{}); err != nil { + return err + } + if err := e.RegisterClass("PolyDiamondSiblingDerived", &ClassPolyDiamondSiblingDerived{}); err != nil { + return err + } + if err := e.RegisterClass("PolyMultiplyDerived", &ClassPolyMultiplyDerived{}); err != nil { + return err + } + if err := e.RegisterClass("PolySecondBase", &ClassPolySecondBase{}); err != nil { + return err + } + if err := e.RegisterClass("PolySiblingDerived", &ClassPolySiblingDerived{}); err != nil { + return err + } + if err := e.RegisterClass("SecondBase", &ClassSecondBase{}); err != nil { + return err + } + if err := e.RegisterClass("SecondElement", &ClassSecondElement{}); err != nil { + return err + } + if err := e.RegisterClass("SharedPtrHolder", &ClassSharedPtrHolder{}); err != nil { + return err + } + if err := e.RegisterClass("SharedPtrVector", &ClassSharedPtrVector{}); err != nil { + return err + } + if err := e.RegisterClass("SiblingDerived", &ClassSiblingDerived{}); err != nil { + return err + } + if err := e.RegisterClass("SmallClass", &ClassSmallClass{}); err != nil { + return err + } + if err := e.RegisterClass("StringFunctorString", &ClassStringFunctorString{}); err != nil { + return err + } + if err := e.RegisterClass("StringHolder", &ClassStringHolder{}); err != nil { + return err + } + if err := e.RegisterClass("StringHolderVector", &ClassStringHolderVector{}); err != nil { + return err + } + if err := e.RegisterClass("StringIntMap", &ClassStringIntMap{}); err != nil { + return err + } + if err := e.RegisterClass("StringVector", &ClassStringVector{}); err != nil { + return err + } + if err := e.RegisterClass("UniquePtrLifetimeMock", &ClassUniquePtrLifetimeMock{}); err != nil { + return err + } + if err := e.RegisterClass("UniquePtrToConstructor", &ClassUniquePtrToConstructor{}); err != nil { + return err + } + if err := e.RegisterClass("ValHolder", &ClassValHolder{}); err != nil { + return err + } + if err := e.RegisterClass("VectorHolder", &ClassVectorHolder{}); err != nil { + return err + } + if err := e.RegisterClass("VectorUnsigned", &ClassVectorUnsigned{}); err != nil { + return err + } + if err := e.RegisterClass("VectorUnsignedChar", &ClassVectorUnsignedChar{}); err != nil { + return err + } + if err := e.RegisterEnum("Enum", EnumEnum(0)); err != nil { + return err + } + if err := e.RegisterEnum("EnumClass", EnumEnumClass(0)); err != nil { + return err + } + if err := e.RegisterEnum("NewStyle", EnumNewStyle(0)); err != nil { + return err + } + if err := e.RegisterEnum("OldStyle", EnumOldStyle(0)); err != nil { + return err + } + return nil +} diff --git a/tests/generated/enums.go b/tests/generated/enums.go new file mode 100644 index 0000000..d567d57 --- /dev/null +++ b/tests/generated/enums.go @@ -0,0 +1,74 @@ +// Code generated by wazero-emscripten-embind, DO NOT EDIT. +package generated + +type EnumEnum uint32 + +const ( + EnumEnum_ONE EnumEnum = 0 + EnumEnum_TWO EnumEnum = 1 +) + +func (enum EnumEnum) Values() map[string]any { + return map[string]any{ + "ONE": EnumEnum_ONE, + "TWO": EnumEnum_TWO, + } +} + +func (enum EnumEnum) Type() any { + return EnumEnum(0) +} + +type EnumEnumClass int8 + +const ( + EnumEnumClass_ONE EnumEnumClass = 0 + EnumEnumClass_TWO EnumEnumClass = 1 +) + +func (enum EnumEnumClass) Values() map[string]any { + return map[string]any{ + "ONE": EnumEnumClass_ONE, + "TWO": EnumEnumClass_TWO, + } +} + +func (enum EnumEnumClass) Type() any { + return EnumEnumClass(0) +} + +type EnumNewStyle int32 + +const ( + EnumNewStyle_ONE EnumNewStyle = 0 + EnumNewStyle_TWO EnumNewStyle = 1 +) + +func (enum EnumNewStyle) Values() map[string]any { + return map[string]any{ + "ONE": EnumNewStyle_ONE, + "TWO": EnumNewStyle_TWO, + } +} + +func (enum EnumNewStyle) Type() any { + return EnumNewStyle(0) +} + +type EnumOldStyle uint32 + +const ( + EnumOldStyle_ONE EnumOldStyle = 0 + EnumOldStyle_TWO EnumOldStyle = 1 +) + +func (enum EnumOldStyle) Values() map[string]any { + return map[string]any{ + "ONE": EnumOldStyle_ONE, + "TWO": EnumOldStyle_TWO, + } +} + +func (enum EnumOldStyle) Type() any { + return EnumOldStyle(0) +} diff --git a/tests/generated/functions.go b/tests/generated/functions.go new file mode 100644 index 0000000..d765fa7 --- /dev/null +++ b/tests/generated/functions.go @@ -0,0 +1,3383 @@ +// Code generated by wazero-emscripten-embind, DO NOT EDIT. +package generated + +import ( + "context" + + "github.com/jerbob92/wazero-emscripten-embind" +) + +func AbstractClass(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "AbstractClass") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func AbstractClassWithConstructor(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "AbstractClassWithConstructor") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func AbstractClassWithConstructorWrapper(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "AbstractClassWithConstructorWrapper") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func AbstractClassWrapper(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "AbstractClassWrapper") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Base(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "Base") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Base1(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "Base1") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Base2(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "Base2") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func BaseClass(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "BaseClass") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func BaseClassWrapper(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "BaseClassWrapper") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func BigClass(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "BigClass") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Bool_return_bool(e embind.Engine, ctx context.Context, arg0 bool) (bool, error) { + res, err := e.CallPublicSymbol(ctx, "bool_return_bool", arg0) + if err != nil { + return bool(false), err + } + if res == nil { + return bool(false), nil + } + return res.(bool), nil +} + +func Bool_return_false(e embind.Engine, ctx context.Context) (bool, error) { + res, err := e.CallPublicSymbol(ctx, "bool_return_false") + if err != nil { + return bool(false), err + } + if res == nil { + return bool(false), nil + } + return res.(bool), nil +} + +func Bool_return_true(e embind.Engine, ctx context.Context) (bool, error) { + res, err := e.CallPublicSymbol(ctx, "bool_return_true") + if err != nil { + return bool(false), err + } + if res == nil { + return bool(false), nil + } + return res.(bool), nil +} + +func BoundClass(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "BoundClass") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func C(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "C") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func CallAbstractMethod(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (string, error) { + res, err := e.CallPublicSymbol(ctx, "callAbstractMethod", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func CallAbstractMethod2(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (string, error) { + res, err := e.CallPublicSymbol(ctx, "callAbstractMethod2", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func CallDifferentArguments(e embind.Engine, ctx context.Context, arg0 embind.ClassBase, arg1 int32, arg2 float64, arg3 uint8, arg4 float64, arg5 string) error { + _, err := e.CallPublicSymbol(ctx, "callDifferentArguments", arg0, arg1, arg2, arg3, arg4, arg5) + return err +} + +func CallOptionalMethod(e embind.Engine, ctx context.Context, arg0 embind.ClassBase, arg1 string) (string, error) { + res, err := e.CallPublicSymbol(ctx, "callOptionalMethod", arg0, arg1) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func CallReturnsSharedPtrMethod(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) error { + _, err := e.CallPublicSymbol(ctx, "callReturnsSharedPtrMethod", arg0) + return err +} + +func CallWithMemoryView(e embind.Engine, ctx context.Context, arg0 any) error { + _, err := e.CallPublicSymbol(ctx, "callWithMemoryView", arg0) + return err +} + +func Call_StringHolder_func(e embind.Engine, ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "call_StringHolder_func", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func CharVector(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "CharVector") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Char_return_char(e embind.Engine, ctx context.Context, arg0 int8) (int8, error) { + res, err := e.CallPublicSymbol(ctx, "char_return_char", arg0) + if err != nil { + return int8(0), err + } + if res == nil { + return int8(0), nil + } + return res.(int8), nil +} + +func Char_to_string(e embind.Engine, ctx context.Context, arg0 int8) (string, error) { + res, err := e.CallPublicSymbol(ctx, "char_to_string", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Clear_StringHolder(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) error { + _, err := e.CallPublicSymbol(ctx, "clear_StringHolder", arg0) + return err +} + +func ConstAndNonConst(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "ConstAndNonConst") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Const_ref_adder(e embind.Engine, ctx context.Context, arg0 int32, arg1 float32) (float32, error) { + res, err := e.CallPublicSymbol(ctx, "const_ref_adder", arg0, arg1) + if err != nil { + return float32(0), err + } + if res == nil { + return float32(0), nil + } + return res.(float32), nil +} + +func ConstructFromFunctionObject(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "ConstructFromFunctionObject") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func ConstructFromStdFunction(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "ConstructFromStdFunction") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Construct_with_6_arguments(e embind.Engine, ctx context.Context, arg0 any) (any, error) { + res, err := e.CallPublicSymbol(ctx, "construct_with_6_arguments", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Construct_with_arguments_before_and_after_memory_growth(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "construct_with_arguments_before_and_after_memory_growth") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Construct_with_ints_and_float(e embind.Engine, ctx context.Context, arg0 any) (any, error) { + res, err := e.CallPublicSymbol(ctx, "construct_with_ints_and_float", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Construct_with_memory_view(e embind.Engine, ctx context.Context, arg0 any) (any, error) { + res, err := e.CallPublicSymbol(ctx, "construct_with_memory_view", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func ContainsTemplatedMemberClass(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "ContainsTemplatedMemberClass") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func CustomStruct(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "CustomStruct") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Derived(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "Derived") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func DerivedClass(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "DerivedClass") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func DerivedHolder(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "DerivedHolder") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func DerivedThrice(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "DerivedThrice") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func DerivedTwice(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "DerivedTwice") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func DerivedWithMixin(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "DerivedWithMixin") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func DerivedWithOffset(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "DerivedWithOffset") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func DoCustomMarshalTest(e embind.Engine, ctx context.Context) error { + _, err := e.CallPublicSymbol(ctx, "doCustomMarshalTest") + return err +} + +func DoEmval(e embind.Engine, ctx context.Context) (string, error) { + res, err := e.CallPublicSymbol(ctx, "doEmval") + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Double_return_double(e embind.Engine, ctx context.Context, arg0 float64) (float64, error) { + res, err := e.CallPublicSymbol(ctx, "double_return_double", arg0) + if err != nil { + return float64(0), err + } + if res == nil { + return float64(0), nil + } + return res.(float64), nil +} + +func DummyForOverloads(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "DummyForOverloads") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func DummyForPointer(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "DummyForPointer") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func EmValVector(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "EmValVector") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_attempt_to_modify_smart_pointer_when_passed_by_value(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) error { + _, err := e.CallPublicSymbol(ctx, "embind_attempt_to_modify_smart_pointer_when_passed_by_value", arg0) + return err +} + +func Embind_modify_smart_pointer_passed_by_reference(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) error { + _, err := e.CallPublicSymbol(ctx, "embind_modify_smart_pointer_passed_by_reference", arg0) + return err +} + +func Embind_save_smart_base_pointer(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) error { + _, err := e.CallPublicSymbol(ctx, "embind_save_smart_base_pointer", arg0) + return err +} + +func Embind_test_accept_big_class_instance(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (int32, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_accept_big_class_instance", arg0) + if err != nil { + return int32(0), err + } + if res == nil { + return int32(0), nil + } + return res.(int32), nil +} + +func Embind_test_accept_small_class_instance(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (int32, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_accept_small_class_instance", arg0) + if err != nil { + return int32(0), err + } + if res == nil { + return int32(0), nil + } + return res.(int32), nil +} + +func Embind_test_accept_unique_ptr(e embind.Engine, ctx context.Context, arg0 int32) (int32, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_accept_unique_ptr", arg0) + if err != nil { + return int32(0), err + } + if res == nil { + return int32(0), nil + } + return res.(int32), nil +} + +func Embind_test_construct_class_with_unique_ptr(e embind.Engine, ctx context.Context, arg0 int32) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_construct_class_with_unique_ptr", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_get_class_name_via_base_ptr(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (string, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_get_class_name_via_base_ptr", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Embind_test_get_class_name_via_polymorphic_base_ptr(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (string, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_get_class_name_via_polymorphic_base_ptr", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Embind_test_get_class_name_via_polymorphic_second_base_ptr(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (string, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_get_class_name_via_polymorphic_second_base_ptr", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Embind_test_get_class_name_via_reference_to_smart_base_ptr(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (string, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_get_class_name_via_reference_to_smart_base_ptr", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Embind_test_get_class_name_via_second_base_ptr(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (string, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_get_class_name_via_second_base_ptr", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Embind_test_get_class_name_via_smart_base_ptr(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (string, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_get_class_name_via_smart_base_ptr", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Embind_test_get_class_name_via_smart_polymorphic_base_ptr(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (string, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_get_class_name_via_smart_polymorphic_base_ptr", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Embind_test_get_class_name_via_smart_polymorphic_second_base_ptr(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (string, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_get_class_name_via_smart_polymorphic_second_base_ptr", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Embind_test_get_class_name_via_smart_second_base_ptr(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (string, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_get_class_name_via_smart_second_base_ptr", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Embind_test_get_string_int_map(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_get_string_int_map") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_get_virtual_class_name_via_smart_polymorphic_base_ptr(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (string, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_get_virtual_class_name_via_smart_polymorphic_base_ptr", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Embind_test_getglobal(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_getglobal") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Embind_test_new_Object(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_new_Object") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Embind_test_new_factory(e embind.Engine, ctx context.Context, arg0 any, arg1 any) (any, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_new_factory", arg0, arg1) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Embind_test_return_big_class_instance(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_big_class_instance") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_poly_derived_twice_without_smart_pointer_as_poly_base(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_poly_derived_twice_without_smart_pointer_as_poly_base") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_raw_base_ptr(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_raw_base_ptr") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_raw_derived_ptr_as_base(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_raw_derived_ptr_as_base") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_raw_polymorphic_derived_four_times_not_bound_as_base(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_raw_polymorphic_derived_four_times_not_bound_as_base") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_raw_polymorphic_derived_ptr_as_base(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_raw_polymorphic_derived_ptr_as_base") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_raw_polymorphic_multiply_derived_ptr_as_base(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_raw_polymorphic_multiply_derived_ptr_as_base") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_raw_polymorphic_multiply_derived_ptr_as_second_base(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_raw_polymorphic_multiply_derived_ptr_as_second_base") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_raw_polymorphic_sibling_derived_ptr_as_base(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_raw_polymorphic_sibling_derived_ptr_as_base") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_raw_sibling_derived_ptr_as_base(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_raw_sibling_derived_ptr_as_base") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_small_class_instance(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_small_class_instance") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_smart_base_ptr(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_smart_base_ptr") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_smart_derived_ptr(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_smart_derived_ptr") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_smart_derived_ptr_as_base(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_smart_derived_ptr_as_base") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_smart_derived_ptr_as_val(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_smart_derived_ptr_as_val") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Embind_test_return_smart_derived_thrice_ptr(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_smart_derived_thrice_ptr") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_smart_multiply_derived_ptr(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_smart_multiply_derived_ptr") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_smart_poly_derived_thrice_ptr(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_smart_poly_derived_thrice_ptr") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_smart_polymorphic_base_ptr(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_smart_polymorphic_base_ptr") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_smart_polymorphic_derived_ptr(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_smart_polymorphic_derived_ptr") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_smart_polymorphic_derived_ptr_as_base(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_smart_polymorphic_derived_ptr_as_base") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_smart_polymorphic_multiply_derived_ptr(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_smart_polymorphic_multiply_derived_ptr") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_smart_polymorphic_sibling_derived_ptr(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_smart_polymorphic_sibling_derived_ptr") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_smart_polymorphic_sibling_derived_ptr_as_base(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_smart_polymorphic_sibling_derived_ptr_as_base") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_smart_sibling_derived_ptr(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_smart_sibling_derived_ptr") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Embind_test_return_unique_ptr(e embind.Engine, ctx context.Context, arg0 int32) (int32, error) { + res, err := e.CallPublicSymbol(ctx, "embind_test_return_unique_ptr", arg0) + if err != nil { + return int32(0), err + } + if res == nil { + return int32(0), nil + } + return res.(int32), nil +} + +func Emval_array(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "emval_array") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Emval_await(e embind.Engine, ctx context.Context, arg0 any) (any, error) { + res, err := e.CallPublicSymbol(ctx, "emval_await", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Emval_delete(e embind.Engine, ctx context.Context, arg0 any) error { + _, err := e.CallPublicSymbol(ctx, "emval_delete", arg0) + return err +} + +func Emval_has_own_property(e embind.Engine, ctx context.Context, arg0 any, arg1 any) (any, error) { + res, err := e.CallPublicSymbol(ctx, "emval_has_own_property", arg0, arg1) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Emval_in(e embind.Engine, ctx context.Context, arg0 any, arg1 any) (bool, error) { + res, err := e.CallPublicSymbol(ctx, "emval_in", arg0, arg1) + if err != nil { + return bool(false), err + } + if res == nil { + return bool(false), nil + } + return res.(bool), nil +} + +func Emval_instance_of(e embind.Engine, ctx context.Context, arg0 any, arg1 any) (bool, error) { + res, err := e.CallPublicSymbol(ctx, "emval_instance_of", arg0, arg1) + if err != nil { + return bool(false), err + } + if res == nil { + return bool(false), nil + } + return res.(bool), nil +} + +func Emval_is_array(e embind.Engine, ctx context.Context, arg0 any) (bool, error) { + res, err := e.CallPublicSymbol(ctx, "emval_is_array", arg0) + if err != nil { + return bool(false), err + } + if res == nil { + return bool(false), nil + } + return res.(bool), nil +} + +func Emval_is_number(e embind.Engine, ctx context.Context, arg0 any) (bool, error) { + res, err := e.CallPublicSymbol(ctx, "emval_is_number", arg0) + if err != nil { + return bool(false), err + } + if res == nil { + return bool(false), nil + } + return res.(bool), nil +} + +func Emval_is_string(e embind.Engine, ctx context.Context, arg0 any) (bool, error) { + res, err := e.CallPublicSymbol(ctx, "emval_is_string", arg0) + if err != nil { + return bool(false), err + } + if res == nil { + return bool(false), nil + } + return res.(bool), nil +} + +func Emval_test_add(e embind.Engine, ctx context.Context, arg0 int8, arg1 int8, arg2 uint8, arg3 int16, arg4 uint16, arg5 int32, arg6 uint32, arg7 int32, arg8 uint32, arg9 float32, arg10 float64) (float64, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_add", arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) + if err != nil { + return float64(0), err + } + if res == nil { + return float64(0), nil + } + return res.(float64), nil +} + +func Emval_test_as_unsigned(e embind.Engine, ctx context.Context, arg0 any) (uint32, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_as_unsigned", arg0) + if err != nil { + return uint32(0), err + } + if res == nil { + return uint32(0), nil + } + return res.(uint32), nil +} + +func Emval_test_call_function(e embind.Engine, ctx context.Context, arg0 any, arg1 int32, arg2 float32, arg3 []any, arg4 map[string]any) error { + _, err := e.CallPublicSymbol(ctx, "emval_test_call_function", arg0, arg1, arg2, arg3, arg4) + return err +} + +func Emval_test_equals(e embind.Engine, ctx context.Context, arg0 any, arg1 any) (bool, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_equals", arg0, arg1) + if err != nil { + return bool(false), err + } + if res == nil { + return bool(false), nil + } + return res.(bool), nil +} + +func Emval_test_get_function_ptr(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_get_function_ptr") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Emval_test_get_length(e embind.Engine, ctx context.Context, arg0 any) (uint32, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_get_length", arg0) + if err != nil { + return uint32(0), err + } + if res == nil { + return uint32(0), nil + } + return res.(uint32), nil +} + +func Emval_test_get_string_from_val(e embind.Engine, ctx context.Context, arg0 any) (string, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_get_string_from_val", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Emval_test_instance_pointer(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_instance_pointer") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Emval_test_is_false(e embind.Engine, ctx context.Context, arg0 any) (bool, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_is_false", arg0) + if err != nil { + return bool(false), err + } + if res == nil { + return bool(false), nil + } + return res.(bool), nil +} + +func Emval_test_is_null(e embind.Engine, ctx context.Context, arg0 any) (bool, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_is_null", arg0) + if err != nil { + return bool(false), err + } + if res == nil { + return bool(false), nil + } + return res.(bool), nil +} + +func Emval_test_is_shared_ptr_null(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (bool, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_is_shared_ptr_null", arg0) + if err != nil { + return bool(false), err + } + if res == nil { + return bool(false), nil + } + return res.(bool), nil +} + +func Emval_test_is_true(e embind.Engine, ctx context.Context, arg0 any) (bool, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_is_true", arg0) + if err != nil { + return bool(false), err + } + if res == nil { + return bool(false), nil + } + return res.(bool), nil +} + +func Emval_test_is_undefined(e embind.Engine, ctx context.Context, arg0 any) (bool, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_is_undefined", arg0) + if err != nil { + return bool(false), err + } + if res == nil { + return bool(false), nil + } + return res.(bool), nil +} + +func Emval_test_new_integer(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_new_integer") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Emval_test_new_object(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_new_object") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Emval_test_new_string(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_new_string") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Emval_test_not(e embind.Engine, ctx context.Context, arg0 bool) (bool, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_not", arg0) + if err != nil { + return bool(false), err + } + if res == nil { + return bool(false), nil + } + return res.(bool), nil +} + +func Emval_test_passthrough(e embind.Engine, ctx context.Context, arg0 any) (any, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_passthrough", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Emval_test_passthrough_unsigned(e embind.Engine, ctx context.Context, arg0 uint32) (uint32, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_passthrough_unsigned", arg0) + if err != nil { + return uint32(0), err + } + if res == nil { + return uint32(0), nil + } + return res.(uint32), nil +} + +func Emval_test_return_StructVector(e embind.Engine, ctx context.Context) (map[string]any, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_return_StructVector") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(map[string]any), nil +} + +func Emval_test_return_TupleVector(e embind.Engine, ctx context.Context) ([]any, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_return_TupleVector") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.([]any), nil +} + +func Emval_test_return_TupleVectorTuple(e embind.Engine, ctx context.Context) ([]any, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_return_TupleVectorTuple") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.([]any), nil +} + +func Emval_test_return_ValHolder(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_return_ValHolder") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Emval_test_return_empty_shared_ptr(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_return_empty_shared_ptr") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Emval_test_return_shared_ptr(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_return_shared_ptr") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Emval_test_return_shared_ptr_vector(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_return_shared_ptr_vector") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Emval_test_return_unique_ptr(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_return_unique_ptr") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Emval_test_return_unique_ptr_lifetime(e embind.Engine, ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_return_unique_ptr_lifetime", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Emval_test_return_vector(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_return_vector") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Emval_test_return_vector_of_vectors(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_return_vector_of_vectors") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Emval_test_return_void(e embind.Engine, ctx context.Context) error { + _, err := e.CallPublicSymbol(ctx, "emval_test_return_void") + return err +} + +func Emval_test_set_ValHolder_to_empty_object(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) error { + _, err := e.CallPublicSymbol(ctx, "emval_test_set_ValHolder_to_empty_object", arg0) + return err +} + +func Emval_test_strictly_equals(e embind.Engine, ctx context.Context, arg0 any, arg1 any) (bool, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_strictly_equals", arg0, arg1) + if err != nil { + return bool(false), err + } + if res == nil { + return bool(false), nil + } + return res.(bool), nil +} + +func Emval_test_sum(e embind.Engine, ctx context.Context, arg0 any) (uint32, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_sum", arg0) + if err != nil { + return uint32(0), err + } + if res == nil { + return uint32(0), nil + } + return res.(uint32), nil +} + +func Emval_test_take_and_call_functor(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (string, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_take_and_call_functor", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Emval_test_take_and_return_ArrayInStruct(e embind.Engine, ctx context.Context, arg0 map[string]any) (map[string]any, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_take_and_return_ArrayInStruct", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(map[string]any), nil +} + +func Emval_test_take_and_return_Enum(e embind.Engine, ctx context.Context, arg0 EnumEnum) (EnumEnum, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_take_and_return_Enum", arg0) + if err != nil { + return EnumEnum(0), err + } + if res == nil { + return EnumEnum(0), nil + } + return res.(EnumEnum), nil +} + +func Emval_test_take_and_return_EnumClass(e embind.Engine, ctx context.Context, arg0 EnumEnumClass) (EnumEnumClass, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_take_and_return_EnumClass", arg0) + if err != nil { + return EnumEnumClass(0), err + } + if res == nil { + return EnumEnumClass(0), nil + } + return res.(EnumEnumClass), nil +} + +func Emval_test_take_and_return_StructVector(e embind.Engine, ctx context.Context, arg0 map[string]any) (map[string]any, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_take_and_return_StructVector", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(map[string]any), nil +} + +func Emval_test_take_and_return_TupleInStruct(e embind.Engine, ctx context.Context, arg0 map[string]any) (map[string]any, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_take_and_return_TupleInStruct", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(map[string]any), nil +} + +func Emval_test_take_and_return_TupleVector(e embind.Engine, ctx context.Context, arg0 []any) ([]any, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_take_and_return_TupleVector", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.([]any), nil +} + +func Emval_test_take_and_return_std_basic_string_unsigned_char(e embind.Engine, ctx context.Context, arg0 string) (string, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_take_and_return_std_basic_string_unsigned_char", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Emval_test_take_and_return_std_string(e embind.Engine, ctx context.Context, arg0 string) (string, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_take_and_return_std_string", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Emval_test_take_and_return_std_string_const_ref(e embind.Engine, ctx context.Context, arg0 string) (string, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_take_and_return_std_string_const_ref", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Emval_test_value_from_instance_pointer(e embind.Engine, ctx context.Context, arg0 any) (int32, error) { + res, err := e.CallPublicSymbol(ctx, "emval_test_value_from_instance_pointer", arg0) + if err != nil { + return int32(0), err + } + if res == nil { + return int32(0), nil + } + return res.(int32), nil +} + +func Emval_throw(e embind.Engine, ctx context.Context, arg0 any) error { + _, err := e.CallPublicSymbol(ctx, "emval_throw", arg0) + return err +} + +func Emval_type_of(e embind.Engine, ctx context.Context, arg0 any) (any, error) { + res, err := e.CallPublicSymbol(ctx, "emval_type_of", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Emval_u16_string(e embind.Engine, ctx context.Context, arg0 any) (any, error) { + res, err := e.CallPublicSymbol(ctx, "emval_u16_string", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Emval_u8_string(e embind.Engine, ctx context.Context, arg0 any) (any, error) { + res, err := e.CallPublicSymbol(ctx, "emval_u8_string", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Enum_in_enum_out(e embind.Engine, ctx context.Context, arg0 EnumNewStyle) (EnumOldStyle, error) { + res, err := e.CallPublicSymbol(ctx, "enum_in_enum_out", arg0) + if err != nil { + return EnumOldStyle(0), err + } + if res == nil { + return EnumOldStyle(0), nil + } + return res.(EnumOldStyle), nil +} + +func FindPersonAtLocation(e embind.Engine, ctx context.Context, arg0 []any) (map[string]any, error) { + res, err := e.CallPublicSymbol(ctx, "findPersonAtLocation", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(map[string]any), nil +} + +func FirstElement(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "FirstElement") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func FloatVector(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "FloatVector") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Float_return_float(e embind.Engine, ctx context.Context, arg0 float32) (float32, error) { + res, err := e.CallPublicSymbol(ctx, "float_return_float", arg0) + if err != nil { + return float32(0), err + } + if res == nil { + return float32(0), nil + } + return res.(float32), nil +} + +func Float_return_void(e embind.Engine, ctx context.Context, arg0 float32) error { + _, err := e.CallPublicSymbol(ctx, "float_return_void", arg0) + return err +} + +func Foo(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "Foo") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Foo_(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "foo") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Force_memory_growth(e embind.Engine, ctx context.Context) error { + _, err := e.CallPublicSymbol(ctx, "force_memory_growth") + return err +} + +func Function_overload0(e embind.Engine, ctx context.Context) (int32, error) { + res, err := e.CallPublicSymbol(ctx, "function_overload") + if err != nil { + return int32(0), err + } + if res == nil { + return int32(0), nil + } + return res.(int32), nil +} + +func Function_overload1(e embind.Engine, ctx context.Context, arg0 int32) (int32, error) { + res, err := e.CallPublicSymbol(ctx, "function_overload", arg0) + if err != nil { + return int32(0), err + } + if res == nil { + return int32(0), nil + } + return res.(int32), nil +} + +func GetAbstractClass(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "getAbstractClass") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func GetDerivedClassInstance(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "getDerivedClassInstance") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func GetDummy0(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "getDummy") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func GetDummy1(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "getDummy", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func GetHasUnboundBase(e embind.Engine, ctx context.Context, arg0 any) (any, error) { + res, err := e.CallPublicSymbol(ctx, "getHasUnboundBase", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func GetNoncopyable(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "getNoncopyable") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func GetOrderedStruct(e embind.Engine, ctx context.Context) (map[string]any, error) { + res, err := e.CallPublicSymbol(ctx, "getOrderedStruct") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(map[string]any), nil +} + +func GetOrderedTuple(e embind.Engine, ctx context.Context) ([]any, error) { + res, err := e.CallPublicSymbol(ctx, "getOrderedTuple") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.([]any), nil +} + +func GetTypeOfVal(e embind.Engine, ctx context.Context, arg0 any) (string, error) { + res, err := e.CallPublicSymbol(ctx, "getTypeOfVal", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func GetUnboundClass(e embind.Engine, ctx context.Context, arg0 any) (any, error) { + res, err := e.CallPublicSymbol(ctx, "getUnboundClass", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Get_literal_u16string(e embind.Engine, ctx context.Context) (string, error) { + res, err := e.CallPublicSymbol(ctx, "get_literal_u16string") + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Get_literal_u32string(e embind.Engine, ctx context.Context) (string, error) { + res, err := e.CallPublicSymbol(ctx, "get_literal_u32string") + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Get_literal_wstring(e embind.Engine, ctx context.Context) (string, error) { + res, err := e.CallPublicSymbol(ctx, "get_literal_wstring") + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Get_memory_view_char(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "get_memory_view_char") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Get_memory_view_double(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "get_memory_view_double") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Get_memory_view_float(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "get_memory_view_float") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Get_memory_view_int(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "get_memory_view_int") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Get_memory_view_long(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "get_memory_view_long") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Get_memory_view_longlong(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "get_memory_view_longlong") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Get_memory_view_short(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "get_memory_view_short") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Get_memory_view_unsigned_char(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "get_memory_view_unsigned_char") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Get_memory_view_unsigned_int(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "get_memory_view_unsigned_int") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Get_memory_view_unsigned_long(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "get_memory_view_unsigned_long") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Get_memory_view_unsigned_longlong(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "get_memory_view_unsigned_longlong") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Get_memory_view_unsigned_short(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "get_memory_view_unsigned_short") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Get_module_property(e embind.Engine, ctx context.Context, arg0 string) (any, error) { + res, err := e.CallPublicSymbol(ctx, "get_module_property", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Get_non_ascii_string(e embind.Engine, ctx context.Context, arg0 bool) (string, error) { + res, err := e.CallPublicSymbol(ctx, "get_non_ascii_string", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Get_non_ascii_u16string(e embind.Engine, ctx context.Context) (string, error) { + res, err := e.CallPublicSymbol(ctx, "get_non_ascii_u16string") + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Get_non_ascii_u32string(e embind.Engine, ctx context.Context) (string, error) { + res, err := e.CallPublicSymbol(ctx, "get_non_ascii_u32string") + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Get_non_ascii_wstring(e embind.Engine, ctx context.Context) (string, error) { + res, err := e.CallPublicSymbol(ctx, "get_non_ascii_wstring") + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func HasConstructorUsingUnboundArgument(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "HasConstructorUsingUnboundArgument") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func HasConstructorUsingUnboundArgumentAndUnboundBase(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "HasConstructorUsingUnboundArgumentAndUnboundBase") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func HasExternalConstructor(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "HasExternalConstructor") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func HasReadOnlyProperty(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "HasReadOnlyProperty") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func HasStaticMember(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "HasStaticMember") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func HasTwoBases(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "HasTwoBases") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func HasUnboundBase(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "HasUnboundBase") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func HeldAbstractClass(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "HeldAbstractClass") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func HeldAbstractClassWrapper(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "HeldAbstractClassWrapper") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func HeldByCustomSmartPtr(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "HeldByCustomSmartPtr") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func HeldBySmartPtr(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "HeldBySmartPtr") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func IntTemplateClass(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "IntTemplateClass") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Int_return_int(e embind.Engine, ctx context.Context, arg0 int32) (int32, error) { + res, err := e.CallPublicSymbol(ctx, "int_return_int", arg0) + if err != nil { + return int32(0), err + } + if res == nil { + return int32(0), nil + } + return res.(int32), nil +} + +func Int_to_string(e embind.Engine, ctx context.Context, arg0 int32) (string, error) { + res, err := e.CallPublicSymbol(ctx, "int_to_string", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func IntegerVector(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "IntegerVector") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func IntegerVectorVector(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "IntegerVectorVector") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Interface(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "Interface") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func InterfaceWrapper(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "InterfaceWrapper") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func IntrusiveClass(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "IntrusiveClass") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func IntrusiveClassHolder(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "IntrusiveClassHolder") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func IntrusiveClassWrapper(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "IntrusiveClassWrapper") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Load_unsigned_char(e embind.Engine, ctx context.Context) (uint8, error) { + res, err := e.CallPublicSymbol(ctx, "load_unsigned_char") + if err != nil { + return uint8(0), err + } + if res == nil { + return uint8(0), nil + } + return res.(uint8), nil +} + +func Load_unsigned_int(e embind.Engine, ctx context.Context) (uint32, error) { + res, err := e.CallPublicSymbol(ctx, "load_unsigned_int") + if err != nil { + return uint32(0), err + } + if res == nil { + return uint32(0), nil + } + return res.(uint32), nil +} + +func Load_unsigned_long(e embind.Engine, ctx context.Context) (uint32, error) { + res, err := e.CallPublicSymbol(ctx, "load_unsigned_long") + if err != nil { + return uint32(0), err + } + if res == nil { + return uint32(0), nil + } + return res.(uint32), nil +} + +func Load_unsigned_short(e embind.Engine, ctx context.Context) (uint16, error) { + res, err := e.CallPublicSymbol(ctx, "load_unsigned_short") + if err != nil { + return uint16(0), err + } + if res == nil { + return uint16(0), nil + } + return res.(uint16), nil +} + +func Long_return_long(e embind.Engine, ctx context.Context, arg0 int32) (int32, error) { + res, err := e.CallPublicSymbol(ctx, "long_return_long", arg0) + if err != nil { + return int32(0), err + } + if res == nil { + return int32(0), nil + } + return res.(int32), nil +} + +func Long_to_string(e embind.Engine, ctx context.Context, arg0 int32) (string, error) { + res, err := e.CallPublicSymbol(ctx, "long_to_string", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Longlong_return_longlong(e embind.Engine, ctx context.Context, arg0 int64) (int64, error) { + res, err := e.CallPublicSymbol(ctx, "longlong_return_longlong", arg0) + if err != nil { + return int64(0), err + } + if res == nil { + return int64(0), nil + } + return res.(int64), nil +} + +func Mallinfo(e embind.Engine, ctx context.Context) (any, error) { + res, err := e.CallPublicSymbol(ctx, "mallinfo") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Map_int__string_(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "map_int__string_") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func MultipleAccessors(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "MultipleAccessors") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func MultipleCtors(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "MultipleCtors") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func MultipleOverloads(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "MultipleOverloads") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func MultipleOverloadsDependingOnDummy(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "MultipleOverloadsDependingOnDummy") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func MultipleOverloadsDerived(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "MultipleOverloadsDerived") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func MultipleSmartCtors(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "MultipleSmartCtors") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func MultiplyDerived(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "MultiplyDerived") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func MyClass(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "MyClass") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func NoExceptClass(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "NoExceptClass") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Noncopyable(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "Noncopyable") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Overloaded_function1(e embind.Engine, ctx context.Context, arg0 int32) (int32, error) { + res, err := e.CallPublicSymbol(ctx, "overloaded_function", arg0) + if err != nil { + return int32(0), err + } + if res == nil { + return int32(0), nil + } + return res.(int32), nil +} + +func Overloaded_function2(e embind.Engine, ctx context.Context, arg0 int32, arg1 int32) (int32, error) { + res, err := e.CallPublicSymbol(ctx, "overloaded_function", arg0, arg1) + if err != nil { + return int32(0), err + } + if res == nil { + return int32(0), nil + } + return res.(int32), nil +} + +func PFoo(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "pFoo") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func ParentClass(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "ParentClass") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func PassHeldAbstractClass(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "passHeldAbstractClass", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func PassShared(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) error { + _, err := e.CallPublicSymbol(ctx, "passShared", arg0) + return err +} + +func PassThrough(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "passThrough", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func PassThroughCustomSmartPtr(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "passThroughCustomSmartPtr", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func PassThroughIntrusiveClass(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "passThroughIntrusiveClass", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func PassThroughRawPtr(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "passThroughRawPtr", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func PassVal(e embind.Engine, ctx context.Context, arg0 embind.ClassBase, arg1 any) error { + _, err := e.CallPublicSymbol(ctx, "passVal", arg0, arg1) + return err +} + +func PolyBase(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "PolyBase") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func PolyDerived(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "PolyDerived") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func PolyDerivedThrice(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "PolyDerivedThrice") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func PolyDiamondBase(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "PolyDiamondBase") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func PolyDiamondDerived(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "PolyDiamondDerived") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func PolyDiamondMultiplyDerived(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "PolyDiamondMultiplyDerived") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func PolyDiamondSiblingDerived(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "PolyDiamondSiblingDerived") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func PolyMultiplyDerived(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "PolyMultiplyDerived") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func PolySecondBase(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "PolySecondBase") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func PolySiblingDerived(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "PolySiblingDerived") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Return_Base_from_DerivedWithOffset(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "return_Base_from_DerivedWithOffset", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Return_StringHolder_copy(e embind.Engine, ctx context.Context, arg0 any) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "return_StringHolder_copy", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Return_map(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "return_map") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Return_vector(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "return_vector") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func SecondBase(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "SecondBase") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func SecondElement(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "SecondElement") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func SetPersonAtLocation(e embind.Engine, ctx context.Context, arg0 []any, arg1 map[string]any) error { + _, err := e.CallPublicSymbol(ctx, "setPersonAtLocation", arg0, arg1) + return err +} + +func Set_bind_f64(e embind.Engine, ctx context.Context, arg0 any) error { + _, err := e.CallPublicSymbol(ctx, "set_bind_f64", arg0) + return err +} + +func Set_bind_u32(e embind.Engine, ctx context.Context, arg0 any) error { + _, err := e.CallPublicSymbol(ctx, "set_bind_u32", arg0) + return err +} + +func Set_bind_u64(e embind.Engine, ctx context.Context, arg0 any) error { + _, err := e.CallPublicSymbol(ctx, "set_bind_u64", arg0) + return err +} + +func SharedPtrHolder(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "SharedPtrHolder") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func SharedPtrVector(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "SharedPtrVector") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Short_return_short(e embind.Engine, ctx context.Context, arg0 int16) (int16, error) { + res, err := e.CallPublicSymbol(ctx, "short_return_short", arg0) + if err != nil { + return int16(0), err + } + if res == nil { + return int16(0), nil + } + return res.(int16), nil +} + +func Short_to_string(e embind.Engine, ctx context.Context, arg0 int16) (string, error) { + res, err := e.CallPublicSymbol(ctx, "short_to_string", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func SiblingDerived(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "SiblingDerived") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Signed_char_to_string(e embind.Engine, ctx context.Context, arg0 int8) (string, error) { + res, err := e.CallPublicSymbol(ctx, "signed_char_to_string", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func SmallClass(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "SmallClass") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Std_string_return_std_string(e embind.Engine, ctx context.Context, arg0 string) (string, error) { + res, err := e.CallPublicSymbol(ctx, "std_string_return_std_string", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Std_u16string_return_std_u16string(e embind.Engine, ctx context.Context, arg0 string) (string, error) { + res, err := e.CallPublicSymbol(ctx, "std_u16string_return_std_u16string", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Std_wstring_return_std_wstring(e embind.Engine, ctx context.Context, arg0 string) (string, error) { + res, err := e.CallPublicSymbol(ctx, "std_wstring_return_std_wstring", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Store_unsigned_char(e embind.Engine, ctx context.Context, arg0 uint8) error { + _, err := e.CallPublicSymbol(ctx, "store_unsigned_char", arg0) + return err +} + +func Store_unsigned_int(e embind.Engine, ctx context.Context, arg0 uint32) error { + _, err := e.CallPublicSymbol(ctx, "store_unsigned_int", arg0) + return err +} + +func Store_unsigned_long(e embind.Engine, ctx context.Context, arg0 uint32) error { + _, err := e.CallPublicSymbol(ctx, "store_unsigned_long", arg0) + return err +} + +func Store_unsigned_short(e embind.Engine, ctx context.Context, arg0 uint16) error { + _, err := e.CallPublicSymbol(ctx, "store_unsigned_short", arg0) + return err +} + +func StringFunctorString(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "StringFunctorString") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func StringHolder(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "StringHolder") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func StringHolderVector(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "StringHolderVector") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func StringIntMap(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "StringIntMap") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func StringVector(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "StringVector") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Take_and_return_std_u16string(e embind.Engine, ctx context.Context, arg0 string) (string, error) { + res, err := e.CallPublicSymbol(ctx, "take_and_return_std_u16string", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Take_and_return_std_u32string(e embind.Engine, ctx context.Context, arg0 string) (string, error) { + res, err := e.CallPublicSymbol(ctx, "take_and_return_std_u32string", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Take_and_return_std_wstring(e embind.Engine, ctx context.Context, arg0 string) (string, error) { + res, err := e.CallPublicSymbol(ctx, "take_and_return_std_wstring", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func TakesHeldBySmartPtr(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "takesHeldBySmartPtr", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func TakesHeldBySmartPtrSharedPtr(e embind.Engine, ctx context.Context, arg0 embind.ClassBase) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "takesHeldBySmartPtrSharedPtr", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Test_string_with_vec(e embind.Engine, ctx context.Context, arg0 string, arg1 embind.ClassBase) error { + _, err := e.CallPublicSymbol(ctx, "test_string_with_vec", arg0, arg1) + return err +} + +func Uchar_return_uchar(e embind.Engine, ctx context.Context, arg0 uint8) (uint8, error) { + res, err := e.CallPublicSymbol(ctx, "uchar_return_uchar", arg0) + if err != nil { + return uint8(0), err + } + if res == nil { + return uint8(0), nil + } + return res.(uint8), nil +} + +func Uint_return_uint(e embind.Engine, ctx context.Context, arg0 uint32) (uint32, error) { + res, err := e.CallPublicSymbol(ctx, "uint_return_uint", arg0) + if err != nil { + return uint32(0), err + } + if res == nil { + return uint32(0), nil + } + return res.(uint32), nil +} + +func Ulong_return_ulong(e embind.Engine, ctx context.Context, arg0 uint32) (uint32, error) { + res, err := e.CallPublicSymbol(ctx, "ulong_return_ulong", arg0) + if err != nil { + return uint32(0), err + } + if res == nil { + return uint32(0), nil + } + return res.(uint32), nil +} + +func Ulonglong_return_ulonglong(e embind.Engine, ctx context.Context, arg0 uint64) (uint64, error) { + res, err := e.CallPublicSymbol(ctx, "ulonglong_return_ulonglong", arg0) + if err != nil { + return uint64(0), err + } + if res == nil { + return uint64(0), nil + } + return res.(uint64), nil +} + +func UniquePtrLifetimeMock(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "UniquePtrLifetimeMock") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func UniquePtrToConstructor(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "UniquePtrToConstructor") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Unsigned_char_to_string(e embind.Engine, ctx context.Context, arg0 uint8) (string, error) { + res, err := e.CallPublicSymbol(ctx, "unsigned_char_to_string", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Unsigned_int_to_string(e embind.Engine, ctx context.Context, arg0 uint32) (string, error) { + res, err := e.CallPublicSymbol(ctx, "unsigned_int_to_string", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Unsigned_long_to_string(e embind.Engine, ctx context.Context, arg0 uint32) (string, error) { + res, err := e.CallPublicSymbol(ctx, "unsigned_long_to_string", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Unsigned_short_to_string(e embind.Engine, ctx context.Context, arg0 uint16) (string, error) { + res, err := e.CallPublicSymbol(ctx, "unsigned_short_to_string", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Ushort_return_ushort(e embind.Engine, ctx context.Context, arg0 uint16) (uint16, error) { + res, err := e.CallPublicSymbol(ctx, "ushort_return_ushort", arg0) + if err != nil { + return uint16(0), err + } + if res == nil { + return uint16(0), nil + } + return res.(uint16), nil +} + +func ValHolder(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "ValHolder") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func Val_as_bool(e embind.Engine, ctx context.Context, arg0 any) (bool, error) { + res, err := e.CallPublicSymbol(ctx, "val_as_bool", arg0) + if err != nil { + return bool(false), err + } + if res == nil { + return bool(false), nil + } + return res.(bool), nil +} + +func Val_as_char(e embind.Engine, ctx context.Context, arg0 any) (int8, error) { + res, err := e.CallPublicSymbol(ctx, "val_as_char", arg0) + if err != nil { + return int8(0), err + } + if res == nil { + return int8(0), nil + } + return res.(int8), nil +} + +func Val_as_double(e embind.Engine, ctx context.Context, arg0 any) (float64, error) { + res, err := e.CallPublicSymbol(ctx, "val_as_double", arg0) + if err != nil { + return float64(0), err + } + if res == nil { + return float64(0), nil + } + return res.(float64), nil +} + +func Val_as_enum(e embind.Engine, ctx context.Context, arg0 any) (EnumEnum, error) { + res, err := e.CallPublicSymbol(ctx, "val_as_enum", arg0) + if err != nil { + return EnumEnum(0), err + } + if res == nil { + return EnumEnum(0), nil + } + return res.(EnumEnum), nil +} + +func Val_as_float(e embind.Engine, ctx context.Context, arg0 any) (float32, error) { + res, err := e.CallPublicSymbol(ctx, "val_as_float", arg0) + if err != nil { + return float32(0), err + } + if res == nil { + return float32(0), nil + } + return res.(float32), nil +} + +func Val_as_int(e embind.Engine, ctx context.Context, arg0 any) (int32, error) { + res, err := e.CallPublicSymbol(ctx, "val_as_int", arg0) + if err != nil { + return int32(0), err + } + if res == nil { + return int32(0), nil + } + return res.(int32), nil +} + +func Val_as_int64_t(e embind.Engine, ctx context.Context, arg0 any) (int64, error) { + res, err := e.CallPublicSymbol(ctx, "val_as_int64_t", arg0) + if err != nil { + return int64(0), err + } + if res == nil { + return int64(0), nil + } + return res.(int64), nil +} + +func Val_as_long(e embind.Engine, ctx context.Context, arg0 any) (int32, error) { + res, err := e.CallPublicSymbol(ctx, "val_as_long", arg0) + if err != nil { + return int32(0), err + } + if res == nil { + return int32(0), nil + } + return res.(int32), nil +} + +func Val_as_short(e embind.Engine, ctx context.Context, arg0 any) (int16, error) { + res, err := e.CallPublicSymbol(ctx, "val_as_short", arg0) + if err != nil { + return int16(0), err + } + if res == nil { + return int16(0), nil + } + return res.(int16), nil +} + +func Val_as_string(e embind.Engine, ctx context.Context, arg0 any) (string, error) { + res, err := e.CallPublicSymbol(ctx, "val_as_string", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func Val_as_uint64_t(e embind.Engine, ctx context.Context, arg0 any) (uint64, error) { + res, err := e.CallPublicSymbol(ctx, "val_as_uint64_t", arg0) + if err != nil { + return uint64(0), err + } + if res == nil { + return uint64(0), nil + } + return res.(uint64), nil +} + +func Val_as_val(e embind.Engine, ctx context.Context, arg0 any) (any, error) { + res, err := e.CallPublicSymbol(ctx, "val_as_val", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(any), nil +} + +func Val_as_value_array(e embind.Engine, ctx context.Context, arg0 any) ([]any, error) { + res, err := e.CallPublicSymbol(ctx, "val_as_value_array", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.([]any), nil +} + +func Val_as_value_object(e embind.Engine, ctx context.Context, arg0 any) (map[string]any, error) { + res, err := e.CallPublicSymbol(ctx, "val_as_value_object", arg0) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(map[string]any), nil +} + +func Val_as_wstring(e embind.Engine, ctx context.Context, arg0 any) (string, error) { + res, err := e.CallPublicSymbol(ctx, "val_as_wstring", arg0) + if err != nil { + return "", err + } + if res == nil { + return "", nil + } + return res.(string), nil +} + +func VectorHolder(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "VectorHolder") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func VectorUnsigned(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "VectorUnsigned") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} + +func VectorUnsignedChar(e embind.Engine, ctx context.Context) (embind.ClassBase, error) { + res, err := e.CallPublicSymbol(ctx, "VectorUnsignedChar") + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return res.(embind.ClassBase), nil +} diff --git a/tests/generated/generate.go b/tests/generated/generate.go new file mode 100644 index 0000000..673851b --- /dev/null +++ b/tests/generated/generate.go @@ -0,0 +1,2 @@ +//go:generate go run github.com/jerbob92/wazero-emscripten-embind/generator -v=true -wasm=../../testdata/wasm/tests.wasm +package generated diff --git a/tests/generated_test.go b/tests/generated_test.go new file mode 100644 index 0000000..996e370 --- /dev/null +++ b/tests/generated_test.go @@ -0,0 +1,3998 @@ +package tests + +import ( + "context" + embind "github.com/jerbob92/wazero-emscripten-embind/internal" + "log" + "os" + "testing" + + embind_external "github.com/jerbob92/wazero-emscripten-embind" + "github.com/jerbob92/wazero-emscripten-embind/tests/generated" + "github.com/jerbob92/wazero-emscripten-embind/types" + + "github.com/tetratelabs/wazero" + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/imports/emscripten" + "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestEmbindGenerated(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Embind generated Suite") +} + +var ctx = context.Background() + +//var ctx = context.WithValue(context.Background(), experimental.FunctionListenerFactoryKey{}, logging.NewLoggingListenerFactory(os.Stdout)) + +var engine embind_external.Engine +var runtime wazero.Runtime +var mod api.Module +var wasmData []byte +var compiledModule wazero.CompiledModule + +var _ = BeforeSuite(func() { + wasm, err := os.ReadFile("../testdata/wasm/tests.wasm") + if err != nil { + Expect(err).To(BeNil()) + return + } + + wasmData = wasm + + runtimeConfig := wazero.NewRuntimeConfig() + runtime = wazero.NewRuntimeWithConfig(ctx, runtimeConfig) + + if _, err := wasi_snapshot_preview1.Instantiate(ctx, runtime); err != nil { + Expect(err).To(BeNil()) + return + } + + compiledModule, err = runtime.CompileModule(ctx, wasm) + if err != nil { + log.Fatal(err) + } + + builder := runtime.NewHostModuleBuilder("env") + + emscriptenExporter, err := emscripten.NewFunctionExporterForModule(compiledModule) + if err != nil { + Expect(err).To(BeNil()) + return + } + + emscriptenExporter.ExportFunctions(builder) + + engine = embind_external.CreateEngine(embind_external.NewConfig()) + + embindExporter := engine.NewFunctionExporterForModule(compiledModule) + err = embindExporter.ExportFunctions(builder) + if err != nil { + Expect(err).To(BeNil()) + return + } + + _, err = builder.Instantiate(ctx) + if err != nil { + Expect(err).To(BeNil()) + return + } +}) + +var _ = AfterSuite(func() { + runtime.Close(ctx) +}) + +var _ = BeforeEach(func() { + moduleConfig := wazero.NewModuleConfig(). + WithStartFunctions("_initialize"). + WithStdout(os.Stdout). + WithStderr(os.Stderr). + WithName("") + + var err error + engine = embind_external.CreateEngine(embind_external.NewConfig()) + ctx = engine.Attach(ctx) + mod, err = runtime.InstantiateModule(ctx, compiledModule, moduleConfig) + if err != nil { + Expect(err).To(BeNil()) + return + } + + err = generated.Attach(engine) + if err != nil { + Expect(err).To(BeNil()) + return + } + + err = engine.SetDelayFunction(nil) + Expect(err).To(BeNil()) + + emvalHandleCount := engine.CountEmvalHandles() + Expect(emvalHandleCount).To(Equal(0)) +}) + +var _ = AfterEach(func() { + err := engine.FlushPendingDeletes(ctx) + Expect(err).To(BeNil()) + + emvalHandleCount := engine.CountEmvalHandles() + Expect(emvalHandleCount).To(Equal(0)) + + mod.Close(ctx) +}) + +var _ = Describe("executing original embind tests", Label("library"), func() { + When("access to base class members", func() { + It("method name in derived class silently overrides inherited name", func() { + derived, err := generated.NewClassDerived(engine, ctx) + Expect(err).To(BeNil()) + Expect(derived.GetClassName(ctx)).To(Equal("Derived")) + err = derived.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("can reference base method from derived class", func() { + derived, err := generated.NewClassDerived(engine, ctx) + Expect(err).To(BeNil()) + Expect(derived.GetClassNameFromBase(ctx)).To(Equal("Base")) + err = derived.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("can reference base method from doubly derived class", func() { + derivedTwice, err := generated.NewClassDerivedTwice(engine, ctx) + Expect(err).To(BeNil()) + Expect(derivedTwice.GetClassNameFromBase(ctx)).To(Equal("Base")) + err = derivedTwice.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("can reference base method through unbound classes", func() { + derivedThrice, err := generated.NewClassDerivedThrice(engine, ctx) + Expect(err).To(BeNil()) + Expect(derivedThrice.GetClassNameFromBase(ctx)).To(Equal("Base")) + err = derivedThrice.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("property name in derived class hides identically named property in base class for set", func() { + derived, err := generated.NewClassDerived(engine, ctx) + Expect(err).To(BeNil()) + + err = derived.SetMember(ctx, 7) + Expect(err).To(BeNil()) + + err = derived.SetPropertyMember(ctx, 17) + Expect(err).To(BeNil()) + + member, err := derived.GetMember(ctx) + Expect(err).To(BeNil()) + Expect(member).To(Equal(int32(17))) + + err = derived.Delete(ctx) + Expect(err).To(BeNil()) + }) + It("can reference base property from derived class for get", func() { + derived, err := generated.NewClassDerived(engine, ctx) + Expect(err).To(BeNil()) + + err = derived.SetMember(ctx, 5) + Expect(err).To(BeNil()) + + member, err := derived.GetPropertyMember(ctx) + Expect(err).To(BeNil()) + Expect(member).To(Equal(int32(5))) + + err = derived.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("can reference property of any base class for get when multiply derived", func() { + derived, err := generated.NewClassMultiplyDerived(engine, ctx) + Expect(err).To(BeNil()) + + err = derived.SetMember(ctx, 11) + Expect(err).To(BeNil()) + + member, err := derived.GetPropertyMember(ctx) + Expect(err).To(BeNil()) + Expect(member).To(Equal(int32(11))) + + err = derived.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("can reference base property from derived class for set", func() { + derived, err := generated.NewClassDerived(engine, ctx) + Expect(err).To(BeNil()) + + err = derived.SetPropertyBaseMember(ctx, 32) + Expect(err).To(BeNil()) + + member, err := derived.GetBaseMember(ctx) + Expect(err).To(BeNil()) + Expect(member).To(Equal(int32(32))) + + err = derived.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("can reference property of any base for set when multiply derived", func() { + derived, err := generated.NewClassMultiplyDerived(engine, ctx) + Expect(err).To(BeNil()) + + err = derived.SetPropertyBaseMember(ctx, 32) + Expect(err).To(BeNil()) + + member, err := derived.GetBaseMember(ctx) + Expect(err).To(BeNil()) + Expect(member).To(Equal(int32(32))) + + err = derived.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("can reach around derived property to access base property with same name for get", func() { + derived, err := generated.NewClassDerived(engine, ctx) + Expect(err).To(BeNil()) + + err = derived.SetMember(ctx, 12) + Expect(err).To(BeNil()) + + err = derived.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("if deriving from second base adjusts pointer", func() { + derived, err := generated.HasTwoBases(engine, ctx) + Expect(err).To(BeNil()) + + derivedClass := derived.(*generated.ClassHasTwoBases) + + getField, err := derivedClass.GetField(ctx) + Expect(getField).To(Equal("Base2")) + + err = derivedClass.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("properties adjust pointer", func() { + derived, err := generated.HasTwoBases(engine, ctx) + Expect(err).To(BeNil()) + + derivedClass := derived.(*generated.ClassHasTwoBases) + + err = derivedClass.SetPropertyField(ctx, "Foo") + Expect(err).To(BeNil()) + + getField, err := derivedClass.GetField(ctx) + Expect(getField).To(Equal("Foo")) + + getFieldProperty, err := derivedClass.GetPropertyField(ctx) + Expect(getFieldProperty).To(Equal("Foo")) + + err = derivedClass.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("class functions are inherited in subclasses", func() { + classFunction, err := generated.ClassBaseStaticClassFunction(engine, ctx) + Expect(err).To(BeNil()) + Expect(classFunction).To(Equal("Base")) + + classFunction, err = generated.ClassDerivedStaticClassFunction(engine, ctx) + Expect(err).To(BeNil()) + Expect(classFunction).To(Equal("Derived")) + + classFunction, err = generated.ClassDerivedTwiceStaticClassFunction(engine, ctx) + Expect(err).To(BeNil()) + Expect(classFunction).To(Equal("Derived")) + }) + + // @todo: do we want to test this? You can't really reach this in Go anyway? + /* + test("calling method on unrelated class throws error", function() { + var a = new cm.HasTwoBases; + var e = assert.throws(cm.BindingError, function() { + cm.Derived.prototype.setMember.call(a, "foo"); + }); + assert.equal('Expected null or instance of Derived, got an instance of Base2', e.message); + a.delete(); + + // Base1 and Base2 both have the method 'getField()' exposed - make sure + // that calling the Base2 function with a 'this' instance of Base1 doesn't accidentally work! + var b = new cm.Base1; + var e = assert.throws(cm.BindingError, function() { + cm.Base2.prototype.getField.call(b); + }); + assert.equal('Expected null or instance of Base2, got an instance of Base1', e.message); + b.delete(); + }); + + test("calling method with invalid this throws error", function() { + var e = assert.throws(cm.BindingError, function() { + cm.Derived.prototype.setMember.call(undefined, "foo"); + }); + assert.equal('Cannot pass "[object global]" as a Derived*', e.message); + + var e = assert.throws(cm.BindingError, function() { + cm.Derived.prototype.setMember.call(true, "foo"); + }); + assert.equal('Cannot pass "true" as a Derived*', e.message); + + var e = assert.throws(cm.BindingError, function() { + cm.Derived.prototype.setMember.call(null, "foo"); + }); + assert.equal('Cannot pass "[object global]" as a Derived*', e.message); + + var e = assert.throws(cm.BindingError, function() { + cm.Derived.prototype.setMember.call(42, "foo"); + }); + assert.equal('Cannot pass "42" as a Derived*', e.message); + + var e = assert.throws(cm.BindingError, function() { + cm.Derived.prototype.setMember.call("this", "foo"); + }); + assert.equal('Cannot pass "this" as a Derived*', e.message); + + var e = assert.throws(cm.BindingError, function() { + cm.Derived.prototype.setMember.call({}, "foo"); + }); + assert.equal('Cannot pass "[object Object]" as a Derived*', e.message); + }); + + test("setting and getting property on unrelated class throws error", function() { + var a = new cm.HasTwoBases; + var e = assert.throws(cm.BindingError, function() { + Object.getOwnPropertyDescriptor(cm.HeldBySmartPtr.prototype, 'i').set.call(a, 10); + }); + assert.equal('HeldBySmartPtr.i setter incompatible with "this" of type HasTwoBases', e.message); + + var e = assert.throws(cm.BindingError, function() { + Object.getOwnPropertyDescriptor(cm.HeldBySmartPtr.prototype, 'i').get.call(a); + }); + assert.equal('HeldBySmartPtr.i getter incompatible with "this" of type HasTwoBases', e.message); + + a.delete(); + }); + */ + + }) + + When("automatic upcasting of parameters passed to C++", func() { + It("raw pointer argument is upcast to parameter type", func() { + derived, err := generated.NewClassDerived(engine, ctx) + Expect(err).To(BeNil()) + + name, err := generated.Embind_test_get_class_name_via_base_ptr(engine, ctx, derived) + Expect(err).To(BeNil()) + Expect(name).To(Equal("Base")) + err = derived.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("automatic raw pointer upcasting works with multiple inheritance", func() { + derived, err := generated.NewClassMultiplyDerived(engine, ctx) + Expect(err).To(BeNil()) + + name, err := generated.Embind_test_get_class_name_via_base_ptr(engine, ctx, derived) + Expect(err).To(BeNil()) + Expect(name).To(Equal("Base")) + err = derived.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("automatic raw pointer upcasting does not change local pointer", func() { + derived, err := generated.NewClassMultiplyDerived(engine, ctx) + Expect(err).To(BeNil()) + + _, err = generated.Embind_test_get_class_name_via_base_ptr(engine, ctx, derived) + Expect(err).To(BeNil()) + + name, err := derived.GetClassName(ctx) + Expect(err).To(BeNil()) + Expect(name).To(Equal("MultiplyDerived")) + + err = derived.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("passing incompatible raw pointer to method throws exception", func() { + base, err := generated.NewClassBase(engine, ctx) + Expect(err).To(BeNil()) + + _, err = generated.Embind_test_get_class_name_via_second_base_ptr(engine, ctx, base) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("expected null or instance of SecondBase, got an instance of Base")) + } + + err = base.Delete(ctx) + Expect(err).To(BeNil()) + + }) + + // raw polymorphic + It("polymorphic raw pointer argument is upcast to parameter type", func() { + derived, err := generated.NewClassPolyDerived(engine, ctx) + Expect(err).To(BeNil()) + + name, err := generated.Embind_test_get_class_name_via_polymorphic_base_ptr(engine, ctx, derived) + Expect(err).To(BeNil()) + Expect(name).To(Equal("PolyBase")) + + err = derived.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("automatic polymorphic raw pointer upcasting works with multiple inheritance", func() { + derived, err := generated.NewClassPolyMultiplyDerived(engine, ctx) + Expect(err).To(BeNil()) + + name, err := generated.Embind_test_get_class_name_via_polymorphic_base_ptr(engine, ctx, derived) + Expect(err).To(BeNil()) + Expect(name).To(Equal("PolyBase")) + + err = derived.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("passing incompatible raw polymorphic pointer to method throws exception", func() { + base, err := generated.NewClassPolyBase(engine, ctx) + Expect(err).To(BeNil()) + + _, err = generated.Embind_test_get_class_name_via_polymorphic_second_base_ptr(engine, ctx, base) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("expected null or instance of PolySecondBase, got an instance of PolyBase")) + } + + err = base.Delete(ctx) + Expect(err).To(BeNil()) + }) + + // smart + It("can pass smart pointer to raw pointer parameter", func() { + smartBase, err := generated.Embind_test_return_smart_base_ptr(engine, ctx) + Expect(err).To(BeNil()) + + name, err := generated.Embind_test_get_class_name_via_base_ptr(engine, ctx, smartBase) + Expect(err).To(BeNil()) + Expect(name).To(Equal("Base")) + + err = smartBase.(*generated.ClassBase).Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("can pass and upcast smart pointer to raw pointer parameter", func() { + smartDerived, err := generated.Embind_test_return_smart_derived_ptr(engine, ctx) + Expect(err).To(BeNil()) + + name, err := generated.Embind_test_get_class_name_via_base_ptr(engine, ctx, smartDerived) + Expect(err).To(BeNil()) + Expect(name).To(Equal("Base")) + + err = smartDerived.(*generated.ClassDerived).Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("smart pointer argument is upcast to parameter type", func() { + derived, err := generated.Embind_test_return_smart_derived_ptr(engine, ctx) + Expect(err).To(BeNil()) + + // Todo: can we implement these? + //assert.instanceof(derived, cm.Derived) + //assert.instanceof(derived, cm.Base) + + name, err := generated.Embind_test_get_class_name_via_smart_base_ptr(engine, ctx, derived) + Expect(err).To(BeNil()) + Expect(name).To(Equal("Base")) + + err = derived.(*generated.ClassDerived).Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("return smart derived ptr as base", func() { + derived, err := generated.Embind_test_return_smart_derived_ptr_as_base(engine, ctx) + Expect(err).To(BeNil()) + + name, err := generated.Embind_test_get_virtual_class_name_via_smart_polymorphic_base_ptr(engine, ctx, derived) + Expect(err).To(BeNil()) + Expect(name).To(Equal("PolyDerived")) + + name, err = derived.(*generated.ClassPolyDerived).GetClassName(ctx) + Expect(err).To(BeNil()) + Expect(name).To(Equal("PolyDerived")) + + err = derived.(*generated.ClassPolyDerived).Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("return smart derived ptr as val", func() { + derived, err := generated.Embind_test_return_smart_derived_ptr_as_val(engine, ctx) + Expect(err).To(BeNil()) + + name, err := generated.Embind_test_get_virtual_class_name_via_smart_polymorphic_base_ptr(engine, ctx, derived.(*generated.ClassPolyDerived)) + Expect(err).To(BeNil()) + Expect(name).To(Equal("PolyDerived")) + + err = derived.(*generated.ClassPolyDerived).Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("automatic smart pointer upcasting works with multiple inheritance", func() { + derived, err := generated.Embind_test_return_smart_multiply_derived_ptr(engine, ctx) + Expect(err).To(BeNil()) + + name, err := generated.Embind_test_get_class_name_via_smart_base_ptr(engine, ctx, derived) + Expect(err).To(BeNil()) + Expect(name).To(Equal("Base")) + + err = derived.(*generated.ClassMultiplyDerived).Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("automatically upcasted smart pointer parameter shares ownership with original argument", func() { + derived, err := generated.Embind_test_return_smart_multiply_derived_ptr(engine, ctx) + Expect(err).To(BeNil()) + + instanceCount, err := derived.(*generated.ClassMultiplyDerived).StaticGetInstanceCount(ctx) + Expect(err).To(BeNil()) + Expect(instanceCount).To(Equal(int32(1))) + + err = generated.Embind_save_smart_base_pointer(engine, ctx, derived) + Expect(err).To(BeNil()) + + instanceCount, err = derived.(*generated.ClassMultiplyDerived).StaticGetInstanceCount(ctx) + Expect(err).To(BeNil()) + Expect(instanceCount).To(Equal(int32(1))) + + err = derived.(*generated.ClassMultiplyDerived).Delete(ctx) + Expect(err).To(BeNil()) + + instanceCount, err = derived.(*generated.ClassMultiplyDerived).StaticGetInstanceCount(ctx) + Expect(err).To(BeNil()) + Expect(instanceCount).To(Equal(int32(1))) + + err = generated.Embind_save_smart_base_pointer(engine, ctx, nil) + Expect(err).To(BeNil()) + + instanceCount, err = derived.(*generated.ClassMultiplyDerived).StaticGetInstanceCount(ctx) + Expect(err).To(BeNil()) + Expect(instanceCount).To(Equal(int32(0))) + }) + + // smart polymorphic + It("smart polymorphic pointer argument is upcast to parameter type", func() { + derived, err := generated.Embind_test_return_smart_polymorphic_derived_ptr(engine, ctx) + Expect(err).To(BeNil()) + + name, err := generated.Embind_test_get_class_name_via_smart_polymorphic_base_ptr(engine, ctx, derived) + Expect(err).To(BeNil()) + Expect(name).To(Equal("PolyBase")) + + err = derived.(*generated.ClassPolyDerived).Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("automatic smart polymorphic pointer upcasting works with multiple inheritance", func() { + derived, err := generated.Embind_test_return_smart_polymorphic_multiply_derived_ptr(engine, ctx) + Expect(err).To(BeNil()) + + name, err := generated.Embind_test_get_class_name_via_smart_polymorphic_base_ptr(engine, ctx, derived) + Expect(err).To(BeNil()) + Expect(name).To(Equal("PolyBase")) + + err = derived.(*generated.ClassPolyMultiplyDerived).Delete(ctx) + Expect(err).To(BeNil()) + }) + + }) + When("automatic downcasting of return values received from C++", func() { + // raw + It("non-polymorphic raw pointers are not downcast and do not break automatic casting mechanism", func() { + base, err := generated.Embind_test_return_raw_derived_ptr_as_base(engine, ctx) + Expect(err).To(BeNil()) + + name, err := base.(*generated.ClassBase).GetClassName(ctx) + Expect(err).To(BeNil()) + Expect(name).To(Equal("Base")) + + err = base.(*generated.ClassBase).Delete(ctx) + Expect(err).To(BeNil()) + }) + + // raw polymorphic + It("polymorphic raw pointer return value is downcast to allocated type (if that is bound)", func() { + derived, err := generated.Embind_test_return_raw_polymorphic_derived_ptr_as_base(engine, ctx) + Expect(err).To(BeNil()) + + name, err := derived.(*generated.ClassPolyDerived).GetClassName(ctx) + Expect(err).To(BeNil()) + Expect(name).To(Equal("PolyDerived")) + + //assert.instanceof(derived, cm.PolyBase) + //assert.instanceof(derived, cm.PolyDerived) + + siblingDerived, err := generated.Embind_test_return_raw_polymorphic_sibling_derived_ptr_as_base(engine, ctx) + Expect(err).To(BeNil()) + + name, err = siblingDerived.(*generated.ClassPolySiblingDerived).GetClassName(ctx) + Expect(err).To(BeNil()) + Expect(name).To(Equal("PolySiblingDerived")) + + err = siblingDerived.(*generated.ClassPolySiblingDerived).Delete(ctx) + Expect(err).To(BeNil()) + + err = derived.(*generated.ClassPolyDerived).Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("polymorphic raw pointer return value is downcast to the most derived bound type", func() { + derivedThrice, err := generated.Embind_test_return_raw_polymorphic_derived_four_times_not_bound_as_base(engine, ctx) + Expect(err).To(BeNil()) + + // if the actual returned type is not bound, then don't assume anything + name, err := derivedThrice.(*generated.ClassPolyBase).GetClassName(ctx) + Expect(err).To(BeNil()) + Expect(name).To(Equal("PolyBase")) + + // if we ever fix this, then reverse the assertion (comment from Emscripten) + //assert.equal("PolyDerivedThrice", derivedThrice.getClassName()); + + err = derivedThrice.(*generated.ClassPolyBase).Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("polymorphic smart pointer return value is downcast to the most derived type which has an associated smart pointer", func() { + derived, err := generated.Embind_test_return_poly_derived_twice_without_smart_pointer_as_poly_base(engine, ctx) + Expect(err).To(BeNil()) + + // if the actual returned type is not bound, then don't assume anything + name, err := derived.(*generated.ClassPolyBase).GetClassName(ctx) + Expect(err).To(BeNil()) + Expect(name).To(Equal("PolyBase")) + + // if we ever fix this, then reverse the assertion (comment from Emscripten) + //assert.equal("PolyDerived", derivedThrice.getClassName()); + + err = derived.(*generated.ClassPolyBase).Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("automatic downcasting works with multiple inheritance", func() { + base, err := generated.Embind_test_return_raw_polymorphic_multiply_derived_ptr_as_base(engine, ctx) + Expect(err).To(BeNil()) + + secondBase, err := generated.Embind_test_return_raw_polymorphic_multiply_derived_ptr_as_second_base(engine, ctx) + Expect(err).To(BeNil()) + + name, err := base.(*generated.ClassPolyMultiplyDerived).GetClassName(ctx) + Expect(err).To(BeNil()) + Expect(name).To(Equal("PolyMultiplyDerived")) + + // embind does not support multiple inheritance + //assert.equal("PolyMultiplyDerived", secondBase.getClassName()); + + err = secondBase.(*generated.ClassPolySecondBase).Delete(ctx) + Expect(err).To(BeNil()) + + err = base.(*generated.ClassPolyMultiplyDerived).Delete(ctx) + Expect(err).To(BeNil()) + }) + + // smart polymorphic + It("automatically downcasting a smart pointer does not change the underlying pointer", func() { + err := generated.ClassPolyDerivedStaticSetPtrDerived(engine, ctx) + Expect(err).To(BeNil()) + + name, err := generated.ClassPolyDerivedStaticGetPtrClassName(engine, ctx) + Expect(err).To(BeNil()) + Expect(name).To(Equal("PolyBase")) + + derived, err := generated.ClassPolyDerivedStaticGetPtr(engine, ctx) + Expect(err).To(BeNil()) + + name, err = derived.(*generated.ClassPolyDerived).GetClassName(ctx) + Expect(err).To(BeNil()) + Expect(name).To(Equal("PolyDerived")) + + name, err = generated.ClassPolyDerivedStaticGetPtrClassName(engine, ctx) + Expect(err).To(BeNil()) + Expect(name).To(Equal("PolyBase")) + + err = derived.(*generated.ClassPolyDerived).Delete(ctx) + Expect(err).To(BeNil()) + + err = generated.ClassPolyDerivedStaticReleasePtr(engine, ctx) + Expect(err).To(BeNil()) + }) + + It("polymorphic smart pointer return value is actual allocated type (when bound)", func() { + derived, err := generated.Embind_test_return_smart_polymorphic_derived_ptr_as_base(engine, ctx) + Expect(err).To(BeNil()) + + name, err := derived.(*generated.ClassPolyDerived).GetClassName(ctx) + Expect(err).To(BeNil()) + Expect(name).To(Equal("PolyDerived")) + + siblingDerived, err := generated.Embind_test_return_smart_polymorphic_sibling_derived_ptr_as_base(engine, ctx) + Expect(err).To(BeNil()) + + name, err = siblingDerived.(*generated.ClassPolySiblingDerived).GetClassName(ctx) + Expect(err).To(BeNil()) + Expect(name).To(Equal("PolySiblingDerived")) + + err = siblingDerived.(*generated.ClassPolySiblingDerived).Delete(ctx) + Expect(err).To(BeNil()) + + err = derived.(*generated.ClassPolyDerived).Delete(ctx) + Expect(err).To(BeNil()) + }) + + }) + When("string", func() { + // var stdStringIsUTF8 = (cm.getCompilerSetting('EMBIND_STD_STRING_IS_UTF8') === true); + // We only support that this is true. + stdStringIsUTF8 := true + + It("non-ascii strings", func() { + + //if(stdStringIsUTF8) { + + //ASCII + expected := "aei" + //Latin-1 Supplement + expected += "\u00E1\u00E9\u00ED" + //Greek + expected += "\u03B1\u03B5\u03B9" + //Cyrillic + expected += "\u0416\u041B\u0424" + //CJK + expected += "\u5F9E\u7345\u5B50" + //Euro sign + expected += "\u20AC" + + //} else { + // for (var i = 0; i < 128; ++i) { + // expected += String.fromCharCode(128 + i); + // } + // } + + non_ascii_string, err := generated.Get_non_ascii_string(engine, ctx, stdStringIsUTF8) + Expect(err).To(BeNil()) + Expect(non_ascii_string).To(Equal(expected)) + }) + + /* + if(!stdStringIsUTF8) { + It("passing non-8-bit strings from JS to std::string throws", func() { + assert.throws(cm.BindingError, function() { + cm.emval_test_take_and_return_std_string("\u1234"); + }); + }); + } + */ + + It("can't pass integers as strings", func() { + _, err := engine.CallPublicSymbol(ctx, "emval_test_take_and_return_std_string", 10) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("value must be of type string")) + } + }) + + /* + It("can pass Uint8Array to std::string", func() { + var e = cm.emval_test_take_and_return_std_string(new Uint8Array([65, 66, 67, 68])); + assert.equal('ABCD', e); + }); + + It("can pass Uint8ClampedArray to std::string", func() { + var e = cm.emval_test_take_and_return_std_string(new Uint8ClampedArray([65, 66, 67, 68])); + assert.equal('ABCD', e); + }); + + It("can pass Int8Array to std::string", func() { + var e = cm.emval_test_take_and_return_std_string(new Int8Array([65, 66, 67, 68])); + assert.equal('ABCD', e); + }); + + It("can pass ArrayBuffer to std::string", func() { + var e = cm.emval_test_take_and_return_std_string((new Int8Array([65, 66, 67, 68])).buffer); + assert.equal('ABCD', e); + }); + + It("can pass Uint8Array to std::basic_string", func() { + var e = cm.emval_test_take_and_return_std_basic_string_unsigned_char(new Uint8Array([65, 66, 67, 68])); + assert.equal('ABCD', e); + }); + + It("can pass long string to std::basic_string", func() { + var s = 'this string is long enough to exceed the short string optimization'; + var e = cm.emval_test_take_and_return_std_basic_string_unsigned_char(s); + assert.equal(s, e); + }); + + It("can pass Uint8ClampedArray to std::basic_string", func() { + var e = cm.emval_test_take_and_return_std_basic_string_unsigned_char(new Uint8ClampedArray([65, 66, 67, 68])); + assert.equal('ABCD', e); + }); + + + It("can pass Int8Array to std::basic_string", func() { + var e = cm.emval_test_take_and_return_std_basic_string_unsigned_char(new Int8Array([65, 66, 67, 68])); + assert.equal('ABCD', e); + }); + + It("can pass ArrayBuffer to std::basic_string", func() { + var e = cm.emval_test_take_and_return_std_basic_string_unsigned_char((new Int8Array([65, 66, 67, 68])).buffer); + assert.equal('ABCD', e); + }); + + It("can pass string to std::string", func() { + //var string = stdStringIsUTF8?"aeiáéíαειЖЛФ從獅子€":"ABCD"; + + string := "aeiáéíαειЖЛФ從獅子€" + + var e = cm.emval_test_take_and_return_std_string(string); + assert.equal(string, e); + }); + + var utf16TestString = String.fromCharCode(10) + + String.fromCharCode(1234) + + String.fromCharCode(2345) + + String.fromCharCode(65535); + + var utf32TestString = String.fromCharCode(10) + + String.fromCharCode(1234) + + String.fromCharCode(2345) + + String.fromCharCode(55357) + + String.fromCharCode(56833) + + String.fromCharCode(55357) + + String.fromCharCode(56960); + + It("non-ascii wstrings", func() { + assert.equal(utf16TestString, cm.get_non_ascii_wstring()); + }); + + It("non-ascii u16strings", func() { + assert.equal(utf16TestString, cm.get_non_ascii_u16string()); + }); + + It("non-ascii u32strings", func() { + assert.equal(utf32TestString, cm.get_non_ascii_u32string()); + }); + + It("passing unicode (wide) string into C++", func() { + assert.equal(utf16TestString, cm.take_and_return_std_wstring(utf16TestString)); + }); + + It("passing unicode (utf-16) string into C++", func() { + assert.equal(utf16TestString, cm.take_and_return_std_u16string(utf16TestString)); + }); + + It("passing unicode (utf-32) string into C++", func() { + assert.equal(utf32TestString, cm.take_and_return_std_u32string(utf32TestString)); + }); + + //if (cm.isMemoryGrowthEnabled) { + It("can access a literal wstring after a memory growth", func() { + cm.force_memory_growth(); + assert.equal("get_literal_wstring", cm.get_literal_wstring()); + }); + + It("can access a literal u16string after a memory growth", func() { + cm.force_memory_growth(); + assert.equal("get_literal_u16string", cm.get_literal_u16string()); + }); + + It("can access a literal u32string after a memory growth", func() { + cm.force_memory_growth(); + assert.equal("get_literal_u32string", cm.get_literal_u32string()); + }); + //} + */ + }) + When("embind", func() { + /* + test("value creation", function() { + assert.equal(15, cm.emval_test_new_integer()); + assert.equal("Hello everyone", cm.emval_test_new_string()); + assert.equal("Hello everyone", cm.emval_test_get_string_from_val({key: "Hello everyone"})); + + var object = cm.emval_test_new_object(); + assert.equal('bar', object.foo); + assert.equal(1, object.baz); + }); + + test("pass const reference to primitive", function() { + assert.equal(3, cm.const_ref_adder(1, 2)); + }); + + test("get instance pointer as value", function() { + var v = cm.emval_test_instance_pointer(); + assert.instanceof(v, cm.DummyForPointer); + }); + + test("cast value to instance pointer using as", function() { + var v = cm.emval_test_instance_pointer(); + var p_value = cm.emval_test_value_from_instance_pointer(v); + assert.equal(42, p_value); + }); + + test("passthrough", function() { + var a = {foo: 'bar'}; + var b = cm.emval_test_passthrough(a); + a.bar = 'baz'; + assert.equal('baz', b.bar); + + assert.equal(0, cm.count_emval_handles()); + }); + + test("void return converts to undefined", function() { + assert.equal(undefined, cm.emval_test_return_void()); + }); + + test("booleans can be marshalled", function() { + assert.equal(false, cm.emval_test_not(true)); + assert.equal(true, cm.emval_test_not(false)); + }); + + test("val.is_undefined() is functional",function() { + assert.equal(true, cm.emval_test_is_undefined(undefined)); + assert.equal(false, cm.emval_test_is_undefined(true)); + assert.equal(false, cm.emval_test_is_undefined(false)); + assert.equal(false, cm.emval_test_is_undefined(null)); + assert.equal(false, cm.emval_test_is_undefined({})); + }); + + test("val.is_null() is functional",function() { + assert.equal(true, cm.emval_test_is_null(null)); + assert.equal(false, cm.emval_test_is_null(true)); + assert.equal(false, cm.emval_test_is_null(false)); + assert.equal(false, cm.emval_test_is_null(undefined)); + assert.equal(false, cm.emval_test_is_null({})); + }); + + test("val.is_true() is functional",function() { + assert.equal(true, cm.emval_test_is_true(true)); + assert.equal(false, cm.emval_test_is_true(false)); + assert.equal(false, cm.emval_test_is_true(null)); + assert.equal(false, cm.emval_test_is_true(undefined)); + assert.equal(false, cm.emval_test_is_true({})); + }); + + test("val.is_false() is functional",function() { + assert.equal(true, cm.emval_test_is_false(false)); + assert.equal(false, cm.emval_test_is_false(true)); + assert.equal(false, cm.emval_test_is_false(null)); + assert.equal(false, cm.emval_test_is_false(undefined)); + assert.equal(false, cm.emval_test_is_false({})); + }); + + test("val.equals() is functional",function() { + var values = [undefined, null, true, false, {}]; + + for(var i=0;i 0 + assert.true(isNaN(cm.const_ref_adder(1, 'cannot parse'))); + assert.true(isNaN(cm.const_ref_adder(1, undefined))); // undefined => NaN + }); + } + + test("convert double to unsigned", function() { + var rv = cm.emval_test_as_unsigned(1.5); + assert.equal('number', typeof rv); + assert.equal(1, rv); + assert.equal(0, cm.count_emval_handles()); + }); + + test("get length of array", function() { + assert.equal(10, cm.emval_test_get_length([0, 1, 2, 3, 4, 5, 'a', 'b', 'c', 'd'])); + assert.equal(0, cm.count_emval_handles()); + }); + + test("add a bunch of things", function() { + assert.equal(66.0, cm.emval_test_add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)); + assert.equal(0, cm.count_emval_handles()); + }); + + test("sum array", function() { + assert.equal(66, cm.emval_test_sum([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])); + assert.equal(0, cm.count_emval_handles()); + }); + + test("strings", function() { + assert.equal("foobar", "foo" + "bar"); + assert.equal("foobar", cm.emval_test_take_and_return_std_string("foobar")); + + assert.equal("foobar", cm.emval_test_take_and_return_std_string_const_ref("foobar")); + }); + + test("nuls pass through strings", function() { + assert.equal("foo\0bar", cm.emval_test_take_and_return_std_string("foo\0bar")); + }); + + test("no memory leak when passing strings in by const reference", function() { + cm.emval_test_take_and_return_std_string_const_ref("foobar"); + }); + + test("can get global", function(){ + assert.equal((new Function("return this;"))(), cm.embind_test_getglobal()); + }); + + test("can create new object", function() { + assert.deepEqual({}, cm.embind_test_new_Object()); + }); + + test("can invoke constructors with arguments", function() { + function constructor(i, s, argument) { + this.i = i; + this.s = s; + this.argument = argument; + } + constructor.prototype.method = function() { + return this.argument; + }; + var x = {}; + var instance = cm.embind_test_new_factory(constructor, x); + assert.equal(10, instance.i); + assert.equal("hello", instance.s); + assert.equal(x, instance.argument); + }); + + test("can return module property objects", function() { + assert.equal(cm.HEAP8, cm.get_module_property("HEAP8")); + }); + + test("can return big class instances", function() { + var c = cm.embind_test_return_big_class_instance(); + assert.equal(11, c.member); + c.delete(); + }); + + test("can return small class instances", function() { + var c = cm.embind_test_return_small_class_instance(); + assert.equal(7, c.member); + c.delete(); + }); + + test("can pass small class instances", function() { + var c = new cm.SmallClass(); + var m = cm.embind_test_accept_small_class_instance(c); + assert.equal(7, m); + c.delete(); + }); + + test("can pass big class instances", function() { + var c = new cm.BigClass(); + var m = cm.embind_test_accept_big_class_instance(c); + assert.equal(11, m); + c.delete(); + }); + + test("can pass unique_ptr", function() { + var p = cm.embind_test_return_unique_ptr(42); + var m = cm.embind_test_accept_unique_ptr(p); + assert.equal(42, m); + }); + + test("can pass unique_ptr to constructor", function() { + var c = new cm.embind_test_construct_class_with_unique_ptr(42); + assert.equal(42, c.getValue()); + c.delete(); + }); + + test("can get member classes then call its member functions", function() { + var p = new cm.ParentClass(); + var c = p.getBigClass(); + var m = c.getMember(); + assert.equal(11, m); + c.delete(); + p.delete(); + }); + + test('C++ -> JS primitive type range checks', function() { + // all types should have zero. + assert.equal("0", cm.char_to_string(0)); + assert.equal("0", cm.signed_char_to_string(0)); + assert.equal("0", cm.unsigned_char_to_string(0)); + assert.equal("0", cm.short_to_string(0)); + assert.equal("0", cm.unsigned_short_to_string(0)); + assert.equal("0", cm.int_to_string(0)); + assert.equal("0", cm.unsigned_int_to_string(0)); + assert.equal("0", cm.long_to_string(0)); + assert.equal("0", cm.unsigned_long_to_string(0)); + + // all types should have positive values. + assert.equal("5", cm.char_to_string(5)); + assert.equal("5", cm.signed_char_to_string(5)); + assert.equal("5", cm.unsigned_char_to_string(5)); + assert.equal("5", cm.short_to_string(5)); + assert.equal("5", cm.unsigned_short_to_string(5)); + assert.equal("5", cm.int_to_string(5)); + assert.equal("5", cm.unsigned_int_to_string(5)); + assert.equal("5", cm.long_to_string(5)); + assert.equal("5", cm.unsigned_long_to_string(5)); + + // signed types should have negative values. + assert.equal("-5", cm.char_to_string(-5)); // Assuming char as signed. + assert.equal("-5", cm.signed_char_to_string(-5)); + assert.equal("-5", cm.short_to_string(-5)); + assert.equal("-5", cm.int_to_string(-5)); + assert.equal("-5", cm.long_to_string(-5)); + + // assumptions: char == signed char == 8 bits + // unsigned char == 8 bits + // short == 16 bits + // int == long == 32 bits + + // all types should have their max positive values. + assert.equal("127", cm.char_to_string(127)); + assert.equal("127", cm.signed_char_to_string(127)); + assert.equal("255", cm.unsigned_char_to_string(255)); + assert.equal("32767", cm.short_to_string(32767)); + assert.equal("65535", cm.unsigned_short_to_string(65535)); + assert.equal("2147483647", cm.int_to_string(2147483647)); + assert.equal("4294967295", cm.unsigned_int_to_string(4294967295)); + assert.equal("2147483647", cm.long_to_string(2147483647)); + assert.equal("4294967295", cm.unsigned_long_to_string(4294967295)); + + // signed types should have their min negative values. + assert.equal("-128", cm.char_to_string(-128)); + assert.equal("-128", cm.signed_char_to_string(-128)); + assert.equal("-32768", cm.short_to_string(-32768)); + assert.equal("-2147483648", cm.int_to_string(-2147483648)); + assert.equal("-2147483648", cm.long_to_string(-2147483648)); + + // passing out of range values should fail with assertions. + if (cm.getCompilerSetting('ASSERTIONS')) { + assert.throws(TypeError, function() { cm.char_to_string(-129); }); + assert.throws(TypeError, function() { cm.char_to_string(128); }); + assert.throws(TypeError, function() { cm.signed_char_to_string(-129); }); + assert.throws(TypeError, function() { cm.signed_char_to_string(128); }); + assert.throws(TypeError, function() { cm.unsigned_char_to_string(-1); }); + assert.throws(TypeError, function() { cm.unsigned_char_to_string(256); }); + assert.throws(TypeError, function() { cm.short_to_string(-32769); }); + assert.throws(TypeError, function() { cm.short_to_string(32768); }); + assert.throws(TypeError, function() { cm.unsigned_short_to_string(-1); }); + assert.throws(TypeError, function() { cm.unsigned_short_to_string(65536); }); + assert.throws(TypeError, function() { cm.int_to_string(-2147483649); }); + assert.throws(TypeError, function() { cm.int_to_string(2147483648); }); + assert.throws(TypeError, function() { cm.unsigned_int_to_string(-1); }); + assert.throws(TypeError, function() { cm.unsigned_int_to_string(4294967296); }); + assert.throws(TypeError, function() { cm.long_to_string(-2147483649); }); + assert.throws(TypeError, function() { cm.long_to_string(2147483648); }); + assert.throws(TypeError, function() { cm.unsigned_long_to_string(-1); }); + assert.throws(TypeError, function() { cm.unsigned_long_to_string(4294967296); }); + } else { + // test that an out of range value doesn't throw without assertions. + assert.equal("-129", cm.char_to_string(-129)); + } + }); + + test("unsigned values are correctly returned when stored in memory", function() { + cm.store_unsigned_char(255); + assert.equal(255, cm.load_unsigned_char()); + + cm.store_unsigned_short(32768); + assert.equal(32768, cm.load_unsigned_short()); + + cm.store_unsigned_int(2147483648); + assert.equal(2147483648, cm.load_unsigned_int()); + + cm.store_unsigned_long(2147483648); + assert.equal(2147483648, cm.load_unsigned_long()); + }); + + if (cm.getCompilerSetting('ASSERTIONS')) { + test("throws type error when attempting to coerce null to int", function() { + var e = assert.throws(TypeError, function() { + cm.int_to_string(null); + }); + assert.equal('Cannot convert "null" to int', e.message); + }); + } else { + test("null is converted to 0 without assertions", function() { + assert.equal('0', cm.int_to_string(null)); + }); + } + + test("access multiple class ctors", function() { + var a = new cm.MultipleCtors(10); + assert.equal(a.WhichCtorCalled(), 1); + var b = new cm.MultipleCtors(20, 20); + assert.equal(b.WhichCtorCalled(), 2); + var c = new cm.MultipleCtors(30, 30, 30); + assert.equal(c.WhichCtorCalled(), 3); + a.delete(); + b.delete(); + c.delete(); + }); + + test("access multiple smart ptr ctors", function() { + var a = new cm.MultipleSmartCtors(10); + assert.equal(a.WhichCtorCalled(), 1); + var b = new cm.MultipleCtors(20, 20); + assert.equal(b.WhichCtorCalled(), 2); + a.delete(); + b.delete(); + }); + + test("wrong number of constructor arguments throws", function() { + assert.throws(cm.BindingError, function() { new cm.MultipleCtors(); }); + assert.throws(cm.BindingError, function() { new cm.MultipleCtors(1,2,3,4); }); + }); + + test("overloading of free functions", function() { + var a = cm.overloaded_function(10); + assert.equal(a, 1); + var b = cm.overloaded_function(20, 20); + assert.equal(b, 2); + }); + + test("wrong number of arguments to an overloaded free function", function() { + assert.throws(cm.BindingError, function() { cm.overloaded_function(); }); + assert.throws(cm.BindingError, function() { cm.overloaded_function(30, 30, 30); }); + }); + + test("overloading of class member functions", function() { + var foo = new cm.MultipleOverloads(); + assert.equal(foo.Func(10), 1); + assert.equal(foo.WhichFuncCalled(), 1); + assert.equal(foo.Func(20, 20), 2); + assert.equal(foo.WhichFuncCalled(), 2); + foo.delete(); + }); + + test("wrong number of arguments to an overloaded class member function", function() { + var foo = new cm.MultipleOverloads(); + assert.throws(cm.BindingError, function() { foo.Func(); }); + assert.throws(cm.BindingError, function() { foo.Func(30, 30, 30); }); + foo.delete(); + }); + + test("wrong number of arguments to an overloaded class static function", function() { + assert.throws(cm.BindingError, function() { cm.MultipleOverloads.StaticFunc(); }); + assert.throws(cm.BindingError, function() { cm.MultipleOverloads.StaticFunc(30, 30, 30); }); + }); + + test("overloading of derived class member functions", function() { + var foo = new cm.MultipleOverloadsDerived(); + + // NOTE: In C++, default lookup rules will hide overloads from base class if derived class creates them. + // In JS, we make the base class overloads implicitly available. In C++, they would need to be explicitly + // invoked, like foo.MultipleOverloads::Func(10); + assert.equal(foo.Func(10), 1); + assert.equal(foo.WhichFuncCalled(), 1); + assert.equal(foo.Func(20, 20), 2); + assert.equal(foo.WhichFuncCalled(), 2); + + assert.equal(foo.Func(30, 30, 30), 3); + assert.equal(foo.WhichFuncCalled(), 3); + assert.equal(foo.Func(40, 40, 40, 40), 4); + assert.equal(foo.WhichFuncCalled(), 4); + foo.delete(); + }); + + test("overloading of class static functions", function() { + assert.equal(cm.MultipleOverloads.StaticFunc(10), 1); + assert.equal(cm.MultipleOverloads.WhichStaticFuncCalled(), 1); + assert.equal(cm.MultipleOverloads.StaticFunc(20, 20), 2); + assert.equal(cm.MultipleOverloads.WhichStaticFuncCalled(), 2); + }); + + test("overloading of derived class static functions", function() { + assert.equal(cm.MultipleOverloadsDerived.StaticFunc(30, 30, 30), 3); + // TODO: Cannot access static member functions of a Base class via Derived. + // assert.equal(cm.MultipleOverloadsDerived.WhichStaticFuncCalled(), 3); + assert.equal(cm.MultipleOverloads.WhichStaticFuncCalled(), 3); + assert.equal(cm.MultipleOverloadsDerived.StaticFunc(40, 40, 40, 40), 4); + // TODO: Cannot access static member functions of a Base class via Derived. + // assert.equal(cm.MultipleOverloadsDerived.WhichStaticFuncCalled(), 4); + assert.equal(cm.MultipleOverloads.WhichStaticFuncCalled(), 4); + }); + + test("class member function named with a well-known symbol", function() { + var instance = new cm.SymbolNameClass(); + assert.equal("Iterator", instance[Symbol.iterator]()); + assert.equal("Species", cm.SymbolNameClass[Symbol.species]()); + }); + + test("no undefined entry in overload table when depending on already bound types", function() { + var dummy_overloads = cm.MultipleOverloadsDependingOnDummy.prototype.dummy; + // check if the overloadTable is correctly named + // it can be minimized if using closure compiler + if (dummy_overloads.hasOwnProperty('overloadTable')) { + assert.false(dummy_overloads.overloadTable.hasOwnProperty('undefined')); + } + + var dummy_static_overloads = cm.MultipleOverloadsDependingOnDummy.staticDummy; + // check if the overloadTable is correctly named + // it can be minimized if using closure compiler + if (dummy_static_overloads.hasOwnProperty('overloadTable')) { + assert.false(dummy_static_overloads.overloadTable.hasOwnProperty('undefined')); + } + + // this part should fail anyway if there is no overloadTable + var dependOnDummy = new cm.MultipleOverloadsDependingOnDummy(); + var dummy = dependOnDummy.dummy(); + dependOnDummy.dummy(dummy); + dummy.delete(); + dependOnDummy.delete(); + + // this part should fail anyway if there is no overloadTable + var dummy = cm.MultipleOverloadsDependingOnDummy.staticDummy(); + cm.MultipleOverloadsDependingOnDummy.staticDummy(dummy); + dummy.delete(); + }); + + test("no undefined entry in overload table for free functions", function() { + var dummy_free_func = cm.getDummy; + console.log(dummy_free_func); + + if (dummy_free_func.hasOwnProperty('overloadTable')) { + assert.false(dummy_free_func.overloadTable.hasOwnProperty('undefined')); + } + + var dummy = cm.getDummy(); + cm.getDummy(dummy); + }); + */ + }) + + When("vector", func() { + It("std::vector returns as an native object", func() { + vec, err := generated.Emval_test_return_vector(engine, ctx) + + size, err := vec.CallInstanceMethod(ctx, vec, "size") + Expect(err).To(BeNil()) + Expect(size).To(Equal(uint32(3))) + + get0, err := vec.CallInstanceMethod(ctx, vec, "get", uint32(0)) + Expect(err).To(BeNil()) + Expect(get0).To(Equal(int32(10))) + + get1, err := vec.CallInstanceMethod(ctx, vec, "get", uint32(1)) + Expect(err).To(BeNil()) + Expect(get1).To(Equal(int32(20))) + + get2, err := vec.CallInstanceMethod(ctx, vec, "get", uint32(2)) + Expect(err).To(BeNil()) + Expect(get2).To(Equal(int32(30))) + + err = vec.DeleteInstance(ctx, vec) + Expect(err).To(BeNil()) + }) + + It("out of bounds std::vector access returns undefined", func() { + vec, err := generated.Emval_test_return_vector(engine, ctx) + + get4, err := vec.CallInstanceMethod(ctx, vec, "get", uint32(4)) + Expect(err).To(BeNil()) + Expect(get4).To(Equal(types.Undefined)) + + err = vec.DeleteInstance(ctx, vec) + Expect(err).To(BeNil()) + }) + + It("std::vector> can be passed back", func() { + vec, err := generated.Emval_test_return_shared_ptr_vector(engine, ctx) + Expect(err).To(BeNil()) + + size, err := vec.CallInstanceMethod(ctx, vec, "size") + Expect(err).To(BeNil()) + Expect(size).To(Equal(uint32(2))) + + str0, err := vec.CallInstanceMethod(ctx, vec, "get", uint32(0)) + Expect(err).To(BeNil()) + + str1, err := vec.CallInstanceMethod(ctx, vec, "get", uint32(1)) + Expect(err).To(BeNil()) + + str0Str, err := str0.(embind.IClassBase).CallInstanceMethod(ctx, str0, "get") + Expect(err).To(BeNil()) + Expect(str0Str).To(Equal("string #1")) + + str1Str, err := str1.(embind.IClassBase).CallInstanceMethod(ctx, str1, "get") + Expect(err).To(BeNil()) + Expect(str1Str).To(Equal("string #2")) + + err = str0.(embind.IClassBase).DeleteInstance(ctx, str0.(embind.IClassBase)) + Expect(err).To(BeNil()) + + err = str1.(embind.IClassBase).DeleteInstance(ctx, str1.(embind.IClassBase)) + Expect(err).To(BeNil()) + + err = vec.DeleteInstance(ctx, vec) + Expect(err).To(BeNil()) + }) + + It("objects can be pushed back", func() { + vectorHolder, err := generated.NewClassVectorHolder(engine, ctx) + Expect(err).To(BeNil()) + + vec, err := vectorHolder.Get(ctx) + Expect(err).To(BeNil()) + + size, err := vec.CallInstanceMethod(ctx, vec, "size") + Expect(size).To(Equal(uint32(2))) + + str, err := generated.NewClassStringHolder(engine, ctx, "abc") + Expect(err).To(BeNil()) + + _, err = vec.CallInstanceMethod(ctx, vec, "push_back", str) + Expect(err).To(BeNil()) + + err = str.Delete(ctx) + Expect(err).To(BeNil()) + + size, err = vec.CallInstanceMethod(ctx, vec, "size") + Expect(err).To(BeNil()) + Expect(size).To(Equal(uint32(3))) + + getStr, err := vec.CallInstanceMethod(ctx, vec, "get", uint32(2)) + Expect(err).To(BeNil()) + + getStrGet, err := getStr.(embind.IClassBase).CallInstanceMethod(ctx, getStr, "get") + Expect(err).To(BeNil()) + Expect(getStrGet).To(Equal("abc")) + + err = getStr.(embind.IClassBase).DeleteInstance(ctx, getStr.(embind.IClassBase)) + Expect(err).To(BeNil()) + + err = vec.DeleteInstance(ctx, vec) + Expect(err).To(BeNil()) + + err = vectorHolder.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("can get elements with array operator", func() { + vec, err := generated.Emval_test_return_vector(engine, ctx) + Expect(err).To(BeNil()) + + get, err := vec.CallInstanceMethod(ctx, vec, "get", uint32(0)) + Expect(err).To(BeNil()) + Expect(get).To(Equal(int32(10))) + + err = vec.DeleteInstance(ctx, vec) + Expect(err).To(BeNil()) + }) + + It("can set elements with array operator", func() { + vec, err := generated.Emval_test_return_vector(engine, ctx) + Expect(err).To(BeNil()) + + get0, err := vec.CallInstanceMethod(ctx, vec, "get", uint32(0)) + Expect(err).To(BeNil()) + Expect(get0).To(Equal(int32(10))) + + _, err = vec.CallInstanceMethod(ctx, vec, "set", uint32(2), int32(60)) + Expect(err).To(BeNil()) + + get2, err := vec.CallInstanceMethod(ctx, vec, "get", uint32(2)) + Expect(err).To(BeNil()) + Expect(get2).To(Equal(int32(60))) + + err = vec.DeleteInstance(ctx, vec) + Expect(err).To(BeNil()) + }) + + It("can set and get objects", func() { + vec, err := generated.Emval_test_return_shared_ptr_vector(engine, ctx) + Expect(err).To(BeNil()) + + str, err := vec.CallInstanceMethod(ctx, vec, "get", uint32(0)) + Expect(err).To(BeNil()) + + strGetStr, err := str.(embind.IClassBase).CallInstanceMethod(ctx, str.(embind.IClassBase), "get") + Expect(err).To(BeNil()) + Expect(strGetStr).To(Equal("string #1")) + + err = str.(embind.IClassBase).DeleteInstance(ctx, str.(embind.IClassBase)) + Expect(err).To(BeNil()) + + err = vec.DeleteInstance(ctx, vec) + Expect(err).To(BeNil()) + }) + + It("resize appends the given value", func() { + vec, err := generated.Emval_test_return_vector(engine, ctx) + Expect(err).To(BeNil()) + + _, err = vec.CallInstanceMethod(ctx, vec, "resize", uint32(5), int32(42)) + Expect(err).To(BeNil()) + + size, err := vec.CallInstanceMethod(ctx, vec, "size") + Expect(err).To(BeNil()) + Expect(size).To(Equal(uint32(5))) + + get0, err := vec.CallInstanceMethod(ctx, vec, "get", uint32(0)) + Expect(err).To(BeNil()) + Expect(get0).To(Equal(int32(10))) + + get1, err := vec.CallInstanceMethod(ctx, vec, "get", uint32(1)) + Expect(err).To(BeNil()) + Expect(get1).To(Equal(int32(20))) + + get2, err := vec.CallInstanceMethod(ctx, vec, "get", uint32(2)) + Expect(err).To(BeNil()) + Expect(get2).To(Equal(int32(30))) + + get3, err := vec.CallInstanceMethod(ctx, vec, "get", uint32(3)) + Expect(err).To(BeNil()) + Expect(get3).To(Equal(int32(42))) + + get4, err := vec.CallInstanceMethod(ctx, vec, "get", uint32(4)) + Expect(err).To(BeNil()) + Expect(get4).To(Equal(int32(42))) + + err = vec.DeleteInstance(ctx, vec) + Expect(err).To(BeNil()) + }) + + It("resize preserves content when shrinking", func() { + vec, err := generated.Emval_test_return_vector(engine, ctx) + Expect(err).To(BeNil()) + + _, err = vec.CallInstanceMethod(ctx, vec, "resize", uint32(2), int32(42)) + Expect(err).To(BeNil()) + + size, err := vec.CallInstanceMethod(ctx, vec, "size") + Expect(err).To(BeNil()) + Expect(size).To(Equal(uint32(2))) + + get0, err := vec.CallInstanceMethod(ctx, vec, "get", uint32(0)) + Expect(err).To(BeNil()) + Expect(get0).To(Equal(int32(10))) + + get1, err := vec.CallInstanceMethod(ctx, vec, "get", uint32(1)) + Expect(err).To(BeNil()) + Expect(get1).To(Equal(int32(20))) + + err = vec.DeleteInstance(ctx, vec) + Expect(err).To(BeNil()) + }) + }) + + When("map", func() { + It("std::map returns as native object", func() { + newMap, err := generated.Embind_test_get_string_int_map(engine, ctx) + Expect(err).To(BeNil()) + + size, err := newMap.CallInstanceMethod(ctx, newMap, "size") + Expect(err).To(BeNil()) + Expect(size).To(Equal(uint32(2))) + + one, err := newMap.CallInstanceMethod(ctx, newMap, "get", "one") + Expect(err).To(BeNil()) + Expect(one).To(Equal(int32(1))) + + two, err := newMap.CallInstanceMethod(ctx, newMap, "get", "two") + Expect(err).To(BeNil()) + Expect(two).To(Equal(int32(2))) + + err = newMap.DeleteInstance(ctx, newMap) + Expect(err).To(BeNil()) + }) + + It("std::map can get keys", func() { + newMap, err := generated.Embind_test_get_string_int_map(engine, ctx) + Expect(err).To(BeNil()) + + size, err := newMap.CallInstanceMethod(ctx, newMap, "size") + Expect(err).To(BeNil()) + + keys, err := newMap.CallInstanceMethod(ctx, newMap, "keys") + Expect(err).To(BeNil()) + + keysClass := keys.(embind.IClassBase) + + keysSize, err := keysClass.CallInstanceMethod(ctx, keysClass, "size") + Expect(err).To(BeNil()) + + Expect(keysSize).To(Equal(size.(uint32))) + + one, err := keysClass.CallInstanceMethod(ctx, keysClass, "get", uint32(0)) + Expect(err).To(BeNil()) + Expect(one).To(Equal("one")) + + two, err := keysClass.CallInstanceMethod(ctx, keysClass, "get", uint32(1)) + Expect(err).To(BeNil()) + Expect(two).To(Equal("two")) + + err = keysClass.DeleteInstance(ctx, keysClass) + + err = newMap.DeleteInstance(ctx, newMap) + Expect(err).To(BeNil()) + }) + + It("std::map can set keys and values", func() { + newMap, err := generated.Embind_test_get_string_int_map(engine, ctx) + + size, err := newMap.CallInstanceMethod(ctx, newMap, "size") + Expect(err).To(BeNil()) + Expect(size).To(Equal(uint32(2))) + + _, err = newMap.CallInstanceMethod(ctx, newMap, "set", "three", int32(3)) + Expect(err).To(BeNil()) + + size, err = newMap.CallInstanceMethod(ctx, newMap, "size") + Expect(err).To(BeNil()) + Expect(size).To(Equal(uint32(3))) + + three, err := newMap.CallInstanceMethod(ctx, newMap, "get", "three") + Expect(err).To(BeNil()) + Expect(three).To(Equal(int32(3))) + + _, err = newMap.CallInstanceMethod(ctx, newMap, "set", "three", int32(4)) + Expect(err).To(BeNil()) + + size, err = newMap.CallInstanceMethod(ctx, newMap, "size") + Expect(err).To(BeNil()) + Expect(size).To(Equal(uint32(3))) + + three, err = newMap.CallInstanceMethod(ctx, newMap, "get", "three") + Expect(err).To(BeNil()) + Expect(three).To(Equal(int32(4))) + + err = newMap.DeleteInstance(ctx, newMap) + Expect(err).To(BeNil()) + }) + }) + + When("functors", func() { + It("can get and call function ptrs", func() { + ptr, err := generated.Emval_test_get_function_ptr(engine, ctx) + Expect(err).To(BeNil()) + + opcall, err := ptr.CallInstanceMethod(ctx, ptr, "opcall", "foobar") + Expect(err).To(BeNil()) + Expect(opcall).To(Equal("foobar")) + + err = ptr.DeleteInstance(ctx, ptr) + Expect(err).To(BeNil()) + }) + + It("can pass functor to C++", func() { + ptr, err := generated.Emval_test_get_function_ptr(engine, ctx) + Expect(err).To(BeNil()) + + takeAndCallResult, err := generated.Emval_test_take_and_call_functor(engine, ctx, ptr) + Expect(err).To(BeNil()) + Expect(takeAndCallResult).To(Equal("asdf")) + + err = ptr.DeleteInstance(ctx, ptr) + Expect(err).To(BeNil()) + }) + + It("can clone handles", func() { + a, err := generated.Emval_test_get_function_ptr(engine, ctx) + Expect(err).To(BeNil()) + + b, err := a.CloneInstance(ctx, a) + Expect(err).To(BeNil()) + + err = a.DeleteInstance(ctx, a) + Expect(err).To(BeNil()) + + err = a.DeleteInstance(ctx, a) + Expect(err).To(Not(BeNil())) + Expect(err.Error()).To(ContainSubstring("class handle already deleted")) + + err = b.DeleteInstance(ctx, b) + Expect(err).To(BeNil()) + }) + }) + + When("classes", func() { + It("class instance", func() { + a := map[string]any{"foo": "bar"} + + countEmvalHandles := engine.CountEmvalHandles() + Expect(countEmvalHandles).To(Equal(0)) + + c, err := generated.NewClassValHolder(engine, ctx, a) + Expect(err).To(BeNil()) + + countEmvalHandles = engine.CountEmvalHandles() + Expect(countEmvalHandles).To(Equal(1)) + + getVal, err := c.GetVal(ctx) + Expect(err).To(BeNil()) + Expect(getVal).To(HaveKeyWithValue("foo", "bar")) + + countEmvalHandles = engine.CountEmvalHandles() + Expect(countEmvalHandles).To(Equal(1)) + + err = c.SetVal(ctx, "1234") + Expect(err).To(BeNil()) + + getVal, err = c.GetVal(ctx) + Expect(err).To(BeNil()) + Expect(getVal).To(Equal("1234")) + + err = c.Delete(ctx) + Expect(err).To(BeNil()) + + countEmvalHandles = engine.CountEmvalHandles() + Expect(countEmvalHandles).To(Equal(0)) + }) + + It("class properties can be methods", func() { + a := map[string]any{} + b := map[string]any{"foo": "foo"} + c, err := generated.NewClassValHolder(engine, ctx, a) + Expect(err).To(BeNil()) + + val, err := c.GetPropertyVal(ctx) + Expect(err).To(BeNil()) + Expect(val).To(Equal(a)) + + err = c.SetPropertyVal(ctx, b) + Expect(err).To(BeNil()) + + val, err = c.GetPropertyVal(ctx) + Expect(err).To(BeNil()) + Expect(val).To(Equal(b)) + + err = c.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("class properties can be std::function objects", func() { + a := map[string]any{} + b := map[string]any{"foo": "foo"} + c, err := generated.NewClassValHolder(engine, ctx, a) + Expect(err).To(BeNil()) + + val, err := c.GetPropertyFunction_val(ctx) + Expect(err).To(BeNil()) + Expect(val).To(Equal(a)) + + err = c.SetPropertyFunction_val(ctx, b) + Expect(err).To(BeNil()) + + val, err = c.GetPropertyFunction_val(ctx) + Expect(err).To(BeNil()) + Expect(val).To(Equal(b)) + + err = c.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("class properties can be read-only std::function objects", func() { + a := map[string]any{} + + h, err := generated.NewClassValHolder(engine, ctx, a) + Expect(err).To(BeNil()) + + funcVal, err := h.GetPropertyReadonly_function_val(ctx) + Expect(err).To(BeNil()) + Expect(funcVal).To(Equal(a)) + + err = h.SetProperty(ctx, "readonly_function_val", 10) + Expect(err).To(Not(BeNil())) + Expect(err.Error()).To(ContainSubstring("ValHolder.readonly_function_val is a read-only property")) + + err = h.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("class properties can be function objects (functor)", func() { + a := map[string]any{} + b := map[string]any{"foo": "foo"} + c, err := generated.NewClassValHolder(engine, ctx, a) + Expect(err).To(BeNil()) + + functor_val, err := c.GetPropertyFunctor_val(ctx) + Expect(err).To(BeNil()) + Expect(functor_val).To(Equal(a)) + + err = c.SetPropertyFunction_val(ctx, b) + Expect(err).To(BeNil()) + + functor_val, err = c.GetPropertyFunctor_val(ctx) + Expect(err).To(BeNil()) + Expect(functor_val).To(Equal(b)) + + err = c.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("class properties can be read-only function objects (functor)", func() { + a := map[string]any{} + h, err := generated.NewClassValHolder(engine, ctx, a) + Expect(err).To(BeNil()) + + readonly_functor_val, err := h.GetPropertyReadonly_functor_val(ctx) + Expect(err).To(BeNil()) + Expect(readonly_functor_val).To(Equal(a)) + + err = h.SetProperty(ctx, "readonly_functor_val", 10) + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("ValHolder.readonly_functor_val is a read-only property")) + + err = h.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("class properties can be read-only", func() { + a := map[string]any{} + h, err := generated.NewClassValHolder(engine, ctx, a) + Expect(err).To(BeNil()) + + val_readonly, err := h.GetPropertyVal_readonly(ctx) + Expect(err).To(BeNil()) + Expect(val_readonly).To(Equal(a)) + + err = h.SetProperty(ctx, "val_readonly", 10) + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("ValHolder.val_readonly is a read-only property")) + + err = h.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("read-only member field", func() { + a, err := generated.NewClassHasReadOnlyProperty(engine, ctx, 10) + + i, err := a.GetPropertyI(ctx) + Expect(i).To(Equal(int32(10))) + + err = a.SetProperty(ctx, "i", 20) + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("HasReadOnlyProperty.i is a read-only property")) + + err = a.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("class instance $$ property is non-enumerable", func() { + c, err := generated.NewClassValHolder(engine, ctx, types.Undefined) + Expect(err).To(BeNil()) + + //assert.deepEqual([], Object.keys(c)); + + d, err := c.Clone(ctx) + Expect(err).To(BeNil()) + + err = c.Delete(ctx) + Expect(err).To(BeNil()) + + //assert.deepEqual([], Object.keys(d)); + + err = d.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("class methods", func() { + someClassMethod, err := generated.ClassValHolderStaticSome_class_method(engine, ctx, 10) + Expect(err).To(BeNil()) + Expect(someClassMethod).To(Equal(int32(10))) + + b, err := generated.ClassValHolderStaticMakeValHolder(engine, ctx, "foo") + Expect(err).To(BeNil()) + + getVal, err := b.CallInstanceMethod(ctx, b, "getVal") + Expect(err).To(BeNil()) + Expect(getVal).To(Equal("foo")) + + err = b.DeleteInstance(ctx, b) + Expect(err).To(BeNil()) + }) + + It("function objects as class constructors", func() { + a, err := generated.NewClassConstructFromStdFunction(engine, ctx, "foo", 10) + Expect(err).To(BeNil()) + + getVal, err := a.GetVal(ctx) + Expect(err).To(BeNil()) + Expect(getVal).To(Equal("foo")) + + getA, err := a.GetA(ctx) + Expect(err).To(BeNil()) + Expect(getA).To(Equal(int32(10))) + + b, err := generated.NewClassConstructFromFunctionObject(engine, ctx, "bar", 12) + Expect(err).To(BeNil()) + + getVal, err = b.GetVal(ctx) + Expect(err).To(BeNil()) + Expect(getVal).To(Equal("bar")) + + getA, err = b.GetA(ctx) + Expect(err).To(BeNil()) + Expect(getA).To(Equal(int32(12))) + + err = a.Delete(ctx) + Expect(err).To(BeNil()) + + err = b.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("function objects as class methods", func() { + b, err := generated.ClassValHolderStaticMakeValHolder(engine, ctx, "foo") + Expect(err).To(BeNil()) + + // get & set via std::function + getValFunction, err := b.CallInstanceMethod(ctx, b, "getValFunction") + Expect(err).To(BeNil()) + Expect(getValFunction).To(Equal("foo")) + + _, err = b.CallInstanceMethod(ctx, b, "setValFunction", "bar") + Expect(err).To(BeNil()) + + // get & set via 'callable' + getValFunctor, err := b.CallInstanceMethod(ctx, b, "getValFunctor") + Expect(err).To(BeNil()) + Expect(getValFunctor).To(Equal("bar")) + + _, err = b.CallInstanceMethod(ctx, b, "setValFunctor", "baz") + Expect(err).To(BeNil()) + + getValFunction, err = b.CallInstanceMethod(ctx, b, "getValFunction") + Expect(err).To(BeNil()) + Expect(getValFunction).To(Equal("baz")) + + err = b.DeleteInstance(ctx, b) + Expect(err).To(BeNil()) + }) + + It("can't call methods on deleted class instances", func() { + c, err := generated.NewClassValHolder(engine, ctx, types.Undefined) + Expect(err).To(BeNil()) + + err = c.Delete(ctx) + Expect(err).To(BeNil()) + + _, err = c.GetVal(ctx) + Expect(err).To(Not(BeNil())) + Expect(err.Error()).To(ContainSubstring("cannot pass deleted object as a pointer of type ValHolder const*")) + + err = c.Delete(ctx) + Expect(err).To(Not(BeNil())) + Expect(err.Error()).To(ContainSubstring("class handle already deleted")) + }) + + It("can return class instances by value", func() { + c, err := generated.Emval_test_return_ValHolder(engine, ctx) + Expect(err).To(BeNil()) + + getVal, err := c.CallInstanceMethod(ctx, c, "getVal") + Expect(err).To(BeNil()) + Expect(getVal).To(Equal(map[string]any{})) + + err = c.DeleteInstance(ctx, c) + Expect(err).To(BeNil()) + }) + + It("can pass class instances to functions by reference", func() { + a := map[string]any{"a": 1} + c, err := generated.NewClassValHolder(engine, ctx, a) + err = generated.Emval_test_set_ValHolder_to_empty_object(engine, ctx, c) + getVal, err := c.CallInstanceMethod(ctx, c, "getVal") + Expect(err).To(BeNil()) + Expect(getVal).To(Equal(map[string]any{})) + + err = c.DeleteInstance(ctx, c) + Expect(err).To(BeNil()) + }) + + It("can pass smart pointer by reference", func() { + base, err := generated.Embind_test_return_smart_base_ptr(engine, ctx) + Expect(err).To(BeNil()) + + name, err := generated.Embind_test_get_class_name_via_reference_to_smart_base_ptr(engine, ctx, base) + Expect(err).To(BeNil()) + Expect(name).To(Equal("Base")) + + err = base.DeleteInstance(ctx, base) + Expect(err).To(BeNil()) + }) + + It("can pass smart pointer by value", func() { + base, err := generated.Embind_test_return_smart_base_ptr(engine, ctx) + Expect(err).To(BeNil()) + + name, err := generated.Embind_test_get_class_name_via_smart_base_ptr(engine, ctx, base) + Expect(err).To(BeNil()) + Expect(name).To(Equal("Base")) + + err = base.DeleteInstance(ctx, base) + Expect(err).To(BeNil()) + }) + + // todo: fix this (comment from Emscripten + // This test does not work because we make no provision for argument values + // having been changed after returning from a C++ routine invocation. In + // this specific case, the original pointee of the smart pointer was + // freed and replaced by a new one, but the ptr in our local handle + // was never updated after returning from the call. + It("can modify smart pointers passed by reference", func() { + // var base = cm.embind_test_return_smart_base_ptr(); + // cm.embind_modify_smart_pointer_passed_by_reference(base); + // assert.equal("Changed", base.getClassName()); + // base.delete(); + }) + + It("can not modify smart pointers passed by value", func() { + base, err := generated.Embind_test_return_smart_base_ptr(engine, ctx) + Expect(err).To(BeNil()) + + err = generated.Embind_attempt_to_modify_smart_pointer_when_passed_by_value(engine, ctx, base) + Expect(err).To(BeNil()) + + className, err := base.CallInstanceMethod(ctx, base, "getClassName") + Expect(err).To(BeNil()) + Expect(className).To(Equal("Base")) + + err = base.DeleteInstance(ctx, base) + Expect(err).To(BeNil()) + }) + + It("const return value", func() { + c, err := generated.NewClassValHolder(engine, ctx, "foo") + Expect(err).To(BeNil()) + + constRef, err := c.GetConstVal(ctx) + Expect(err).To(BeNil()) + Expect(constRef).To(Equal("foo")) + + err = c.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("return object by const ref", func() { + c, err := generated.NewClassValHolder(engine, ctx, "foo") + Expect(err).To(BeNil()) + + constRef, err := c.GetValConstRef(ctx) + Expect(err).To(BeNil()) + Expect(constRef).To(Equal("foo")) + + err = c.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("instanceof", func() { + c, err := generated.NewClassValHolder(engine, ctx, "foo") + Expect(err).To(BeNil()) + + err = c.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("can access struct fields", func() { + c, err := generated.NewClassCustomStruct(engine, ctx) + Expect(err).To(BeNil()) + + field, err := c.GetPropertyField(ctx) + Expect(err).To(BeNil()) + Expect(field).To(Equal(int32(10))) + + field, err = c.GetField(ctx) + Expect(err).To(BeNil()) + Expect(field).To(Equal(int32(10))) + + err = c.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("can set struct fields", func() { + c, err := generated.NewClassCustomStruct(engine, ctx) + Expect(err).To(BeNil()) + + err = c.SetPropertyField(ctx, 15) + Expect(err).To(BeNil()) + + field, err := c.GetPropertyField(ctx) + Expect(err).To(BeNil()) + Expect(field).To(Equal(int32(15))) + + err = c.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("can return tuples by value", func() { + c, err := generated.Emval_test_return_TupleVector(engine, ctx) + Expect(err).To(BeNil()) + Expect(c).To(Equal([]any{float32(1), float32(2), float32(3), float32(4)})) + }) + + It("tuples can contain tuples", func() { + c, err := generated.Emval_test_return_TupleVectorTuple(engine, ctx) + Expect(err).To(BeNil()) + Expect(c).To(Equal([]any{[]any{float32(1), float32(2), float32(3), float32(4)}})) + }) + + It("can pass tuples by value", func() { + c, err := generated.Emval_test_take_and_return_TupleVector(engine, ctx, []any{float32(4), float32(5), float32(6), float32(7)}) + Expect(err).To(BeNil()) + Expect(c).To(Equal([]any{float32(4), float32(5), float32(6), float32(7)})) + }) + + It("can return structs by value", func() { + c, err := generated.Emval_test_return_StructVector(engine, ctx) + Expect(err).To(BeNil()) + Expect(c).To(Equal(map[string]any{"x": float32(1), "y": float32(2), "z": float32(3), "w": float32(4)})) + }) + + It("can pass structs by value", func() { + c, err := generated.Emval_test_take_and_return_StructVector(engine, ctx, map[string]any{"x": float32(4), "y": float32(5), "z": float32(6), "w": float32(7)}) + Expect(err).To(BeNil()) + Expect(c).To(Equal(map[string]any{"x": float32(4), "y": float32(5), "z": float32(6), "w": float32(7)})) + }) + + It("can pass and return tuples in structs", func() { + d, err := generated.Emval_test_take_and_return_TupleInStruct(engine, ctx, map[string]any{"field": []any{float32(1), float32(2), float32(3), float32(4)}}) + Expect(err).To(BeNil()) + Expect(d).To(Equal(map[string]any{"field": []any{float32(1), float32(2), float32(3), float32(4)}})) + }) + + It("can pass and return arrays in structs", func() { + d, err := generated.Emval_test_take_and_return_ArrayInStruct(engine, ctx, map[string]any{ + "field1": []any{int32(1), int32(2)}, + "field2": []any{ + map[string]any{"x": int32(1), "y": int32(2)}, + map[string]any{"x": int32(3), "y": int32(4)}, + }, + }) + Expect(err).To(BeNil()) + Expect(d).To(Equal(map[string]any{ + "field1": []any{int32(1), int32(2)}, + "field2": []any{ + map[string]any{"x": int32(1), "y": int32(2)}, + map[string]any{"x": int32(3), "y": int32(4)}, + }, + })) + }) + + It("can clone handles", func() { + a, err := generated.NewClassValHolder(engine, ctx, struct{}{}) + countHandles := engine.CountEmvalHandles() + Expect(err).To(BeNil()) + Expect(countHandles).To(Equal(1)) + + b, err := a.Clone(ctx) + Expect(err).To(BeNil()) + + err = a.DeleteInstance(ctx, a) + Expect(err).To(BeNil()) + + countHandles = engine.CountEmvalHandles() + Expect(countHandles).To(Equal(1)) + + err = a.DeleteInstance(ctx, a) + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("class handle already deleted")) + + err = b.DeleteInstance(ctx, b) + Expect(err).To(BeNil()) + + countHandles = engine.CountEmvalHandles() + Expect(countHandles).To(Equal(0)) + }) + + It("A shared pointer set/get point to the same underlying pointer", func() { + a, err := generated.NewClassSharedPtrHolder(engine, ctx) + Expect(err).To(BeNil()) + + b, err := a.Get(ctx) + Expect(err).To(BeNil()) + + err = a.Set(ctx, b) + Expect(err).To(BeNil()) + + c, err := a.Get(ctx) + Expect(err).To(BeNil()) + + isAliasOf, err := b.IsAliasOfInstance(ctx, b, c) + Expect(err).To(BeNil()) + Expect(isAliasOf).To(BeTrue()) + + err = b.DeleteInstance(ctx, b) + Expect(err).To(BeNil()) + + err = c.DeleteInstance(ctx, c) + Expect(err).To(BeNil()) + + err = a.DeleteInstance(ctx, a) + Expect(err).To(BeNil()) + }) + + It("can return shared ptrs from instance methods", func() { + a, err := generated.NewClassSharedPtrHolder(engine, ctx) + Expect(err).To(BeNil()) + + b, err := a.Get(ctx) + Expect(err).To(BeNil()) + + get, err := b.CallInstanceMethod(ctx, b, "get") + Expect(get).To(Equal("a string")) + + err = b.DeleteInstance(ctx, b) + Expect(err).To(BeNil()) + + err = a.DeleteInstance(ctx, a) + Expect(err).To(BeNil()) + }) + + It("smart ptrs clone correctly", func() { + countHandles := engine.CountEmvalHandles() + Expect(countHandles).To(Equal(0)) + + a, err := generated.Emval_test_return_shared_ptr(engine, ctx) + Expect(err).To(BeNil()) + + b, err := a.CloneInstance(ctx, a) + Expect(err).To(BeNil()) + + err = a.DeleteInstance(ctx, a) + Expect(err).To(BeNil()) + + countHandles = engine.CountEmvalHandles() + Expect(countHandles).To(Equal(1)) + + err = a.DeleteInstance(ctx, a) + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("as")) + + err = b.DeleteInstance(ctx, b) + Expect(err).To(BeNil()) + + countHandles = engine.CountEmvalHandles() + Expect(countHandles).To(Equal(0)) + }) + + It("can't clone if already deleted", func() { + a, err := generated.NewClassValHolder(engine, ctx, struct{}{}) + Expect(err).To(BeNil()) + + err = a.Delete(ctx) + Expect(err).To(BeNil()) + + _, err = a.Clone(ctx) + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("class handle already deleted")) + }) + + It("virtual calls work correctly", func() { + derived, err := generated.Embind_test_return_raw_polymorphic_derived_ptr_as_base(engine, ctx) + Expect(err).To(BeNil()) + + virtualClassName, err := derived.CallInstanceMethod(ctx, derived, "virtualGetClassName") + Expect(err).To(BeNil()) + Expect(virtualClassName).To(Equal("PolyDerived")) + + err = derived.DeleteInstance(ctx, derived) + Expect(err).To(BeNil()) + }) + + It("virtual calls work correctly on smart ptrs", func() { + derived, err := generated.Embind_test_return_smart_polymorphic_derived_ptr_as_base(engine, ctx) + Expect(err).To(BeNil()) + + virtualClassName, err := derived.CallInstanceMethod(ctx, derived, "virtualGetClassName") + Expect(err).To(BeNil()) + Expect(virtualClassName).To(Equal("PolyDerived")) + + err = derived.DeleteInstance(ctx, derived) + Expect(err).To(BeNil()) + }) + + It("Empty smart ptr is null", func() { + a, err := generated.Emval_test_return_empty_shared_ptr(engine, ctx) + Expect(err).To(BeNil()) + Expect(a).To(BeNil()) + }) + + It("string cannot be given as smart pointer argument", func() { + _, err := engine.CallPublicSymbol(ctx, "emval_test_is_shared_ptr_null", "hello world") + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("check whether you constructed it properly through embind, the given value is a string")) + }) + + It("number cannot be given as smart pointer argument", func() { + _, err := engine.CallPublicSymbol(ctx, "emval_test_is_shared_ptr_null", 105) + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("check whether you constructed it properly through embind, the given value is a int")) + }) + + It("raw pointer cannot be given as smart pointer argument", func() { + p, err := generated.NewClassValHolder(engine, ctx, struct{}{}) + Expect(err).To(BeNil()) + + _, err = generated.Emval_test_is_shared_ptr_null(engine, ctx, p) + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("passing raw pointer to smart pointer is illegal")) + + err = p.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("null is passed as empty smart pointer", func() { + isNull, err := generated.Emval_test_is_shared_ptr_null(engine, ctx, nil) + Expect(err).To(BeNil()) + Expect(isNull).To(BeTrue()) + }) + + It("Deleting already deleted smart ptrs fails", func() { + a, err := generated.Emval_test_return_shared_ptr(engine, ctx) + Expect(err).To(BeNil()) + + err = a.DeleteInstance(ctx, a) + Expect(err).To(BeNil()) + + err = a.DeleteInstance(ctx, a) + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("class handle already deleted")) + }) + + It("returned unique_ptr does not call destructor", func() { + logged := "" + + c, err := generated.Emval_test_return_unique_ptr_lifetime(engine, ctx, func(s string) { logged += s }) + Expect(err).To(BeNil()) + Expect(logged).To(Equal("(constructor)")) + + err = c.DeleteInstance(ctx, c) + Expect(err).To(BeNil()) + }) + + It("returned unique_ptr calls destructor on delete", func() { + logged := "" + + c, err := generated.Emval_test_return_unique_ptr_lifetime(engine, ctx, func(s string) { logged += s }) + Expect(err).To(BeNil()) + + logged = "" + + err = c.DeleteInstance(ctx, c) + Expect(err).To(BeNil()) + + Expect(logged).To(Equal("(destructor)")) + }) + + It("StringHolder", func() { + a, err := generated.NewClassStringHolder(engine, ctx, "foobar") + Expect(err).To(BeNil()) + + str, err := a.Get(ctx) + Expect(err).To(BeNil()) + Expect(str).To(Equal("foobar")) + + err = a.Set(ctx, "barfoo") + + str, err = a.Get(ctx) + Expect(err).To(BeNil()) + Expect(str).To(Equal("barfoo")) + + constRef, err := a.Get_const_ref(ctx) + Expect(err).To(BeNil()) + Expect(constRef).To(Equal("barfoo")) + + err = a.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("can call methods on unique ptr", func() { + result, err := generated.Emval_test_return_unique_ptr(engine, ctx) + Expect(err).To(BeNil()) + + _, err = result.CallInstanceMethod(ctx, result, "setVal", "1234") + Expect(err).To(BeNil()) + + getVal, err := result.CallInstanceMethod(ctx, result, "getVal") + Expect(err).To(BeNil()) + Expect(getVal).To(Equal("1234")) + + err = result.DeleteInstance(ctx, result) + Expect(err).To(BeNil()) + }) + + It("can call methods on shared ptr", func() { + result, err := generated.Emval_test_return_shared_ptr(engine, ctx) + Expect(err).To(BeNil()) + + _, err = result.CallInstanceMethod(ctx, result, "setVal", "1234") + Expect(err).To(BeNil()) + + getVal, err := result.CallInstanceMethod(ctx, result, "getVal") + Expect(err).To(BeNil()) + Expect(getVal).To(Equal("1234")) + + err = result.DeleteInstance(ctx, result) + Expect(err).To(BeNil()) + }) + + It("non-member methods", func() { + a := map[string]any{"foo": "bar"} + c, err := generated.NewClassValHolder(engine, ctx, a) + Expect(err).To(BeNil()) + + err = c.SetEmpty(ctx) + Expect(err).To(BeNil()) + + valNonMember, err := c.GetValNonMember(ctx) + Expect(err).To(BeNil()) + Expect(valNonMember).To(Equal(map[string]any{})) + + err = c.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("instantiating class without constructor gives error", func() { + _, err := generated.AbstractClass(engine, ctx) + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring("AbstractClass has no accessible constructor")) + }) + + It("can construct class with external constructor", func() { + e, err := generated.NewClassHasExternalConstructor(engine, ctx, "foo") + Expect(err).To(BeNil()) + + str, err := e.GetString(ctx) + Expect(err).To(BeNil()) + Expect(str).To(Equal("foo")) + + err = e.Delete(ctx) + Expect(err).To(BeNil()) + }) + }) + + When("const", func() { + It("calling non-const method with const handle is error", func() { + vh, err := generated.ClassValHolderStaticMakeConst(engine, ctx, struct{}{}) + Expect(err).To(BeNil()) + + _, err = vh.CallInstanceMethod(ctx, vh, "setVal", struct{}{}) + Expect(err).To(Not(BeNil())) + Expect(err.Error()).To(ContainSubstring("cannot convert argument of type ValHolder const* to parameter type ValHolder*")) + + err = vh.DeleteInstance(ctx, vh) + Expect(err).To(BeNil()) + }) + + It("passing const pointer to non-const pointer is error", func() { + vh, err := generated.ClassValHolderStaticMakeConst(engine, ctx, struct{}{}) + + err = generated.ClassValHolderStaticSet_via_raw_pointer(engine, ctx, vh, struct{}{}) + Expect(err).To(Not(BeNil())) + + Expect(err.Error()).To(ContainSubstring("cannot convert argument of type ValHolder const* to parameter type ValHolder*")) + + err = vh.DeleteInstance(ctx, vh) + Expect(err).To(BeNil()) + }) + }) + + When("smart pointers", func() { + It("constructor can return smart pointer", func() { + e, err := generated.NewClassHeldBySmartPtr(engine, ctx, 10, "foo") + Expect(err).To(BeNil()) + + i, err := e.GetPropertyI(ctx) + Expect(err).To(BeNil()) + Expect(i).To(Equal(int32(10))) + + s, err := e.GetPropertyS(ctx) + Expect(err).To(BeNil()) + Expect(s).To(Equal("foo")) + + f, err := generated.TakesHeldBySmartPtr(engine, ctx, e) + Expect(err).To(BeNil()) + + err = f.DeleteInstance(ctx, f) + Expect(err).To(BeNil()) + + err = e.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("cannot pass incorrect smart pointer type", func() { + e, err := generated.Emval_test_return_shared_ptr(engine, ctx) + Expect(err).To(BeNil()) + + _, err = generated.TakesHeldBySmartPtr(engine, ctx, e) + Expect(err).To(Not(BeNil())) + Expect(err.Error()).To(ContainSubstring("expected null or instance of HeldBySmartPtr, got an instance of ValHolder")) + + err = e.DeleteInstance(ctx, e) + Expect(err).To(BeNil()) + }) + + It("constructor can return smart pointer", func() { + e, err := generated.NewClassHeldBySmartPtr(engine, ctx, 10, "foo") + Expect(err).To(BeNil()) + + i, err := e.GetPropertyI(ctx) + Expect(err).To(BeNil()) + Expect(i).To(Equal(int32(10))) + + s, err := e.GetPropertyS(ctx) + Expect(err).To(BeNil()) + Expect(s).To(Equal("foo")) + + f, err := generated.TakesHeldBySmartPtr(engine, ctx, e) + + err = f.DeleteInstance(ctx, f) + Expect(err).To(BeNil()) + + err = e.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("custom smart pointer", func() { + // @todo: fix me. + /* + e, err := generated.NewClassHeldByCustomSmartPtr(engine, ctx, 20, "bar") + Expect(err).To(BeNil()) + + i, err := e.GetPropertyI(ctx) + Expect(err).To(BeNil()) + Expect(i).To(Equal(int32(20))) + + s, err := e.GetPropertyS(ctx) + Expect(err).To(BeNil()) + Expect(s).To(Equal("bar")) + + err = e.Delete(ctx) + Expect(err).To(BeNil()) + */ + }) + + It("custom smart pointer passed through wiretype", func() { + // @todo: fix me. + /* + e, err := generated.NewClassHeldByCustomSmartPtr(engine, ctx, 20, "bar") + Expect(err).To(BeNil()) + + f, err := generated.PassThroughCustomSmartPtr(engine, ctx, e) + Expect(err).To(BeNil()) + + err = e.Delete(ctx) + Expect(err).To(BeNil()) + + i, err := f.GetInstanceProperty(ctx, f, "i") + Expect(err).To(BeNil()) + Expect(i).To(Equal(int32(20))) + + s, err := f.GetInstanceProperty(ctx, f, "s") + Expect(err).To(BeNil()) + Expect(s).To(Equal("bar")) + + err = f.DeleteInstance(ctx, f) + Expect(err).To(BeNil())*/ + }) + + It("cannot give null to by-value argument", func() { + e, err := generated.TakesHeldBySmartPtr(engine, ctx, nil) + Expect(err).To(Not(BeNil())) + Expect(err.Error()).To(ContainSubstring("nil is not a valid HeldBySmartPtr")) + Expect(e).To(BeNil()) + }) + + It("raw pointer can take and give null", func() { + e, err := generated.PassThroughRawPtr(engine, ctx, nil) + Expect(err).To(BeNil()) + Expect(e).To(BeNil()) + }) + + It("custom smart pointer can take and give null", func() { + // @todo: fix me + /* + e, err := generated.PassThroughCustomSmartPtr(engine, ctx, nil) + Expect(err).To(BeNil()) + Expect(e).To(BeNil()) + */ + }) + + It("cannot pass shared_ptr to CustomSmartPtr", func() { + o, err := generated.ClassHeldByCustomSmartPtrStaticCreateSharedPtr(engine, ctx, 10, "foo") + Expect(err).To(BeNil()) + + e, err := generated.PassThroughCustomSmartPtr(engine, ctx, o) + Expect(err).To(Not(BeNil())) + Expect(err.Error()).To(ContainSubstring("cannot convert argument of type shared_ptr to parameter type CustomSmartPtr")) + Expect(e).To(BeNil()) + + err = o.DeleteInstance(ctx, o) + Expect(err).To(BeNil()) + }) + + It("custom smart pointers can be passed to shared_ptr parameter", func() { + // @todo: fix me + /* + e, err := generated.ClassHeldBySmartPtrStaticNewCustomPtr(engine, ctx, 10, "abc") + Expect(err).To(BeNil()) + + i, err := e.GetInstanceProperty(ctx, e, "i") + Expect(err).To(BeNil()) + Expect(i, 10) + + s, err := e.GetInstanceProperty(ctx, e, "s") + Expect(err).To(BeNil()) + Expect(s, "abc") + + tmp, err := generated.TakesHeldBySmartPtrSharedPtr(engine, ctx, e) + Expect(err).To(BeNil()) + + err = tmp.DeleteInstance(ctx, tmp) + Expect(err).To(BeNil()) + + err = e.DeleteInstance(ctx, e) + Expect(err).To(BeNil()) + */ + }) + + It("can call non-member functions as methods", func() { + e, err := generated.NewClassHeldBySmartPtr(engine, ctx, 20, "bar") + Expect(err).To(BeNil()) + + f, err := e.ReturnThis(ctx) + Expect(err).To(BeNil()) + + err = e.Delete(ctx) + Expect(err).To(BeNil()) + + i, err := f.GetInstanceProperty(ctx, f, "i") + Expect(err).To(BeNil()) + Expect(i, 10) + + s, err := f.GetInstanceProperty(ctx, f, "s") + Expect(err).To(BeNil()) + Expect(s, "abc") + + err = f.DeleteInstance(ctx, f) + Expect(err).To(BeNil()) + }) + }) + + When("enumerations", func() { + It("can pass and return enumeration values to functions", func() { + tar, err := generated.Emval_test_take_and_return_Enum(engine, ctx, generated.EnumEnum_TWO) + Expect(err).To(BeNil()) + Expect(tar).To(Equal(generated.EnumEnum_TWO)) + }) + }) + + When("C++11 enum class", func() { + It("can pass and return enumeration values to functions", func() { + tar, err := generated.Emval_test_take_and_return_EnumClass(engine, ctx, generated.EnumEnumClass_TWO) + Expect(err).To(BeNil()) + Expect(tar).To(Equal(generated.EnumEnumClass_TWO)) + }) + }) + + When("emval call tests", func() { + It("can call functions from C++", func() { + called := false + err := generated.Emval_test_call_function(engine, ctx, func(i int32, f float32, tv []any, sv map[string]any) { + called = true + + Expect(i).To(Equal(int32(10))) + Expect(f).To(Equal(float32(1.5))) + Expect(tv).To(Equal([]any{float32(1.25), float32(2.5), float32(3.75), float32(4)})) + Expect(sv).To(Equal(map[string]any{"x": float32(1.25), "y": float32(2.5), "z": float32(3.75), "w": float32(4)})) + }, 10, 1.5, []any{float32(1.25), float32(2.5), float32(3.75), float32(4)}, map[string]any{"x": float32(1.25), "y": float32(2.5), "z": float32(3.75), "w": float32(4)}) + Expect(err).To(BeNil()) + Expect(called).To(BeTrue()) + }) + }) + + When("raw pointers", func() { + It("can pass raw pointers into functions if explicitly allowed", func() { + vh, err := generated.NewClassValHolder(engine, ctx, "foo") + Expect(err).To(BeNil()) + + err = vh.StaticSet_via_raw_pointer(ctx, vh, 10) + Expect(err).To(BeNil()) + + val, err := vh.StaticGet_via_raw_pointer(ctx, vh) + Expect(err).To(BeNil()) + Expect(val).To(Equal(10)) + + err = vh.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("can return raw pointers from functions if explicitly allowed", func() { + p, err := generated.Embind_test_return_raw_base_ptr(engine, ctx) + Expect(err).To(BeNil()) + + className, err := p.CallInstanceMethod(ctx, p, "getClassName") + Expect(className).To(Equal("Base")) + + err = p.DeleteInstance(ctx, p) + Expect(err).To(BeNil()) + }) + + It("can pass multiple raw pointers to functions", func() { + target, err := generated.NewClassValHolder(engine, ctx, types.Undefined) + Expect(err).To(BeNil()) + + source, err := generated.NewClassValHolder(engine, ctx, "hi") + Expect(err).To(BeNil()) + + err = generated.ClassValHolderStaticTransfer_via_raw_pointer(engine, ctx, target, source) + Expect(err).To(BeNil()) + + val, err := target.GetVal(ctx) + Expect(err).To(BeNil()) + + Expect(val).To(Equal("hi")) + + err = target.Delete(ctx) + Expect(err).To(BeNil()) + + err = source.Delete(ctx) + Expect(err).To(BeNil()) + }) + }) + + When("implementing abstract methods with JS objects", func() { + /* + test("can call abstract methods", function() { + var obj = cm.getAbstractClass(); + assert.equal("from concrete", obj.abstractMethod()); + obj.delete(); + }); + + test("can implement abstract methods in JavaScript", function() { + var expected = "my JS string"; + function MyImplementation() { + this.rv = expected; + } + MyImplementation.prototype.abstractMethod = function() { + return this.rv; + }; + + var impl = cm.AbstractClass.implement(new MyImplementation); + assert.equal(expected, impl.abstractMethod()); + assert.equal(expected, cm.callAbstractMethod(impl)); + impl.delete(); + }); + + test("can implement optional methods in JavaScript", function() { + var expected = "my JS string"; + function MyImplementation() { + this.rv = expected; + } + MyImplementation.prototype.optionalMethod = function() { + return this.rv; + }; + + var impl = cm.AbstractClass.implement(new MyImplementation); + assert.equal(expected, cm.callOptionalMethod(impl, expected)); + impl.delete(); + }); + + test("if not implemented then optional method runs default", function() { + var impl = cm.AbstractClass.implement({}); + assert.equal("optionalfoo", impl.optionalMethod("foo")); + impl.delete(); + }); + + test("returning null shared pointer from interfaces implemented in JS code does not leak", function() { + var impl = cm.AbstractClass.implement({ + returnsSharedPtr: function() { + return null; + } + }); + cm.callReturnsSharedPtrMethod(impl); + impl.delete(); + // Let the memory leak test superfixture check that no leaks occurred. + }); + + test("returning a new shared pointer from interfaces implemented in JS code does not leak", function() { + var impl = cm.AbstractClass.implement({ + returnsSharedPtr: function() { + return cm.embind_test_return_smart_derived_ptr().deleteLater(); + } + }); + cm.callReturnsSharedPtrMethod(impl); + impl.delete(); + // Let the memory leak test superfixture check that no leaks occurred. + }); + + test("void methods work", function() { + var saved = {}; + var impl = cm.AbstractClass.implement({ + differentArguments: function(i, d, f, q, s) { + saved.i = i; + saved.d = d; + saved.f = f; + saved.q = q; + saved.s = s; + } + }); + + cm.callDifferentArguments(impl, 1, 2, 3, 4, "foo"); + + assert.deepEqual(saved, { + i: 1, + d: 2, + f: 3, + q: 4, + s: "foo", + }); + + impl.delete(); + }); + + test("returning a cached new shared pointer from interfaces implemented in JS code does not leak", function() { + var derived = cm.embind_test_return_smart_derived_ptr(); + var impl = cm.AbstractClass.implement({ + returnsSharedPtr: function() { + return derived; + } + }); + cm.callReturnsSharedPtrMethod(impl); + impl.delete(); + derived.delete(); + // Let the memory leak test superfixture check that no leaks occurred. + }); + */ + }) + + When("constructor prototype class inheritance", func() { + /* + var Empty = cm.AbstractClass.extend("Empty", { + abstractMethod: function() { + } + }); + + test("can extend, construct, and delete", function() { + var instance = new Empty; + instance.delete(); + }); + + test("properties set in constructor are externally visible", function() { + var HasProperty = cm.AbstractClass.extend("HasProperty", { + __construct: function(x) { + this.__parent.__construct.call(this); + this.property = x; + }, + abstractMethod: function() { + } + }); + var instance = new HasProperty(10); + assert.equal(10, instance.property); + instance.delete(); + }); + + test("pass derived object to c++", function() { + var Implementation = cm.AbstractClass.extend("Implementation", { + abstractMethod: function() { + return "abc"; + }, + }); + var instance = new Implementation; + var result = cm.callAbstractMethod(instance); + instance.delete(); + assert.equal("abc", result); + }); + + test("properties set in constructor are visible in overridden methods", function() { + var HasProperty = cm.AbstractClass.extend("HasProperty", { + __construct: function(x) { + this.__parent.__construct.call(this); + this.x = x; + }, + abstractMethod: function() { + return this.x; + }, + }); + var instance = new HasProperty("xyz"); + var result = cm.callAbstractMethod(instance); + instance.delete(); + assert.equal("xyz", result); + }); + + test("interface methods are externally visible", function() { + var instance = new Empty; + var result = instance.concreteMethod(); + instance.delete(); + assert.equal("concrete", result); + }); + + test("optional methods are externally visible", function() { + var instance = new Empty; + var result = instance.optionalMethod("_123"); + instance.delete(); + assert.equal("optional_123", result); + }); + + test("optional methods: not defined", function() { + var instance = new Empty; + var result = cm.callOptionalMethod(instance, "_123"); + instance.delete(); + assert.equal("optional_123", result); + }); + + // Calling C++ implementations of optional functions can be + // made to work, but requires an interface change on the C++ + // side, using a technique similar to the one described at + // https://wiki.python.org/moin/boost.python/OverridableVirtualFunctions + // + // The issue is that, in a standard binding, calling + // parent.prototype.optionalMethod invokes the wrapper + // function, which checks that the JS object implements + // 'optionalMethod', which it does. Thus, C++ calls back into + // JS, resulting in an infinite loop. + // + // The solution, for optional methods, is to bind a special + // concrete implementation that specifically calls the base + // class's implementation. See the binding of + // AbstractClass::optionalMethod in embind_test.cpp. + + test("can call parent implementation from within derived implementation", function() { + var parent = cm.AbstractClass; + var ExtendsOptionalMethod = parent.extend("ExtendsOptionalMethod", { + abstractMethod: function() { + }, + optionalMethod: function(s) { + return "optionaljs_" + parent.prototype.optionalMethod.call(this, s); + }, + }); + var instance = new ExtendsOptionalMethod; + var result = cm.callOptionalMethod(instance, "_123"); + instance.delete(); + assert.equal("optionaljs_optional_123", result); + }); + + test("instanceof", function() { + var instance = new Empty; + assert.instanceof(instance, Empty); + assert.instanceof(instance, cm.AbstractClass); + instance.delete(); + }); + + test("returning null shared pointer from interfaces implemented in JS code does not leak", function() { + var C = cm.AbstractClass.extend("C", { + abstractMethod: function() { + }, + returnsSharedPtr: function() { + return null; + } + }); + var impl = new C; + cm.callReturnsSharedPtrMethod(impl); + impl.delete(); + // Let the memory leak test superfixture check that no leaks occurred. + }); + + test("returning a new shared pointer from interfaces implemented in JS code does not leak", function() { + var C = cm.AbstractClass.extend("C", { + abstractMethod: function() { + }, + returnsSharedPtr: function() { + return cm.embind_test_return_smart_derived_ptr().deleteLater(); + } + }); + var impl = new C; + cm.callReturnsSharedPtrMethod(impl); + impl.delete(); + // Let the memory leak test superfixture check that no leaks occurred. + }); + + test("void methods work", function() { + var saved = {}; + var C = cm.AbstractClass.extend("C", { + abstractMethod: function() { + }, + differentArguments: function(i, d, f, q, s) { + saved.i = i; + saved.d = d; + saved.f = f; + saved.q = q; + saved.s = s; + } + }); + var impl = new C; + + cm.callDifferentArguments(impl, 1, 2, 3, 4, "foo"); + + assert.deepEqual(saved, { + i: 1, + d: 2, + f: 3, + q: 4, + s: "foo", + }); + + impl.delete(); + }); + + test("returning a cached new shared pointer from interfaces implemented in JS code does not leak", function() { + var derived = cm.embind_test_return_smart_derived_ptr(); + var C = cm.AbstractClass.extend("C", { + abstractMethod: function() { + }, + returnsSharedPtr: function() { + return derived; + } + }); + var impl = new C; + cm.callReturnsSharedPtrMethod(impl); + impl.delete(); + derived.delete(); + // Let the memory leak test superfixture check that no leaks occurred. + }); + + test("calling pure virtual function gives good error message", function() { + var C = cm.AbstractClass.extend("C", {}); + var error = assert.throws(cm.PureVirtualError, function() { + new C; + }); + assert.equal('Pure virtual function abstractMethod must be implemented in JavaScript', error.message); + }); + + test("can extend from C++ class with constructor arguments", function() { + var parent = cm.AbstractClassWithConstructor; + var C = parent.extend("C", { + __construct: function(x) { + this.__parent.__construct.call(this, x); + }, + abstractMethod: function() { + return this.concreteMethod(); + } + }); + + var impl = new C("hi"); + var rv = cm.callAbstractMethod2(impl); + impl.delete(); + + assert.equal("hi", rv); + }); + + test("__destruct is called when object is destroyed", function() { + var parent = cm.HeldAbstractClass; + var calls = []; + var C = parent.extend("C", { + method: function() { + }, + __destruct: function() { + calls.push("__destruct"); + this.__parent.__destruct.call(this); + } + }); + var impl = new C; + var copy = impl.clone(); + impl.delete(); + assert.deepEqual([], calls); + copy.delete(); + assert.deepEqual(["__destruct"], calls); + }); + + test("if JavaScript implementation of interface is returned, don't wrap in new handle", function() { + var parent = cm.HeldAbstractClass; + var C = parent.extend("C", { + method: function() { + } + }); + var impl = new C; + var rv = cm.passHeldAbstractClass(impl); + impl.delete(); + assert.equal(impl, rv); + rv.delete(); + }); + + test("can instantiate two wrappers with constructors", function() { + var parent = cm.HeldAbstractClass; + var C = parent.extend("C", { + __construct: function() { + this.__parent.__construct.call(this); + }, + method: function() { + } + }); + var a = new C; + var b = new C; + a.delete(); + b.delete(); + }); + + test("incorrectly calling parent is an error", function() { + var parent = cm.HeldAbstractClass; + var C = parent.extend("C", { + __construct: function() { + this.__parent.__construct(); + }, + method: function() { + } + }); + assert.throws(cm.BindingError, function() { + new C; + }); + }); + + test("deleteLater() works for JavaScript implementations", function() { + var parent = cm.HeldAbstractClass; + var C = parent.extend("C", { + method: function() { + } + }); + var impl = new C; + var rv = cm.passHeldAbstractClass(impl); + impl.deleteLater(); + rv.deleteLater(); + cm.flushPendingDeletes(); + }); + + test("deleteLater() combined with delete() works for JavaScript implementations", function() { + var parent = cm.HeldAbstractClass; + var C = parent.extend("C", { + method: function() { + } + }); + var impl = new C; + var rv = cm.passHeldAbstractClass(impl); + impl.deleteLater(); + rv.delete(); + cm.flushPendingDeletes(); + }); + + test("method arguments with pointer ownership semantics are cleaned up after call", function() { + var parent = cm.AbstractClass; + var C = parent.extend("C", { + abstractMethod: function() { + }, + }); + var impl = new C; + cm.passShared(impl); + impl.delete(); + }); + + test("method arguments with pointer ownership semantics can be cloned", function() { + var parent = cm.AbstractClass; + var owned; + var C = parent.extend("C", { + abstractMethod: function() { + }, + passShared: function(p) { + owned = p.clone(); + } + }); + var impl = new C; + cm.passShared(impl); + impl.delete(); + + assert.equal("Derived", owned.getClassName()); + owned.delete(); + }); + + test("emscripten::val method arguments don't leak", function() { + var parent = cm.AbstractClass; + var got; + var C = parent.extend("C", { + abstractMethod: function() { + }, + passVal: function(g) { + got = g; + } + }); + var impl = new C; + var v = {}; + cm.passVal(impl, v); + impl.delete(); + + assert.equal(v, got); + }); + */ + }) + + When("registration order", func() { + It("registration of tuple elements out of order leaves them in order", func() { + ot, err := generated.GetOrderedTuple(engine, ctx) + Expect(err).To(BeNil()) + + Expect(ot).To(HaveLen(2)) + Expect(ot[0]).To(BeAssignableToTypeOf(&generated.ClassFirstElement{})) + Expect(ot[1]).To(BeAssignableToTypeOf(&generated.ClassSecondElement{})) + + err = ot[0].(*generated.ClassFirstElement).Delete(ctx) + Expect(err).To(BeNil()) + + err = ot[1].(*generated.ClassSecondElement).Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("registration of struct elements out of order", func() { + ot, err := generated.GetOrderedStruct(engine, ctx) + Expect(err).To(BeNil()) + + Expect(ot).To(HaveKey("first")) + Expect(ot).To(HaveKey("second")) + + Expect(ot["first"]).To(BeAssignableToTypeOf(&generated.ClassFirstElement{})) + Expect(ot["second"]).To(BeAssignableToTypeOf(&generated.ClassSecondElement{})) + + err = ot["first"].(*generated.ClassFirstElement).Delete(ctx) + Expect(err).To(BeNil()) + + err = ot["second"].(*generated.ClassSecondElement).Delete(ctx) + Expect(err).To(BeNil()) + }) + }) + + When("unbound types", func() { + if !generated.Constant_hasUnboundTypeNames { + return + } + + assertMessage := func(fn func() (any, error), message string) { + _, err := fn() + Expect(err).ToNot(BeNil()) + Expect(err.Error()).To(ContainSubstring(message)) + } + + It("calling function with unbound types produces error", func() { + assertMessage( + func() (any, error) { + return generated.GetUnboundClass(engine, ctx, 1) + }, + "getUnboundClass due to unbound types: 12UnboundClass") + }) + + It("unbound base class produces error", func() { + assertMessage( + func() (any, error) { + return generated.GetHasUnboundBase(engine, ctx, 1) + }, + "getHasUnboundBase due to unbound types: 12UnboundClass") + }) + + It("construct of class with unbound base", func() { + assertMessage( + func() (any, error) { + return generated.HasUnboundBase(engine, ctx) + }, "HasUnboundBase due to unbound types: 12UnboundClass") + }) + + It("unbound constructor argument", func() { + assertMessage( + func() (any, error) { + return generated.NewClassHasConstructorUsingUnboundArgument(engine, ctx, 1) + }, + "HasConstructorUsingUnboundArgument due to unbound types: 12UnboundClass") + }) + + It("unbound constructor argument of class with unbound base", func() { + assertMessage( + func() (any, error) { + return generated.HasConstructorUsingUnboundArgumentAndUnboundBase(engine, ctx) + }, + "HasConstructorUsingUnboundArgumentAndUnboundBase due to unbound types: 18SecondUnboundClass") + }) + + It("class function with unbound argument", func() { + x, err := generated.NewClassBoundClass(engine, ctx) + Expect(err).To(BeNil()) + + assertMessage( + func() (any, error) { + return x.Method(ctx, 0) + }, "Cannot call BoundClass.method due to unbound types: 12UnboundClass") + err = x.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("class class function with unbound argument", func() { + assertMessage( + func() (any, error) { + return generated.ClassBoundClassStaticClassfunction(engine, ctx, 0) + }, "Cannot call BoundClass.classfunction due to unbound types: 12UnboundClass") + }) + + It("class property of unbound type", func() { + x, err := generated.NewClassBoundClass(engine, ctx) + Expect(err).To(BeNil()) + + assertMessage( + func() (any, error) { + return x.GetPropertyProperty(ctx) + }, "Cannot access BoundClass.property due to unbound types: 12UnboundClass") + assertMessage( + func() (any, error) { + err := x.SetPropertyProperty(ctx, 10) + return nil, err + }, "Cannot access BoundClass.property due to unbound types: 12UnboundClass") + err = x.Delete(ctx) + Expect(err).To(BeNil()) + }) + }) + + When("noncopyable", func() { + It("can call method on noncopyable object", func() { + x, err := generated.NewClassNoncopyable(engine, ctx) + Expect(err).To(BeNil()) + + method, err := x.Method(ctx) + Expect(err).To(BeNil()) + Expect(method).To(Equal("foo")) + + err = x.Delete(ctx) + Expect(err).To(BeNil()) + }) + }) + + When("constants", func() { + Expect(generated.Constant_INT_CONSTANT, 10) + Expect(generated.Constant_STATIC_CONST_INTEGER_VALUE_1, 1) + Expect(generated.Constant_STATIC_CONST_INTEGER_VALUE_1000, 1000) + Expect(generated.Constant_STRING_CONSTANT, "some string") + Expect(generated.Constant_VALUE_ARRAY_CONSTANT, []any{float32(1), float32(2), float32(3), float32(4)}) + Expect(generated.Constant_VALUE_OBJECT_CONSTANT, map[string]interface{}{"w": 4, "x": 1, "y": 2, "z": 3}) + }) + + When("object handle comparison", func() { + It("", func() { + e, err := generated.NewClassValHolder(engine, ctx, "foo") + Expect(err).To(BeNil()) + + f, err := generated.NewClassValHolder(engine, ctx, "foo") + Expect(err).To(BeNil()) + + eIsAliasOfE, err := e.IsAliasOf(ctx, e) + Expect(err).To(BeNil()) + Expect(eIsAliasOfE).To(BeTrue()) + + eIsAliasOfF, err := e.IsAliasOf(ctx, f) + Expect(err).To(BeNil()) + Expect(eIsAliasOfF).To(BeFalse()) + + fIsAliasOfE, err := f.IsAliasOf(ctx, e) + Expect(err).To(BeNil()) + Expect(fIsAliasOfE).To(BeFalse()) + + err = e.Delete(ctx) + Expect(err).To(BeNil()) + + err = f.Delete(ctx) + Expect(err).To(BeNil()) + }) + }) + + When("derived-with-offset types compare with base", func() { + It("", func() { + e, err := generated.NewClassDerivedWithOffset(engine, ctx) + Expect(err).To(BeNil()) + + f, err := generated.Return_Base_from_DerivedWithOffset(engine, ctx, e) + Expect(err).To(BeNil()) + + eIsAliasOfF, err := e.IsAliasOf(ctx, f) + Expect(err).To(BeNil()) + Expect(eIsAliasOfF).To(BeTrue()) + + fIsAliasOfE, err := f.(*generated.ClassBase).IsAliasOf(ctx, e) + Expect(err).To(BeNil()) + Expect(fIsAliasOfE).To(BeTrue()) + + err = e.Delete(ctx) + Expect(err).To(BeNil()) + + err = f.(*generated.ClassBase).Delete(ctx) + Expect(err).To(BeNil()) + }) + }) + + When("memory view", func() { + + It("can pass memory view from C++ to JS", func() { + views := []any{} + err := generated.CallWithMemoryView(engine, ctx, func(view any) { + views = append(views, view) + }) + Expect(err).To(BeNil()) + Expect(views).To(HaveLen(3)) + + Expect(views[0]).To(HaveLen(8)) + Expect(views[0]).To(Equal([]uint8{0, 1, 2, 3, 4, 5, 6, 7})) + + Expect(views[1]).To(HaveLen(4)) + Expect(views[1]).To(Equal([]float32{1.5, 2.5, 3.5, 4.5})) + + Expect(views[2]).To(HaveLen(4)) + Expect(views[2]).To(Equal([]int16{1000, 100, 10, 1})) + }) + }) + + When("delete pool", func() { + It("can delete objects later", func() { + v, err := generated.NewClassValHolder(engine, ctx, struct{}{}) + Expect(err).To(BeNil()) + + _, err = v.DeleteLater(ctx) + Expect(err).To(BeNil()) + + val, err := v.GetVal(ctx) + Expect(err).To(BeNil()) + Expect(val).To(Equal(struct{}{})) + + err = engine.FlushPendingDeletes(ctx) + + val, err = v.GetVal(ctx) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("cannot pass deleted object as a pointer of type")) + } + }) + + It("calling deleteLater twice is an error", func() { + v, err := generated.NewClassValHolder(engine, ctx, struct{}{}) + Expect(err).To(BeNil()) + + _, err = v.DeleteLater(ctx) + Expect(err).To(BeNil()) + + _, err = v.DeleteLater(ctx) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("object already scheduled for deletion")) + } + }) + + It("can clone instances that have been scheduled for deletion", func() { + v, err := generated.NewClassValHolder(engine, ctx, struct{}{}) + Expect(err).To(BeNil()) + + _, err = v.DeleteLater(ctx) + Expect(err).To(BeNil()) + + v2, err := v.Clone(ctx) + Expect(err).To(BeNil()) + + err = v2.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("deleteLater returns the object", func() { + v, err := generated.NewClassValHolder(engine, ctx, struct{}{}) + Expect(err).To(BeNil()) + + vReturned, err := v.DeleteLater(ctx) + Expect(err).To(BeNil()) + + val, err := vReturned.(*generated.ClassValHolder).GetVal(ctx) + Expect(err).To(BeNil()) + Expect(val).To(Equal(struct{}{})) + }) + + It("deleteLater throws if object is already deleted", func() { + v, err := generated.NewClassValHolder(engine, ctx, struct{}{}) + Expect(err).To(BeNil()) + + err = v.Delete(ctx) + Expect(err).To(BeNil()) + + _, err = v.DeleteLater(ctx) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("class handle already deleted")) + } + }) + + It("delete throws if object is already scheduled for deletion", func() { + v, err := generated.NewClassValHolder(engine, ctx, struct{}{}) + Expect(err).To(BeNil()) + + _, err = v.DeleteLater(ctx) + Expect(err).To(BeNil()) + + err = v.Delete(ctx) + Expect(err).To(Not(BeNil())) + if err != nil { + Expect(err.Error()).To(ContainSubstring("object already scheduled for deletion")) + } + }) + + It("deleteLater invokes delay function", func() { + var runLater func(ctx context.Context) error + + err := engine.SetDelayFunction(func(fn func(ctx context.Context) error) error { + runLater = fn + return nil + }) + + Expect(err).To(BeNil()) + + v, err := generated.NewClassValHolder(engine, ctx, struct{}{}) + Expect(err).To(BeNil()) + + Expect(runLater).To(BeNil()) + + _, err = v.DeleteLater(ctx) + Expect(err).To(BeNil()) + + Expect(runLater).To(Not(BeNil())) + + isDeleted := v.IsDeleted(ctx) + + Expect(isDeleted).To(BeFalse()) + err = runLater(ctx) + Expect(err).To(BeNil()) + + isDeleted = v.IsDeleted(ctx) + Expect(isDeleted).To(BeTrue()) + }) + + It("deleteLater twice invokes delay function once", func() { + count := 0 + var runLater func(ctx context.Context) error + + err := engine.SetDelayFunction(func(fn func(ctx context.Context) error) error { + count++ + runLater = fn + return nil + }) + + Expect(err).To(BeNil()) + + v, err := generated.NewClassValHolder(engine, ctx, struct{}{}) + Expect(err).To(BeNil()) + + _, err = v.DeleteLater(ctx) + Expect(err).To(BeNil()) + + v2, err := generated.NewClassValHolder(engine, ctx, struct{}{}) + Expect(err).To(BeNil()) + + _, err = v2.DeleteLater(ctx) + Expect(err).To(BeNil()) + + Expect(count).To(Equal(1)) + + err = runLater(ctx) + Expect(err).To(BeNil()) + + v3, err := generated.NewClassValHolder(engine, ctx, struct{}{}) + Expect(err).To(BeNil()) + + _, err = v3.DeleteLater(ctx) + Expect(err).To(BeNil()) + + Expect(count).To(Equal(2)) + }) + + It("The delay function is immediately invoked if the deletion queue is not empty", func() { + v, err := generated.NewClassValHolder(engine, ctx, struct{}{}) + Expect(err).To(BeNil()) + + _, err = v.DeleteLater(ctx) + Expect(err).To(BeNil()) + + count := 0 + err = engine.SetDelayFunction(func(fn func(ctx context.Context) error) error { + count++ + return nil + }) + Expect(err).To(BeNil()) + Expect(count).To(Equal(1)) + }) + + // The idea is that an interactive application would + // periodically flush the deleteLater queue by calling + // + // setDelayFunction(function(fn) { + // setTimeout(fn, 0); + // }); + }) + + When("references", func() { + It("JS object handles can be passed through to C++ by reference", func() { + sh1, err := generated.NewClassStringHolder(engine, ctx, "Hello world") + Expect(err).To(BeNil()) + + sh1String, err := sh1.Get(ctx) + Expect(err).To(BeNil()) + Expect(sh1String).To(Equal("Hello world")) + + err = generated.Clear_StringHolder(engine, ctx, sh1) + Expect(err).To(BeNil()) + + sh1String, err = sh1.Get(ctx) + Expect(err).To(BeNil()) + Expect(sh1String).To(Equal("")) + + err = sh1.Delete(ctx) + Expect(err).To(BeNil()) + }) + }) + + When("val::as from pointer to value", func() { + It("calling as on pointer with value makes a copy", func() { + sh1, err := generated.NewClassStringHolder(engine, ctx, "Hello world") + Expect(err).To(BeNil()) + + sh2, err := generated.Return_StringHolder_copy(engine, ctx, sh1) + Expect(err).To(BeNil()) + + isAliasOf, err := sh1.IsAliasOf(ctx, sh2) + Expect(err).To(BeNil()) + Expect(isAliasOf).To(BeFalse()) + + err = sh2.(*generated.ClassStringHolder).Delete(ctx) + Expect(err).To(BeNil()) + + err = sh1.Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("calling function that returns a StringHolder", func() { + sh1, err := generated.NewClassStringHolder(engine, ctx, "Hello world") + Expect(err).To(BeNil()) + + sh2, err := generated.Call_StringHolder_func(engine, ctx, func() *generated.ClassStringHolder { + return sh1 + }) + Expect(err).To(BeNil()) + + sh1String, err := sh1.Get(ctx) + Expect(err).To(BeNil()) + Expect(sh1String).To(Equal("Hello world")) + + sh2String, err := sh2.(*generated.ClassStringHolder).Get(ctx) + Expect(err).To(BeNil()) + Expect(sh2String).To(Equal("Hello world")) + + isAliasOf, err := sh1.IsAliasOf(ctx, sh2) + Expect(err).To(BeNil()) + Expect(isAliasOf).To(BeFalse()) + + err = sh2.(*generated.ClassStringHolder).Delete(ctx) + Expect(err).To(BeNil()) + + err = sh1.Delete(ctx) + Expect(err).To(BeNil()) + }) + }) + + When("mixin", func() { + It("can call mixin method", func() { + a, err := generated.NewClassDerivedWithMixin(engine, ctx) + Expect(err).To(BeNil()) + + // assert.instanceof(a, cm.Base); + + get10, err := a.Get10(ctx) + Expect(err).To(BeNil()) + Expect(get10).To(Equal(int32(10))) + + err = a.Delete(ctx) + Expect(err).To(BeNil()) + }) + }) + + When("val::as", func() { + It("built-ins", func() { + valAsBool, err := generated.Val_as_bool(engine, ctx, true) + Expect(err).To(BeNil()) + Expect(valAsBool).To(BeTrue()) + + valAsBool, err = generated.Val_as_bool(engine, ctx, false) + Expect(err).To(BeNil()) + Expect(valAsBool).To(BeFalse()) + + valAsChar, err := generated.Val_as_char(engine, ctx, int8(127)) + Expect(err).To(BeNil()) + Expect(valAsChar).To(Equal(int8(127))) + + valAsShort, err := generated.Val_as_short(engine, ctx, int16(32767)) + Expect(err).To(BeNil()) + Expect(valAsShort).To(Equal(int16(32767))) + + valAsInt, err := generated.Val_as_int(engine, ctx, int32(65536)) + Expect(err).To(BeNil()) + Expect(valAsInt).To(Equal(int32(65536))) + + valAsLong, err := generated.Val_as_long(engine, ctx, int32(65536)) + Expect(err).To(BeNil()) + Expect(valAsLong).To(Equal(int32(65536))) + + valAsDouble, err := generated.Val_as_float(engine, ctx, float32(10.5)) + Expect(err).To(BeNil()) + Expect(valAsDouble).To(Equal(float32(10.5))) + + valAsFloat, err := generated.Val_as_double(engine, ctx, float64(10.5)) + Expect(err).To(BeNil()) + Expect(valAsFloat).To(Equal(float64(10.5))) + + valAsString, err := generated.Val_as_string(engine, ctx, "foo") + Expect(err).To(BeNil()) + Expect(valAsString).To(Equal("foo")) + + valAsWString, err := generated.Val_as_wstring(engine, ctx, "foo") + Expect(err).To(BeNil()) + Expect(valAsWString).To(Equal("foo")) + + obj := struct{}{} + + valAsObj, err := generated.Val_as_val(engine, ctx, obj) + Expect(err).To(BeNil()) + Expect(valAsObj).To(Equal(obj)) + + // JS->C++ memory view not implemented (comment from emscripten) + //var ab = cm.val_as_memory_view(new ArrayBuffer(13)); + //assert.equal(13, ab.byteLength); + }) + + It("value types", func() { + tuple := []any{float32(1), float32(2), float32(3), float32(4)} + + valAsValueArray, err := generated.Val_as_value_array(engine, ctx, tuple) + Expect(err).To(BeNil()) + Expect(valAsValueArray).To(Equal(tuple)) + + valStruct := map[string]any{ + "x": float32(1), + "y": float32(2), + "z": float32(3), + "w": float32(4), + } + + valAsValueStruct, err := generated.Val_as_value_object(engine, ctx, valStruct) + Expect(err).To(BeNil()) + Expect(valAsValueStruct).To(Equal(valStruct)) + }) + + It("enums", func() { + valAsEnum, err := generated.Val_as_enum(engine, ctx, generated.EnumEnum_ONE) + Expect(err).To(BeNil()) + Expect(valAsEnum).To(Equal(generated.EnumEnum_ONE)) + }) + }) + + When("val::new_", func() { + It("variety of types", func() { + type factoryStruct struct { + Arg1 uint8 `embind_arg:"0"` + Arg2 float64 `embind_arg:"1"` + Arg3 string `embind_arg:"2"` + Arg4 map[string]any `embind_arg:"3"` + Arg5 generated.EnumEnumClass `embind_arg:"4"` + Arg6 []any `embind_arg:"5"` + } + instance, err := generated.Construct_with_6_arguments(engine, ctx, factoryStruct{}) + Expect(err).To(BeNil()) + Expect(instance).To(Equal(factoryStruct{ + Arg1: 6, + Arg2: -12.5, + Arg3: "a3", + Arg4: map[string]any{ + "x": float32(1), + "y": float32(2), + "z": float32(3), + "w": float32(4), + }, + Arg5: generated.EnumEnumClass_TWO, + Arg6: []any{ + float32(-1), + float32(-2), + float32(-3), + float32(-4), + }, + })) + }) + + It("memory view", func() { + type factoryStruct struct { + Before string `embind_arg:"0"` + View []int8 `embind_arg:"1"` + After string `embind_arg:"2"` + } + + instance, err := generated.Construct_with_memory_view(engine, ctx, factoryStruct{}) + Expect(err).To(BeNil()) + Expect(instance).To(Equal(factoryStruct{ + Before: "before", + View: []int8{48, 49, 50, 51, 52, 53, 54, 55, 56, 57}, + After: "after", + })) + }) + + It("ints_and_float", func() { + type factoryStruct struct { + A int32 `embind_arg:"0"` + B float32 `embind_arg:"1"` + C int32 `embind_arg:"2"` + } + + instance, err := generated.Construct_with_ints_and_float(engine, ctx, factoryStruct{}) + Expect(err).To(BeNil()) + Expect(instance).To(Equal(factoryStruct{ + A: 65537, + B: 4.0, + C: 65538, + })) + }) + + It("before and after memory growth", func() { + // @todo: implement EmvalNewArray. + // @todo: implement some globals that we can also have on our side (like Uint8Array). + //array, err := generated.Construct_with_arguments_before_and_after_memory_growth(engine, ctx) + //Expect(err).To(BeNil()) + //Expect(array.([]uint8)[0]).To(HaveLen(5)) + //Expect(array.([]uint8)[0]).To(HaveLen(len(array.([]uint8)[1]))) + }) + }) + + When("intrusive pointers", func() { + It("can pass intrusive pointers", func() { + ic, err := generated.NewClassIntrusiveClass(engine, ctx) + Expect(err).To(BeNil()) + + d, err := generated.PassThroughIntrusiveClass(engine, ctx, ic) + Expect(err).To(BeNil()) + + isAlias, err := ic.IsAliasOf(ctx, d) + Expect(err).To(BeNil()) + Expect(isAlias).To(Equal(true)) + + err = ic.Delete(ctx) + Expect(err).To(BeNil()) + + err = d.(*generated.ClassIntrusiveClass).Delete(ctx) + Expect(err).To(BeNil()) + }) + + It("can hold intrusive pointers", func() { + ic, err := generated.NewClassIntrusiveClass(engine, ctx) + Expect(err).To(BeNil()) + + holder, err := generated.NewClassIntrusiveClassHolder(engine, ctx) + Expect(err).To(BeNil()) + + err = holder.Set(ctx, ic) + Expect(err).To(BeNil()) + + err = ic.Delete(ctx) + Expect(err).To(BeNil()) + + d, err := holder.Get(ctx) + Expect(err).To(BeNil()) + + err = d.(*generated.ClassIntrusiveClass).Delete(ctx) + Expect(err).To(BeNil()) + + err = holder.Delete(ctx) + Expect(err).To(BeNil()) + }) + + // @todo: implement me + // We don't support this in Go right now. Needs CreateInheritingConstructor. + It("can extend from intrusive pointer class and still preserve reference in JavaScript", func() { + //type newStructTypeToExtend struct { + // embind.ClassBase + //} + //C, err := generated.ClassIntrusiveClassStaticExtend(engine, ctx, "C2", &newStructTypeToExtend{}) + //Expect(err).To(BeNil()) + //log.Println(C) + //log.Println(C.(func(context.Context, ...any) (any, error))(ctx)) + + //var instance = new C; + //var holder = new cm.IntrusiveClassHolder; + //holder.set(instance); + //instance.delete(); + + //var back = holder.get(); + //assert.equal(back, instance); + //holder.delete(); + //back.delete(); + }) + }) + + When("typeof", func() { + It("typeof", func() { + typeName, err := generated.GetTypeOfVal(engine, ctx, nil) + Expect(err).To(BeNil()) + Expect(typeName).To(Equal("object")) + + typeName, err = generated.GetTypeOfVal(engine, ctx, struct{}{}) + Expect(err).To(BeNil()) + Expect(typeName).To(Equal("object")) + + typeName, err = generated.GetTypeOfVal(engine, ctx, func() {}) + Expect(err).To(BeNil()) + Expect(typeName).To(Equal("function")) + + typeName, err = generated.GetTypeOfVal(engine, ctx, 1) + Expect(err).To(BeNil()) + Expect(typeName).To(Equal("number")) + + typeName, err = generated.GetTypeOfVal(engine, ctx, "hi") + Expect(err).To(BeNil()) + Expect(typeName).To(Equal("string")) + + typeName, err = generated.GetTypeOfVal(engine, ctx, types.Undefined) + Expect(err).To(BeNil()) + Expect(typeName).To(Equal("undefined")) + + typeName, err = generated.GetTypeOfVal(engine, ctx, true) + Expect(err).To(BeNil()) + Expect(typeName).To(Equal("boolean")) + + typeName, err = generated.GetTypeOfVal(engine, ctx, int64(0)) + Expect(err).To(BeNil()) + Expect(typeName).To(Equal("bigint")) + + typeName, err = generated.GetTypeOfVal(engine, ctx, uint64(0)) + Expect(err).To(BeNil()) + Expect(typeName).To(Equal("bigint")) + }) + }) + + When("static members", func() { + It("static members", func() { + c, err := generated.ClassHasStaticMemberGetStaticPropertyC(engine, ctx) + Expect(err).To(BeNil()) + Expect(c).To(Equal(int32(10))) + + v, err := generated.ClassHasStaticMemberGetStaticPropertyV(engine, ctx) + Expect(err).To(BeNil()) + Expect(v).To(Equal(int32(20))) + + err = generated.ClassHasStaticMemberSetStaticPropertyV(engine, ctx, 30) + Expect(err).To(BeNil()) + + v, err = generated.ClassHasStaticMemberGetStaticPropertyV(engine, ctx) + Expect(err).To(BeNil()) + Expect(v).To(Equal(int32(30))) + }) + }) +}) diff --git a/types/types.go b/types/types.go new file mode 100644 index 0000000..3971dd0 --- /dev/null +++ b/types/types.go @@ -0,0 +1,5 @@ +package types + +type UndefinedType int8 + +var Undefined = UndefinedType(0) diff --git a/wazero.go b/wazero.go index 7787cc6..ed6423f 100644 --- a/wazero.go +++ b/wazero.go @@ -40,6 +40,17 @@ func (e unexportedFunctionError) Error() string { return fmt.Sprintf("you need to export the \"%s\" function to make embind work, you can do this using the \"EXPORTED_FUNCTIONS\" option in Emscripten during compilation, you will need to prepend exports with an underscore, so you have to add \"_%s\" to the list", e.name, e.name) } +func (e functionExporter) GetImportedFunction(name string) api.FunctionDefinition { + importedFunctions := e.guest.ImportedFunctions() + for i := range importedFunctions { + if importedFunctions[i].Name() == name { + return importedFunctions[i] + } + } + + return nil +} + // ExportFunctions implements FunctionExporter.ExportFunctions func (e functionExporter) ExportFunctions(b wazero.HostModuleBuilder) error { // First validate whether required functions are available. @@ -66,11 +77,25 @@ func (e functionExporter) ExportFunctions(b wazero.HostModuleBuilder) error { WithGoModuleFunction(internal.RegisterVoid, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}). Export("_embind_register_void") - b.NewFunctionBuilder(). - WithName("_embind_register_bool"). - WithParameterNames("rawType", "name", "size", "trueValue", "falseValue"). - WithGoModuleFunction(internal.RegisterBool, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}). - Export("_embind_register_bool") + importedEmbindRegisterBool := e.GetImportedFunction("_embind_register_bool") + if importedEmbindRegisterBool != nil { + // Since Emscripten 3.1.45, the size of the boolean is put to 1, while + // before the size was part of the registration. + boolHasSizeArgument := len(importedEmbindRegisterBool.ParamTypes()) == 5 + if boolHasSizeArgument { + b.NewFunctionBuilder(). + WithName("_embind_register_bool"). + WithParameterNames("rawType", "name", "size", "trueValue", "falseValue"). + WithGoModuleFunction(internal.RegisterBool(true), []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}). + Export("_embind_register_bool") + } else { + b.NewFunctionBuilder(). + WithName("_embind_register_bool"). + WithParameterNames("rawType", "name", "trueValue", "falseValue"). + WithGoModuleFunction(internal.RegisterBool(false), []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}). + Export("_embind_register_bool") + } + } b.NewFunctionBuilder(). WithName("_embind_register_integer"). @@ -211,6 +236,13 @@ func (e functionExporter) ExportFunctions(b wazero.HostModuleBuilder) error { WithGoModuleFunction(internal.EmvalGetMethodCaller, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). Export("_emval_get_method_caller") + b.NewFunctionBuilder(). + WithName("_emval_call"). + WithParameterNames("handle", "argCount", "argTypes", "argv"). + WithResultNames("handle"). + WithGoModuleFunction(internal.EmvalCall, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_call") + b.NewFunctionBuilder(). WithName("_emval_call_method"). WithParameterNames("caller", "id", "methodName", "destructorsRef", "args"). @@ -355,5 +387,191 @@ func (e functionExporter) ExportFunctions(b wazero.HostModuleBuilder) error { WithGoModuleFunction(internal.FinalizeValueObject, []api.ValueType{api.ValueTypeI32}, []api.ValueType{}). Export("_embind_finalize_value_object") + b.NewFunctionBuilder(). + WithName("_embind_register_smart_ptr"). + WithParameterNames( + "rawType", + "rawPointeeType", + "name", + "sharingPolicy", + "getPointeeSignature", + "rawGetPointee", + "constructorSignature", + "rawConstructor", + "shareSignature", + "rawShare", + "destructorSignature", + "rawDestructor", + ). + WithGoModuleFunction(internal.RegisterSmartPtr, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}). + Export("_embind_register_smart_ptr") + + b.NewFunctionBuilder(). + WithName("_embind_create_inheriting_constructor"). + WithParameterNames("constructorName", "wrapperType", "properties"). + WithResultNames("handle"). + WithGoModuleFunction(internal.CreateInheritingConstructor, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_embind_create_inheriting_constructor") + + b.NewFunctionBuilder(). + WithName("_embind_register_class_class_property"). + WithParameterNames( + "rawClassType", + "fieldName", + "rawFieldType", + "rawFieldPtr", + "getterSignature", + "getter", + "setterSignature", + "setter", + ). + WithGoModuleFunction(internal.RegisterClassClassProperty, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}). + Export("_embind_register_class_class_property") + + b.NewFunctionBuilder(). + WithName("_emval_as_int64"). + WithParameterNames("handle", "returnType"). + WithResultNames("value"). + WithGoModuleFunction(internal.EmvalAsInt64, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI64}). + Export("_emval_as_int64") + + b.NewFunctionBuilder(). + WithName("_emval_as_uint64"). + WithParameterNames("handle", "returnType"). + WithResultNames("value"). + WithGoModuleFunction(internal.EmvalAsUint64, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI64}). + Export("_emval_as_uint64") + + b.NewFunctionBuilder(). + WithName("_emval_await"). + WithParameterNames("handle"). + WithResultNames("value"). + WithGoModuleFunction(internal.EmvalAwait, []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_await") + + b.NewFunctionBuilder(). + WithName("_emval_delete"). + WithParameterNames("object", "property"). + WithResultNames("result"). + WithGoModuleFunction(internal.EmvalDelete, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_delete") + + b.NewFunctionBuilder(). + WithName("_emval_equals"). + WithParameterNames("handle", "handle2"). + WithResultNames("result"). + WithGoModuleFunction(internal.EmvalEquals, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_equals") + + b.NewFunctionBuilder(). + WithName("_emval_get_module_property"). + WithParameterNames("name"). + WithResultNames("handle"). + WithGoModuleFunction(internal.EmvalGetModuleProperty, []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_get_module_property") + + b.NewFunctionBuilder(). + WithName("_emval_greater_than"). + WithParameterNames("handle", "handle2"). + WithResultNames("result"). + WithGoModuleFunction(internal.EmvalGreaterThan, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}). + Export("_emval_greater_than") + + b.NewFunctionBuilder(). + WithName("_emval_in"). + WithParameterNames("handle", "handle2"). + WithResultNames("result"). + WithGoModuleFunction(internal.EmvalIn, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_in") + + b.NewFunctionBuilder(). + WithName("_emval_instanceof"). + WithParameterNames("handle", "handle2"). + WithResultNames("result"). + WithGoModuleFunction(internal.EmvalInstanceof, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_instanceof") + + b.NewFunctionBuilder(). + WithName("_emval_is_number"). + WithParameterNames("handle"). + WithResultNames("result"). + WithGoModuleFunction(internal.EmvalIsNumber, []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_is_number") + + b.NewFunctionBuilder(). + WithName("_emval_is_string"). + WithParameterNames("handle"). + WithResultNames("result"). + WithGoModuleFunction(internal.EmvalIsString, []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_is_string") + + b.NewFunctionBuilder(). + WithName("_emval_less_than"). + WithParameterNames("handle", "handle2"). + WithResultNames("result"). + WithGoModuleFunction(internal.EmvalLessThan, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_less_than") + + b.NewFunctionBuilder(). + WithName("_emval_new_array"). + WithResultNames("array"). + WithGoModuleFunction(internal.EmvalNewArray, []api.ValueType{}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_new_array") + + b.NewFunctionBuilder(). + WithName("_emval_new_array_from_memory_view"). + WithParameterNames("view"). + WithResultNames("array"). + WithGoModuleFunction(internal.EmvalNewArrayFromMemoryView, []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_new_array_from_memory_view") + + b.NewFunctionBuilder(). + WithName("_emval_new_object"). + WithResultNames("object"). + WithGoModuleFunction(internal.EmvalNewObject, []api.ValueType{}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_new_object") + + b.NewFunctionBuilder(). + WithName("_emval_new_u16string"). + WithParameterNames("in"). + WithResultNames("out"). + WithGoModuleFunction(internal.EmvalNewU16string, []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_new_u16string") + + b.NewFunctionBuilder(). + WithName("_emval_new_u8string"). + WithParameterNames("in"). + WithResultNames("out"). + WithGoModuleFunction(internal.EmvalNewU8string, []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_new_u8string") + + b.NewFunctionBuilder(). + WithName("_emval_not"). + WithParameterNames("handle"). + WithResultNames("result"). + WithGoModuleFunction(internal.EmvalNot, []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_not") + + b.NewFunctionBuilder(). + WithName("_emval_strictly_equals"). + WithParameterNames("handle1", "handle2"). + WithResultNames("result"). + WithGoModuleFunction(internal.EmvalStrictlyEquals, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_strictly_equals") + + b.NewFunctionBuilder(). + WithName("_emval_throw"). + WithParameterNames("handle"). + WithResultNames("object"). + WithGoModuleFunction(internal.EmvalThrow, []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_throw") + + b.NewFunctionBuilder(). + WithName("_emval_typeof"). + WithParameterNames("handle"). + WithResultNames("type"). + WithGoModuleFunction(internal.EmvalTypeof, []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_typeof") + return nil }