Currently, the SWFRecomp test build process requires duplicating runtime files, build scripts, and headers across each test directory. This document outlines the current issues and proposes solutions to minimize duplication and streamline the process of building and deploying WASM demos.
Key Finding: The SWFModernRuntime repository contains a comprehensive, production-quality runtime library with 1,000+ lines of ActionScript implementation, variable storage, and memory management. This library can potentially replace the simple, duplicated runtimes currently used in test directories.
-
Runtime files duplicated per test - Each test that has WASM support has its own
runtime/directory with copies of similar filesSWFRecomp/tests/trace_swf_4/runtime/SWFRecomp/tests/dyna_string_vars_swf_4/runtime/
-
Build scripts duplicated - Each test needs its own
Makefileandbuild_wasm.shwith nearly identical content- Build scripts are ~70 lines each, mostly identical
- Any improvements require updating all copies
-
Header files duplicated -
recomp.h,stackvalue.hare copied in each test's runtime directory- Makes it difficult to maintain consistency
- Bug fixes require updates in multiple locations
-
Inconsistent runtime implementations
- Some tests (like
dyna_string_vars_swf_4) have more advanced runtimes (305 lines) with variable storage - Simpler tests (like
trace_swf_4) have minimal runtimes (76 lines) - Different levels of ActionScript support across tests
- Some tests (like
-
Most tests don't have WASM build support yet
- Only 2 out of ~50 tests have full
runtime/wasm/directories - Setting up WASM support for a new test requires creating ~5-7 files
- Only 2 out of ~50 tests have full
SWFRecomp/tests/trace_swf_4/
├── test.swf # Source SWF file
├── config.toml # SWFRecomp configuration
├── runtime/ # DUPLICATED runtime files
│ ├── native/
│ │ ├── main.c
│ │ ├── runtime.c
│ │ └── include/
│ │ ├── recomp.h
│ │ └── stackvalue.h
│ └── wasm/
│ ├── main.c
│ ├── runtime.c
│ ├── recomp.h
│ ├── stackvalue.h
│ └── index.html
├── RecompiledScripts/ # Generated by SWFRecomp
├── RecompiledTags/ # Generated by SWFRecomp
├── build/ # Build outputs
├── Makefile # DUPLICATED build script
└── build_wasm.sh # DUPLICATED build script
Stays the same across tests:
- Core runtime implementation (
runtime.cstructure) - Type definitions (
recomp.hbasics) - Build process (copy files, compile, link)
- HTML template structure
Varies between tests:
- Number and complexity of ActionScript functions needed
- Variable storage requirements (simple tests don't need variables)
- Graphics rendering support (graphics tests need additional runtime)
- Generated code (SWFRecomp output)
The SWFModernRuntime repository (located at SWFModernRuntime/) contains a production-quality runtime library that is significantly more advanced than the simple runtimes currently duplicated in test directories.
Core Runtime Components:
src/actionmodern/action.c(832 lines) - Complete ActionScript VM implementationsrc/actionmodern/variables.c(209 lines) - Advanced variable storage with hashmap and array optimizationinclude/actionmodern/- Clean, well-designed header filesinclude/libswf/recomp.h- Runtime API definitions
Key Features:
-
Complete ActionScript Implementation
- All standard operators: add, subtract, multiply, divide, equals, less, and, or, not
- String operations: length, concatenation, equality
- Variable management: get/set with proper memory ownership
- Type conversions: string ↔ float ↔ double
- Built-in functions: trace(), getTime()
-
Advanced Variable Storage
- Hashmap-based storage for dynamic variable names
- Array-based optimization for constant string IDs (O(1) lookup)
- Copy-on-Store semantics - Variables own their string data
- Proper memory management - No leaks, proper cleanup
- Ownership tracking - Knows which strings need to be freed
-
Production Quality
- Comprehensive test suite (1,100+ lines in
test_*.cfiles) - Clean architecture with separation of concerns
- Well-documented code
- Already compiled to static library:
build/libSWFModernRuntime.a
- Comprehensive test suite (1,100+ lines in
| Feature | trace_swf_4 Runtime | SWFModernRuntime |
|---|---|---|
| Lines of code | 76 lines | 1,041 lines |
| ActionScript ops | 1 (trace) | 15+ operations |
| Variable storage | None | HashMap + Array |
| Memory management | Stack only | Heap + Stack |
| String handling | Basic | Advanced (ownership, copying) |
| Type conversions | None | Full support |
| Test coverage | None | Comprehensive |
| Build artifact | None | libSWFModernRuntime.a |
Some tests already reference SWFModernRuntime via CMake:
# From SWFRecomp/tests/trace_swf_4/CMakeLists.txt
set(RUNTIME_INCLUDES
${CMAKE_SOURCE_DIR}/../SWFModernRuntime/include
${CMAKE_SOURCE_DIR}/../SWFModernRuntime/include/actionmodern
${CMAKE_SOURCE_DIR}/../SWFModernRuntime/include/libswf
)
target_link_libraries(${PROJECT_NAME} PRIVATE
RecompiledTags
RecompiledScripts
${PROJECT_SOURCE_DIR}/SWFModernRuntime.lib
)However, the WASM test runtimes don't use SWFModernRuntime - they use simplified, duplicated implementations instead.
Current situation:
- WASM tests use minimal, hand-written runtimes
- Missing advanced features (variables, complex operations)
- Each test reimplements basic functionality
Opportunity:
- SWFModernRuntime can be compiled to WASM with Emscripten
- Provides a complete, tested runtime for all tests
- Eliminates the need for test-specific runtime implementations
- Enables more complex SWF files to work in WASM
Option A: Use SWFModernRuntime as-is
- Compile
libSWFModernRuntime.awith Emscripten - Link all WASM builds against it
- Minimal wrapper code needed per test
Option B: Extract needed components
- Create lightweight WASM runtime based on SWFModernRuntime
- Cherry-pick only the ActionScript functions needed
- Smaller WASM file sizes
Option C: Tiered approach
- Simple tests: minimal runtime (trace only)
- Standard tests: SWFModernRuntime core (variables, math)
- Graphics tests: SWFModernRuntime + rendering backend
SWFModernRuntime/include/
├── actionmodern/
│ ├── action.h # ActionScript VM API
│ ├── stackvalue.h # Stack value type definitions
│ └── variables.h # Variable storage API
├── libswf/
│ ├── recomp.h # Main runtime header
│ ├── swf.h # SWF file structures
│ └── tag.h # Tag definitions
├── common.h # Common types (u8, u16, u32, etc.)
└── utils.h # Utility functions
These headers are more complete and better designed than the duplicated headers in test runtimes.
Instead of creating a new shared runtime from scratch, we should:
- Use SWFModernRuntime as the foundation for all WASM builds
- Create thin wrappers for test-specific initialization
- Compile once - all tests share the same runtime library
- Benefit from ongoing improvements to SWFModernRuntime upstream
This approach provides:
- ✅ Production-quality, tested runtime
- ✅ Full ActionScript support out of the box
- ✅ Proper variable storage and memory management
- ✅ Easy maintenance (changes in one place)
- ✅ Compatibility with native builds (already using it)
Leverage the existing, production-quality SWFModernRuntime library for all test builds.
Use SWFModernRuntime as-is with minimal wrappers:
SWFModernRuntime/ # EXISTING: Production runtime
├── src/actionmodern/ # Complete ActionScript VM
│ ├── action.c # All ActionScript operations
│ └── variables.c # Variable storage
├── src/utils.c # Utility functions
├── include/ # Runtime headers
│ ├── actionmodern/
│ │ ├── action.h
│ │ ├── stackvalue.h
│ │ └── variables.h
│ ├── libswf/
│ │ └── recomp.h
│ ├── common.h
│ └── utils.h
└── build/
└── libSWFModernRuntime.a # Pre-compiled library (optional)
SWFRecomp/
├── wasm_wrappers/ # NEW: Minimal WASM glue code
│ ├── main.c # Entry point with Emscripten exports
│ ├── index_template.html # HTML template with {{TEST_NAME}} placeholder
│ └── README.md # Documentation
├── scripts/
│ ├── build_test.sh # Unified build script (native + wasm)
│ ├── deploy_example.sh # Deployment script
│ └── build_all_examples.sh # Batch build script
└── tests/
├── trace_swf_4/
│ ├── test.swf # Test-specific files only
│ ├── config.toml # SWFRecomp configuration
│ ├── RecompiledScripts/ # Generated by SWFRecomp
│ ├── RecompiledTags/ # Generated by SWFRecomp
│ └── build/
│ ├── native/ # Native build output
│ └── wasm/ # WASM build output
└── [other tests]/
SWFRecompDocs/
└── docs/
└── examples/
├── trace_swf_4/ # Deployed WASM (matches test name)
│ ├── trace_swf_4.wasm # WASM binary (matches test name)
│ ├── trace_swf_4.js # JS loader (matches test name)
│ └── index.html # Browser interface
└── [other tests]/
Key changes:
- Use
SWFModernRuntimesource files directly (compile with each test) - Minimal WASM wrappers in
SWFRecomp/wasm_wrappers/(~50 lines) - Tests contain only test-specific files (SWF + config)
- Build scripts compile SWFModernRuntime sources + generated code together
- Naming convention: Test name used throughout (directory, WASM files, deployment)
- ✅ Leverage existing, tested runtime - SWFModernRuntime has 1,000+ lines of production code
- ✅ Full ActionScript support - All operators, variables, type conversions work out of the box
- ✅ Consistency across builds - Native and WASM use the same runtime
- ✅ Easy maintenance - Runtime improvements happen in one place (SWFModernRuntime)
- ✅ Minimal WASM wrapper - Only need ~100 lines of glue code for Emscripten
- ✅ Tests only contain test-specific files - SWF and config.toml
- ✅ Reduced disk usage - Eliminate ~700 lines of duplicated code per test
- ✅ More capable WASM builds - Complex SWFs with variables and math operations work
-
Build SWFModernRuntime with Emscripten
- Compile
SWFModernRuntime/src/actionmodern/*.cto WASM - Create
libSWFModernRuntime.wasm.alibrary - Test that all ActionScript functions work in WASM
- Compile
-
Create WASM wrapper in SWFRecomp
- Create
SWFRecomp/wasm_wrappers/main.cwith Emscripten exports - Create frame execution wrapper that calls generated code
- Create HTML template with test name placeholder
- Create
-
Create unified build script
build_wasm.shthat uses SWFModernRuntime- Compiles SWFModernRuntime source + test-specific generated code
- Links everything into single WASM file
-
Test with existing tests
- Build
trace_swf_4with new system - Build
dyna_string_vars_swf_4with new system - Verify output matches current behavior
- Build
-
Migrate tests
- Remove per-test
runtime/directories - Update documentation
- Enable WASM for all ~50 tests
- Remove per-test
Use a top-level Makefile system with includes and templates.
SWFRecomp/
├── build_templates/
│ ├── common.mk # Common Makefile rules
│ ├── native.mk # Native build rules
│ ├── wasm.mk # WASM build rules
│ └── runtime_files.mk # Runtime file lists
└── tests/
├── trace_swf_4/
│ └── Makefile # Simple: includes templates
└── [other tests]/
└── Makefile
Note: Uses SWFModernRuntime directly (no local runtime/ directory needed)
TEST_NAME = trace_swf_4
SWF_FILE = test.swf
BUILD_WASM = yes
BUILD_NATIVE = yes
include ../../build_templates/common.mk- ✅ Standard GNU Make approach - familiar to most developers
- ✅ Fine-grained control per test
- ✅ Tests can override specific settings
- ✅ Works well with existing CMake for some tests
- ❌ Still requires a Makefile in each test directory
- ❌ More complex than Option 1 for simple cases
- ❌ Make syntax can be difficult to maintain
Create a unified build tool that can build any test.
SWFRecomp/
├── build_tool.py # Main build orchestrator
├── build_config.yaml # Optional: test-specific overrides
└── tests/
├── trace_swf_4/
│ ├── test.swf
│ └── config.toml # SWFRecomp config
└── [other tests]/
Note: Uses SWFModernRuntime directly (no local runtime/ directory needed)
# Build single test for WASM
./build_tool.py --test trace_swf_4 --target wasm
# Build all tests for WASM
./build_tool.py --all --target wasm
# Build and deploy to docs examples
./build_tool.py --test trace_swf_4 --target wasm --deploy ../SWFRecompDocs/docs/examples/- ✅ Most flexible - can handle complex logic
- ✅ Can auto-generate index.html with test name
- ✅ Can batch-build multiple tests
- ✅ Can integrate deployment to docs
- ✅ Easiest to extend with new features
- ✅ Better error messages and validation
- ❌ New dependency (Python 3)
- ❌ More initial development work
- ❌ May be overkill for simple use cases
Key Design Decision: Separate Native and WASM Build Paths
The build system maintains completely separate build paths:
tests/test_name/
└── build/
├── native/ # Native build (gcc/clang)
│ ├── *.o # Object files
│ └── test_name # Executable
└── wasm/ # WASM build (emcc)
├── *.wasm # WebAssembly binary
├── *.js # Emscripten glue code
└── index.html # Browser interface
Why separate paths:
- Different compilers (gcc vs emcc)
- Different output formats (executable vs WASM)
- Different runtime needs (native entry vs Emscripten exports)
- No cross-contamination between builds
- Can maintain both simultaneously
Native build approach options:
Option A - Link against pre-built library (faster, current CMake approach):
- Uses
libSWFModernRuntime.afromSWFModernRuntime/build/ - Faster rebuilds (runtime already compiled)
- Matches current CMake setup
Option B - Compile from source (simpler, unified with WASM):
- Compiles SWFModernRuntime sources each time
- Slower but no library dependency
- Easier for first-time setup
The script below uses Option B for simplicity, but can be modified for Option A.
Create SWFRecomp/scripts/build_test.sh:
#!/bin/bash
# Usage: ./scripts/build_test.sh <test_name> [native|wasm]
# Example: ./scripts/build_test.sh trace_swf_4 wasm
set -e
TEST_NAME=$1
TARGET=${2:-wasm} # Default: wasm
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SWFRECOMP_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
TEST_DIR="${SWFRECOMP_ROOT}/tests/${TEST_NAME}"
BUILD_DIR="${TEST_DIR}/build/${TARGET}"
# Validate inputs
if [ -z "$TEST_NAME" ]; then
echo "Error: Test name required"
echo "Usage: $0 <test_name> [native|wasm]"
exit 1
fi
if [ ! -d "$TEST_DIR" ]; then
echo "Error: Test directory not found: $TEST_DIR"
exit 1
fi
# Run SWFRecomp if needed
if [ ! -d "${TEST_DIR}/RecompiledScripts" ]; then
echo "Running SWFRecomp..."
cd "${TEST_DIR}"
"${SWFRECOMP_ROOT}/build/SWFRecomp" config.toml
fi
# Setup build directory
echo "Setting up build directory..."
mkdir -p "${BUILD_DIR}"
# Setup paths to SWFModernRuntime (sibling directory)
SWFMODERN_ROOT="${SWFRECOMP_ROOT}/../SWFModernRuntime"
SWFMODERN_SRC="${SWFMODERN_ROOT}/src"
SWFMODERN_INC="${SWFMODERN_ROOT}/include"
# Verify SWFModernRuntime exists
if [ ! -d "$SWFMODERN_ROOT" ]; then
echo "Error: SWFModernRuntime not found at: $SWFMODERN_ROOT"
echo "Expected directory structure:"
echo " /path/to/projects/SWFRecomp/"
echo " /path/to/projects/SWFModernRuntime/"
exit 1
fi
# Copy WASM wrapper files
if [ "$TARGET" == "wasm" ]; then
cp "${SWFRECOMP_ROOT}/wasm_wrappers/main.c" "${BUILD_DIR}/"
cp "${SWFRECOMP_ROOT}/wasm_wrappers/index_template.html" "${BUILD_DIR}/index.html"
# Customize HTML with test name
sed -i "s/{{TEST_NAME}}/${TEST_NAME}/g" "${BUILD_DIR}/index.html"
fi
# Copy SWFModernRuntime source files (for both native and WASM)
# Note: For native, could alternatively link against libSWFModernRuntime.a
cp "${SWFMODERN_SRC}/actionmodern/action.c" "${BUILD_DIR}/"
cp "${SWFMODERN_SRC}/actionmodern/variables.c" "${BUILD_DIR}/"
cp "${SWFMODERN_SRC}/utils.c" "${BUILD_DIR}/"
# Copy hashmap library (required for variable storage)
cp "${SWFMODERN_ROOT}/lib/c-hashmap/map.c" "${BUILD_DIR}/"
# Copy generated files from SWFRecomp
cp "${TEST_DIR}/RecompiledScripts"/*.c "${BUILD_DIR}/" 2>/dev/null || true
cp "${TEST_DIR}/RecompiledScripts"/*.h "${BUILD_DIR}/" 2>/dev/null || true
cp "${TEST_DIR}/RecompiledTags"/*.c "${BUILD_DIR}/" 2>/dev/null || true
cp "${TEST_DIR}/RecompiledTags"/*.h "${BUILD_DIR}/" 2>/dev/null || true
# Build
if [ "$TARGET" == "wasm" ]; then
echo "Building WASM..."
# Check if emcc is available
if ! command -v emcc &> /dev/null; then
echo "Error: Emscripten (emcc) not found!"
echo "Run: source ~/tools/emsdk/emsdk_env.sh"
exit 1
fi
cd "${BUILD_DIR}"
emcc \
*.c \
-I. \
-I"${SWFMODERN_INC}" \
-I"${SWFMODERN_INC}/actionmodern" \
-I"${SWFMODERN_INC}/libswf" \
-I"${SWFMODERN_ROOT}/lib/c-hashmap" \
-o "${TEST_NAME}.js" \
-s WASM=1 \
-s EXPORTED_FUNCTIONS='["_main","_runSWF"]' \
-s EXPORTED_RUNTIME_METHODS='["ccall","cwrap"]' \
-s ALLOW_MEMORY_GROWTH=1 \
-s INITIAL_MEMORY=16MB \
-O2
echo ""
echo "✅ WASM build complete!"
echo "Output: ${BUILD_DIR}/${TEST_NAME}.wasm"
echo ""
echo "To test:"
echo " cd ${BUILD_DIR}"
echo " python3 -m http.server 8000"
echo " Open http://localhost:8000/index.html"
else
echo "Building native..."
cd "${BUILD_DIR}"
# Option B: Compile SWFModernRuntime from source (simpler, shown here)
gcc \
*.c \
-I. \
-I"${SWFMODERN_INC}" \
-I"${SWFMODERN_INC}/actionmodern" \
-I"${SWFMODERN_INC}/libswf" \
-I"${SWFMODERN_ROOT}/lib/c-hashmap" \
-Wall \
-Wno-unused-variable \
-std=c17 \
-o "${TEST_NAME}"
# Option A: Link against pre-built library (faster, commented out)
# gcc \
# tagMain.c constants.c draws.c \
# script_0.c script_defs.c \
# main.c \
# -I. \
# -I"${SWFMODERN_INC}" \
# -I"${SWFMODERN_INC}/actionmodern" \
# -I"${SWFMODERN_INC}/libswf" \
# -L"${SWFMODERN_ROOT}/build" \
# -lSWFModernRuntime \
# -Wall -Wno-unused-variable -std=c17 \
# -o "${TEST_NAME}"
echo ""
echo "✅ Native build complete!"
echo "Output: ${BUILD_DIR}/${TEST_NAME}"
echo ""
echo "To run:"
echo " ${BUILD_DIR}/${TEST_NAME}"
fiCreate SWFRecomp/scripts/deploy_example.sh:
#!/bin/bash
# Deploy a test's WASM build to docs examples
# Usage: ./scripts/deploy_example.sh <test_name> [docs_dir]
set -e
TEST_NAME=$1
DOCS_DIR=${2:-../SWFRecompDocs/docs/examples}
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SWFRECOMP_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
BUILD_DIR="${SWFRECOMP_ROOT}/tests/${TEST_NAME}/build/wasm"
DEPLOY_DIR="${DOCS_DIR}/${TEST_NAME}"
# Validate inputs
if [ -z "$TEST_NAME" ]; then
echo "Error: Test name required"
echo "Usage: $0 <test_name> [docs_dir]"
exit 1
fi
if [ ! -d "$BUILD_DIR" ]; then
echo "Error: Build directory not found: $BUILD_DIR"
echo "Run ./scripts/build_test.sh ${TEST_NAME} wasm first"
exit 1
fi
# Create deployment directory
mkdir -p "${DEPLOY_DIR}"
# Copy WASM artifacts
echo "Deploying ${TEST_NAME} to ${DEPLOY_DIR}..."
cp "${BUILD_DIR}"/*.wasm "${DEPLOY_DIR}/" 2>/dev/null || true
cp "${BUILD_DIR}"/*.js "${DEPLOY_DIR}/" 2>/dev/null || true
cp "${BUILD_DIR}"/index.html "${DEPLOY_DIR}/" 2>/dev/null || true
echo "✅ Deployed ${TEST_NAME} to ${DEPLOY_DIR}"
echo ""
echo "Files deployed:"
ls -lh "${DEPLOY_DIR}"Create SWFRecomp/scripts/build_all_examples.sh:
#!/bin/bash
# Build all tests and deploy to docs
# Usage: ./scripts/build_all_examples.sh [docs_dir]
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DOCS_DIR=${1:-../SWFRecompDocs/docs/examples}
# List of tests to build (can be auto-discovered or manually maintained)
TESTS=(
"trace_swf_4"
"dyna_string_vars_swf_4"
# Add more tests here
)
echo "Building ${#TESTS[@]} tests for WASM deployment..."
echo ""
for test_name in "${TESTS[@]}"; do
echo "========================================="
echo "Building: $test_name"
echo "========================================="
# Build
"${SCRIPT_DIR}/build_test.sh" "$test_name" wasm
# Deploy
"${SCRIPT_DIR}/deploy_example.sh" "$test_name" "$DOCS_DIR"
echo ""
done
echo "✅ All tests built and deployed!"
echo "Documentation examples location: $DOCS_DIR"- Create directory:
SWFRecomp/wasm_wrappers/ - Create
main.cwith Emscripten exports (minimal ~50 lines) - Create
index_template.htmlwith{{TEST_NAME}}placeholder - Create
README.mdexplaining the wrapper approach
Estimated effort: 1-2 hours
- Create directory:
SWFRecomp/scripts/ - Create
build_test.shwith the script above - Create
deploy_example.shwith the deployment script - Create
build_all_examples.shwith the batch script - Make them executable:
chmod +x scripts/*.sh - Test with
trace_swf_4:./scripts/build_test.sh trace_swf_4 wasm
- Verify output:
trace_swf_4.wasm,trace_swf_4.js,index.html
Estimated effort: 2-3 hours
- Build
trace_swf_4with new system - Compare output with existing build
- Test in browser - verify functionality matches
- Check that file names match test name (
trace_swf_4.wasm, etc.)
Estimated effort: 1 hour
- Rename
docs/examples/trace-swf-test/→docs/examples/trace_swf_4/ - Rename
trace_swf.wasm→trace_swf_4.wasm - Rename
trace_swf.js→trace_swf_4.js - Update
index.htmlto reference new file names - Update any links in documentation
Estimated effort: 30 minutes
- Once verified, remove
trace_swf_4/runtime/directory - Remove
trace_swf_4/Makefileandtrace_swf_4/build_wasm.sh - Repeat for
dyna_string_vars_swf_4 - Update test READMEs with new build process
Estimated effort: 30 minutes
- Use
deploy_example.shto deploytrace_swf_4 - Test deployment in
SWFRecompDocs/docs/examples/trace_swf_4/ - Test batch build with
build_all_examples.sh - Verify all examples work in browser
Estimated effort: 30 minutes
With the new system in place, enabling WASM for additional tests is trivial:
# Build any test
./scripts/build_test.sh string_add_swf_4 wasm
./scripts/deploy_example.sh string_add_swf_4
# Or batch build
./scripts/build_all_examples.shEstimated effort: 5-10 minutes per test
If the shell scripts become too complex, migrate to Python:
- Create
SWFRecomp/build_tool.py - Add features:
- Better error messages and validation
- Progress reporting for batch builds
- Incremental builds (only rebuild if source changed)
- Integration with
SWFRecompDocsto update example listings - Automated testing of WASM builds
Estimated effort: 8-12 hours
- ❌ ~500 lines of duplicated runtime code per test
- ❌ ~70 lines of duplicated build scripts per test
- ❌ Manual setup required for each new WASM-enabled test
- ❌ Inconsistent runtime implementations
- ❌ Limited ActionScript support (only trace in simple tests)
- ❌ Only 2/~50 tests have WASM support
- ❌ Manual deployment to docs examples
- ✅ Production-quality runtime - 1,000+ lines of tested ActionScript VM code
- ✅ Full ActionScript support - All operators, variables, type conversions
- ✅ Single runtime source - SWFModernRuntime repository
- ✅ Zero runtime code in test directories - Only test-specific files (SWF, config)
- ✅ Minimal WASM wrapper - ~100 lines of Emscripten glue code (shared)
- ✅ One command to build:
./scripts/build_test.sh <name> wasm - ✅ One command to deploy:
./scripts/deploy_example.sh <name> - ✅ Easy to enable WASM for all ~50 tests
- ✅ Automated batch builds and deployment
- ✅ Consistency with native builds - Both use SWFModernRuntime
| Metric | Current | Proposed with SWFModernRuntime | Improvement |
|---|---|---|---|
| Runtime quality | Basic (76 lines) | Production (1,041 lines) | 13x more capable |
| ActionScript ops | 1-3 functions | 15+ functions | Full coverage |
| Lines of code per test | ~650 | ~0 | 100% reduction |
| Time to add WASM to test | ~30 min | ~30 sec | 60x faster |
| Build script maintenance | 50+ files | 3 files | 95% reduction |
| Deployment process | Manual | Automated | - |
| Variable storage | Limited/none | HashMap + Array | Production-ready |
| Memory management | Stack only | Heap + Stack | Proper cleanup |
- Review and approve this proposal
- Choose implementation approach (recommended: Option 1 with shell scripts)
- Allocate time for implementation (estimated 6-8 hours total for basic system)
- Begin with Step 1 (create WASM wrappers directory)
- Test thoroughly before removing old build system
- Document new process in README and reference docs
- Migrate all tests incrementally
- Deploy examples to SWFRecompDocs
- Add automated testing for WASM builds (optional but recommended)
The proposed system fully supports separate native and WASM build paths:
tests/trace_swf_4/
├── test.swf # Source (shared)
├── config.toml # Config (shared)
├── RecompiledScripts/ # Generated code (shared)
├── RecompiledTags/ # Generated code (shared)
└── build/
├── native/ # SEPARATE: Native build
│ ├── trace_swf_4 # Linux/Mac/Windows executable
│ └── *.o # Native object files
└── wasm/ # SEPARATE: WASM build
├── trace_swf_4.wasm # WebAssembly binary
├── trace_swf_4.js # JavaScript loader
└── index.html # Browser interface
# Build native version only
./scripts/build_test.sh trace_swf_4 native
# Build WASM version only
./scripts/build_test.sh trace_swf_4 wasm
# Build both (separate commands)
./scripts/build_test.sh trace_swf_4 native
./scripts/build_test.sh trace_swf_4 wasm| Aspect | Native Build | WASM Build |
|---|---|---|
| Compiler | gcc / clang | emcc (Emscripten) |
| Output | Executable binary | .wasm + .js |
| Runtime | SWFModernRuntime (source or .a) | SWFModernRuntime (compiled to WASM) |
| Entry point | Standard main() | Emscripten-exported functions |
| Build dir | build/native/ |
build/wasm/ |
| Deployment | Local execution | Deploy to docs/examples/ |
- Native and WASM builds are completely independent
- Different source files can be included (e.g., WASM-specific wrappers)
- Different compiler flags and optimizations
- Can delete one build directory without affecting the other
- Can maintain both builds simultaneously
Native builds can use:
- Existing CMake setup (for complex tests)
- New shell script (for simple tests)
- Pre-built
libSWFModernRuntime.alibrary - Or compile SWFModernRuntime from source
WASM builds use:
- New shell script only (Emscripten-based)
- Always compile SWFModernRuntime from source (simpler for cross-platform WASM)
test.swf
↓
[SWFRecomp]
↓
┌──────────┴──────────┐
↓ ↓
RecompiledScripts RecompiledTags
│ │
└──────────┬──────────┘
↓
┌────────────┴────────────┐
↓ ↓
[Native Build] [WASM Build]
build/native/ build/wasm/
↓ ↓
┌──────────────┐ ┌──────────────┐
│ gcc + .a lib │ │ emcc sources │
│ or │ │ compiled │
│ gcc sources │ │ directly │
└──────┬───────┘ └──────┬───────┘
↓ ↓
trace_swf_4 trace_swf_4.wasm
(executable) + trace_swf_4.js
↓ + index.html
↓ ↓
[Run locally] [Deploy to docs]
./trace_swf_4 docs/examples/
Both paths share the same generated code but produce completely different outputs.
-
SWFModernRuntime integration approach: ✅ RESOLVED
- Decision: Compile SWFModernRuntime source files directly with each test (simpler, chosen approach)
- Alternative: Build
libSWFModernRuntime.wasm.aonce and link against it (faster rebuilds, more complex)
-
Naming convention: ✅ RESOLVED & IMPLEMENTED
- Decision: Use
test_name.wasmformat (e.g.,trace_swf_4.wasm) - Completed: Renamed
trace_swf.wasm→trace_swf_4.wasm - Completed: Renamed deployment directory
trace-swf-test/→trace_swf_4/
- Decision: Use
-
HTML templates: ✅ RESOLVED
- Decision: Generic template with
{{TEST_NAME}}placeholder substitution
- Decision: Generic template with
-
CMake integration: ✅ RESOLVED
- Decision: Keep CMake for native builds, use shell scripts for WASM
- Native builds can use either approach (CMake or scripts)
-
Hashmap dependency: ✅ RESOLVED & IMPLEMENTED
- Location:
SWFModernRuntime/lib/c-hashmap/(containsmap.candmap.h) - Implemented: Build script now copies
map.cto build directory - Implemented: Include path added:
-I"${SWFMODERN_ROOT}/lib/c-hashmap" - See lines 522 and 548 in build script
- Location:
-
Testing: ✅ RESOLVED - YES
- Decision: Add automated tests to verify WASM builds work correctly
- Plan: Reuse SWFModernRuntime's test suite for WASM validation where applicable
- Implementation: Add to Step 8 (optional Python build tool with testing features)
-
Documentation deployment: ✅ RESOLVED - YES
- Decision: Build script should auto-update docs example index page
- Plan: Auto-generate example listing with screenshots
- Implementation: Add to Step 8 (optional Python build tool with doc generation)
Current duplication in tests with WASM support:
SWFRecomp/tests/trace_swf_4/runtime/
├── native/
│ ├── main.c (~30 lines)
│ ├── runtime.c (~80 lines)
│ └── include/
│ ├── recomp.h (~150 lines)
│ └── stackvalue.h (~50 lines)
└── wasm/
├── main.c (~30 lines)
├── runtime.c (~80 lines)
├── recomp.h (~150 lines)
├── stackvalue.h (~50 lines)
└── index.html (~80 lines)
Total: ~700 lines duplicated per test with WASM support
With shared runtime, each test would only contain:
SWFRecomp/tests/trace_swf_4/
├── test.swf (80 bytes)
└── config.toml (4 lines)
Total: ~4 lines per test
Code reduction: ~99.4%