Skip to content

Commit badb440

Browse files
feat: Phase E.3 — WASM target (Emscripten embind + drag-and-drop demo)
Compile the core Parquet reader/writer to WebAssembly via Emscripten embind, enabling browser-side Parquet inspection with zero server dependencies. Includes AES-256 PME encrypted file support. Platform guards: - forge.hpp: exclude mmap_reader.hpp and streaming_sink.hpp on __EMSCRIPTEN__ - wal.hpp: exclude wal_mapped_segment.hpp on __EMSCRIPTEN__ CMake: - SIGNET_BUILD_WASM option + signet_wasm target with embind link flags - wasm configure/build preset (commercial enabled, no external codecs) New files: - wasm/signet_wasm.cpp: embind bindings for SchemaBuilder, Schema, WriterOptions, ParquetWriter (6 typed write methods), ParquetReader (6 typed read methods + readColumnAsStrings), MEMFS helpers, version(), openEncrypted() with footer key + column key + AAD prefix support - wasm/demo.html: self-contained drag-and-drop Parquet preview with paginated data table (50 rows/page, 10K max loaded), schema inspector, file metadata, encrypted file toggle (footer key, column key, AAD prefix, per-column keys), dark theme Output: signet_wasm.js (104K) + signet_wasm.wasm (521K) Native regression: 394/394 tests pass (guards are __EMSCRIPTEN__-only) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 356c880 commit badb440

6 files changed

Lines changed: 919 additions & 3 deletions

File tree

CMakeLists.txt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ set(SIGNET_EVAL_WARN_PCT_2 "90" CACHE STRING
4444
"Default evaluation-tier second warning threshold percentage")
4545
set(SIGNET_COMMERCIAL_LICENSE_HASH "" CACHE STRING
4646
"64-bit FNV-1a hash literal for SIGNET_COMMERCIAL_LICENSE_KEY (example: 0x0123abcd)")
47+
option(SIGNET_BUILD_WASM "Build WASM target via Emscripten embind" OFF)
4748
option(SIGNET_MINIMAL_DEPS "Disable ALL optional external dependencies (for embedded/microcontroller builds)" OFF)
4849

4950
if(SIGNET_BUILD_AI_AUDIT)
@@ -474,6 +475,36 @@ if(SIGNET_BUILD_FFI)
474475
message(STATUS "SIGNET_BUILD_FFI=ON: C FFI static library enabled")
475476
endif()
476477

478+
# ---------------------------------------------------------------------------
479+
# WASM — Emscripten embind target (browser-side Parquet preview)
480+
# ---------------------------------------------------------------------------
481+
if(SIGNET_BUILD_WASM AND EMSCRIPTEN)
482+
add_executable(signet_wasm wasm/signet_wasm.cpp)
483+
target_link_libraries(signet_wasm PRIVATE signet::forge)
484+
target_compile_features(signet_wasm PRIVATE cxx_std_20)
485+
target_link_options(signet_wasm PRIVATE
486+
--bind
487+
-sWASM=1
488+
-sALLOW_MEMORY_GROWTH=1
489+
-sMODULARIZE=1
490+
-sEXPORT_NAME=SignetForge
491+
-sENVIRONMENT=web
492+
-sFORCE_FILESYSTEM=1
493+
"-sEXPORTED_RUNTIME_METHODS=['FS']"
494+
-fexceptions
495+
)
496+
target_compile_options(signet_wasm PRIVATE -fexceptions)
497+
set_target_properties(signet_wasm PROPERTIES
498+
SUFFIX ".js"
499+
)
500+
install(FILES
501+
${CMAKE_CURRENT_BINARY_DIR}/signet_wasm.js
502+
${CMAKE_CURRENT_BINARY_DIR}/signet_wasm.wasm
503+
DESTINATION share/signet_forge/wasm
504+
)
505+
message(STATUS "SIGNET_BUILD_WASM=ON: Emscripten WASM target enabled")
506+
endif()
507+
477508
# ---------------------------------------------------------------------------
478509
# Fuzz harnesses (libFuzzer — requires Clang)
479510
# ---------------------------------------------------------------------------

