From 7d368c4974425a3001c142f41ff0f88a4cc0a3cd Mon Sep 17 00:00:00 2001 From: Spotandjake Date: Tue, 10 Feb 2026 17:52:04 -0500 Subject: [PATCH 1/3] feat(C & JS API): Add `BinaryenHasMemorySegment` This pr adds `BinaryenHasMemorySegment(module, name)` to the c api and `module.hasMemorySegment(name)` to the js api. --- CHANGELOG.md | 2 ++ src/binaryen-c.cpp | 3 +++ src/binaryen-c.h | 1 + src/js/binaryen.js-post.js | 8 ++++++++ test/binaryen.js/kitchen-sink.js | 2 ++ test/example/c-api-kitchen-sink.c | 3 ++- 6 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c94d7dfc0b..0d20f3a4253 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,8 @@ Current Trunk `BinaryenMemoryOrder` param. The functions formerly implicitly used `BinaryenMemoryOrderSeqCst()`. In JS this param is optional and thus not breaking. + - Add `BinaryenHasMemorySegment(, )` to the C API and + `module.hasMemorySegment(name)` to the JS API. Allowing users to check if a segment exists. v125 ---- diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index efbf69d3de3..cf6f2efe795 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -5512,6 +5512,9 @@ void BinaryenSetMemory(BinaryenModuleRef module, uint32_t BinaryenGetNumMemorySegments(BinaryenModuleRef module) { return ((Module*)module)->dataSegments.size(); } +bool BinaryenHasMemorySegment(BinaryenModuleRef module, const char* segmentName) { + return (Module*)module->getDataSegmentOrNull(Name(segmentName)) != NULL; +} uint32_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module, const char* segmentName) { auto* wasm = (Module*)module; diff --git a/src/binaryen-c.h b/src/binaryen-c.h index 806574f744e..c1411da2516 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -3017,6 +3017,7 @@ BINARYEN_API bool BinaryenMemoryIs64(BinaryenModuleRef module, // Memory segments. Query utilities. BINARYEN_API uint32_t BinaryenGetNumMemorySegments(BinaryenModuleRef module); +BINARYEN_API bool BinaryenHasMemorySegment(BinaryenModuleRef module, const char* segmentName); BINARYEN_API uint32_t BinaryenGetMemorySegmentByteOffset( BinaryenModuleRef module, const char* segmentName); BINARYEN_API size_t BinaryenGetMemorySegmentByteLength(BinaryenModuleRef module, diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 0541b171f22..748ff652c8e 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -2757,6 +2757,14 @@ function wrapModule(module, self = {}) { self['getNumMemorySegments'] = function() { return Module['_BinaryenGetNumMemorySegments'](module); }; + /** + * Determines wether a memory segment with the given name exists within the given module. + * @param {string} name - The name of the memory segment to check exists. + * @returns `true` if the memory segment exists, `false` otherwise + */ + self['hasMemorySegment'] = function(name) { + return Boolean(Module['_BinaryenHasMemorySegment'](module, strToStack(name))); + }; self['getMemorySegmentInfo'] = function(name) { return preserveStack(() => { const passive = Boolean(Module['_BinaryenGetMemorySegmentPassive'](module, strToStack(name))); diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js index 673a470607d..1e69d82e34a 100644 --- a/test/binaryen.js/kitchen-sink.js +++ b/test/binaryen.js/kitchen-sink.js @@ -1132,6 +1132,8 @@ function test_for_each() { data: expected_data[2].split('').map(function(x) { return x.charCodeAt(0) }) } ], false); + assert(module.hasMemorySegment(expected_names[0])); + assert(!module.hasMemorySegment("NonExistantSegment")); for (i = 0; i < module.getNumMemorySegments(); i++) { var segment = module.getMemorySegmentInfo(expected_names[i]); assert(expected_offsets[i] === segment.offset); diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index 2499ffff646..48c2e0e27c2 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -2004,7 +2004,8 @@ void test_for_each() { BinaryenTypeInt32(), 0, makeInt32(module, expected_offsets[1])); - + assert(BinaryenHasMemorySegment(module, segmentNames[0])); + assert(!BinaryenHasMemorySegment(module, "NonExistantSegment")); for (i = 0; i < BinaryenGetNumMemorySegments(module); i++) { char out[15] = {}; assert(BinaryenGetMemorySegmentByteOffset(module, segmentNames[i]) == From cd887c12ea9ebae90461a9805be7ac5875abe1ca Mon Sep 17 00:00:00 2001 From: Spotandjake Date: Tue, 10 Feb 2026 18:47:25 -0500 Subject: [PATCH 2/3] chore: formatting --- src/binaryen-c.cpp | 3 ++- src/binaryen-c.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index cf6f2efe795..6f883928c72 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -5512,7 +5512,8 @@ void BinaryenSetMemory(BinaryenModuleRef module, uint32_t BinaryenGetNumMemorySegments(BinaryenModuleRef module) { return ((Module*)module)->dataSegments.size(); } -bool BinaryenHasMemorySegment(BinaryenModuleRef module, const char* segmentName) { +bool BinaryenHasMemorySegment(BinaryenModuleRef module, + const char* segmentName) { return (Module*)module->getDataSegmentOrNull(Name(segmentName)) != NULL; } uint32_t BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module, diff --git a/src/binaryen-c.h b/src/binaryen-c.h index c1411da2516..9e552e8b70c 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -3017,7 +3017,8 @@ BINARYEN_API bool BinaryenMemoryIs64(BinaryenModuleRef module, // Memory segments. Query utilities. BINARYEN_API uint32_t BinaryenGetNumMemorySegments(BinaryenModuleRef module); -BINARYEN_API bool BinaryenHasMemorySegment(BinaryenModuleRef module, const char* segmentName); +BINARYEN_API bool BinaryenHasMemorySegment(BinaryenModuleRef module, + const char* segmentName); BINARYEN_API uint32_t BinaryenGetMemorySegmentByteOffset( BinaryenModuleRef module, const char* segmentName); BINARYEN_API size_t BinaryenGetMemorySegmentByteLength(BinaryenModuleRef module, From d21c52a524a92fd268704ef33569d8bfdce3e058 Mon Sep 17 00:00:00 2001 From: Spotandjake Date: Wed, 11 Feb 2026 12:06:30 -0500 Subject: [PATCH 3/3] fix: Ensure to call `preserveStack` before calling `strToStack` --- src/js/binaryen.js-post.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 748ff652c8e..ab760b62508 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -2763,7 +2763,7 @@ function wrapModule(module, self = {}) { * @returns `true` if the memory segment exists, `false` otherwise */ self['hasMemorySegment'] = function(name) { - return Boolean(Module['_BinaryenHasMemorySegment'](module, strToStack(name))); + return preserveStack(() => Boolean(Module['_BinaryenHasMemorySegment'](module, strToStack(name)))); }; self['getMemorySegmentInfo'] = function(name) { return preserveStack(() => {