CMakePresets.json

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,25 @@
179179
"CMAKE_CXX_FLAGS": "-fprofile-instr-generate -fcoverage-mapping",
180180
"CMAKE_EXE_LINKER_FLAGS": "-fprofile-instr-generate"
181181
}
182+
},
183+
{
184+
"name": "wasm",
185+
"displayName": "WASM (Emscripten embind, browser-side Parquet + PME encryption)",
186+
"generator": "Ninja",
187+
"binaryDir": "${sourceDir}/build-wasm",
188+
"cacheVariables": {
189+
"CMAKE_BUILD_TYPE": "Release",
190+
"SIGNET_BUILD_WASM": "ON",
191+
"SIGNET_ENABLE_COMMERCIAL": "ON",
192+
"SIGNET_ENABLE_ZSTD": "OFF",
193+
"SIGNET_ENABLE_LZ4": "OFF",
194+
"SIGNET_ENABLE_GZIP": "OFF",
195+
"SIGNET_ENABLE_PQ": "OFF",
196+
"SIGNET_BUILD_TESTS": "OFF",
197+
"SIGNET_BUILD_BENCHMARKS": "OFF",
198+
"SIGNET_BUILD_EXAMPLES": "OFF",
199+
"SIGNET_BUILD_TOOLS": "OFF"
200+
}
182201
}
183202
],
184203
"buildPresets": [
@@ -222,7 +241,8 @@
222241
{ "name": "server", "configurePreset": "server" },
223242
{ "name": "server-pq", "configurePreset": "server-pq" },
224243
{ "name": "fuzz", "configurePreset": "fuzz" },
225-
{ "name": "coverage", "configurePreset": "coverage" }
244+
{ "name": "coverage", "configurePreset": "coverage" },
245+
{ "name": "wasm", "configurePreset": "wasm" }
226246
],
227247
"testPresets": [
228248
{

include/signet/ai/wal.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,6 +1170,9 @@ class WalManager {
11701170
// Included here so detail_mmap:: helpers have access to the signet::forge
11711171
// namespace already opened above; WalMmapWriter produces files readable by
11721172
// WalReader without any changes to the reader.
1173+
// Excluded on Emscripten — WalMmapWriter requires std::thread + POSIX mmap.
11731174
// ---------------------------------------------------------------------------
1175+
#ifndef __EMSCRIPTEN__
11741176
#include "signet/ai/wal_mapped_segment.hpp"
1177+
#endif
11751178

include/signet/forge.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222
/// @note Commercial AI audit and compliance modules (audit_chain, decision_log,
2323
/// inference_log, MiFID II/EU AI Act reporters) are conditionally included
2424
/// only when `SIGNET_ENABLE_COMMERCIAL` is defined and non-zero.
25-
/// @note The mmap_reader module is excluded on Windows (`_WIN32`).
25+
/// @note The mmap_reader module is excluded on Windows (`_WIN32`) and Emscripten (`__EMSCRIPTEN__`).
26+
/// @note The streaming_sink and wal_mapped_segment modules are excluded on Emscripten
27+
/// (they require `std::thread`, unavailable in single-threaded WASM).
2628

2729
/// @name Core: error handling, types, schema, statistics, memory, Thrift, column I/O
2830
/// @{
@@ -81,7 +83,7 @@
8183
/// @name Page Index + Memory-Mapped I/O
8284
/// @{
8385
#include "signet/column_index.hpp"
84-
#ifndef _WIN32
86+
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__)
8587
#include "signet/mmap_reader.hpp"
8688
#endif
8789
/// @}
@@ -96,7 +98,9 @@
9698
/// @name Streaming WAL + Async Compaction (Apache 2.0)
9799
/// @{
98100
#include "signet/ai/wal.hpp"
101+
#ifndef __EMSCRIPTEN__
99102
#include "signet/ai/streaming_sink.hpp"
103+
#endif
100104
/// @}
101105

102106
/// @name Feature Store: point-in-time feature retrieval (Apache 2.0)

0 commit comments

Comments
 (0)