Skip to content

Commit 8c20b61

Browse files
committed
Add Supporting ESM
1 parent 892062d commit 8c20b61

6 files changed

Lines changed: 114 additions & 22 deletions

File tree

.github/workflows/publish.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,15 @@ name: Publish Package to NPM
22

33
on:
44
push:
5+
branches:
6+
- main
57
tags:
68
- 'v*'
79

10+
env:
11+
CARGO_TERM_COLOR: always
12+
RUST_BACKTRACE: 1
13+
814
permissions:
915
id-token: write # Required for OIDC
1016
contents: read
@@ -43,7 +49,9 @@ jobs:
4349
run: chmod +x build.sh && ./build.sh
4450

4551
- name: Authenticate with npm
52+
if: startsWith(github.ref, 'refs/tags/v')
4653
run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc
4754

4855
- name: Publish to NPM
56+
if: startsWith(github.ref, 'refs/tags/v')
4957
run: cd pkg && npm publish

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
[package]
22
name = "base64-simd-wasm-vn"
33
description = "Base64 SIMD for WebAssembly"
4-
version = "1.0.0"
4+
version = "1.1.0"
55
edition = "2024"
66
repository = "https://github.com/ndtao2020/base64-simd-wasm-vn"
77
authors = ["Nguyen Dinh Tao <ndtao2020@gmail.com>"]
88
license = "MIT License"
99
readme = "README.md"
1010

1111
[lib]
12+
name = "base64_simd_wasm_vn" # This must match your WASM filename
1213
crate-type = ["cdylib"]
1314

1415
[profile.release]
1516
lto = true
16-
opt-level = "z"
17+
opt-level = "s"
1718
codegen-units = 1
18-
panic = "abort"
1919

2020
[dependencies]
2121
alloc_cat = "1"

build.sh

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ set -e
44

55
PROJECT_NAME="base64_simd_wasm_vn"
66
PKG_DIR="./pkg"
7-
WASM_TARGET="target/wasm32-unknown-unknown/release/${PROJECT_NAME}.wasm"
8-
FLAGS="-C target-feature=+simd128"
7+
TARGET_BUILD="wasm32-unknown-unknown"
8+
WASM_TARGET="target/${TARGET_BUILD}/release/${PROJECT_NAME}.wasm"
9+
FLAGS="-C target-feature=+simd128,+bulk-memory"
910

10-
# RUSTFLAGS='-C target-feature=+simd128' ./build.sh
1111
echo "🔨 Building ${PROJECT_NAME}..."
1212

1313
# Check if wasm-bindgen is installed
@@ -19,11 +19,10 @@ fi
1919
# Clean and create directories
2020
echo "📁 Setting up directories..."
2121
rm -rf "${PKG_DIR}"
22-
mkdir -p "${PKG_DIR}"/{deno,nodejs,bundler,web}
2322

2423
# Build Rust to WASM
2524
echo "🦀 Compiling Rust to WASM..."
26-
RUSTFLAGS="$FLAGS" cargo build --target wasm32-unknown-unknown --release
25+
RUSTFLAGS="$FLAGS" cargo build --target ${TARGET_BUILD} --release
2726

2827
# Check if WASM file was created
2928
if [ ! -f "${WASM_TARGET}" ]; then
@@ -35,17 +34,26 @@ fi
3534
# Generate bindings for different targets
3635
echo "📦 Generating bindings for different targets..."
3736

38-
echo " 🌐 Web target..."
39-
wasm-bindgen --target web --out-dir "${PKG_DIR}/web" "${WASM_TARGET}"
37+
echo " 📦 Bundler target..."
38+
wasm-bindgen --target bundler --out-dir "${PKG_DIR}/bundler" "${WASM_TARGET}"
4039

4140
echo " 🦕 Deno target..."
4241
wasm-bindgen --target deno --out-dir "${PKG_DIR}/deno" "${WASM_TARGET}"
4342

4443
echo " 📟 Node.js target..."
4544
wasm-bindgen --target nodejs --out-dir "${PKG_DIR}/nodejs" "${WASM_TARGET}"
4645

47-
echo " 📦 Bundler target..."
48-
wasm-bindgen --target bundler --out-dir "${PKG_DIR}/bundler" "${WASM_TARGET}"
46+
echo " 📟 Node.js (ESM) target..."
47+
wasm-bindgen --target experimental-nodejs-module --out-dir "${PKG_DIR}/esm" "${WASM_TARGET}"
48+
49+
echo " 📦 Module target..."
50+
wasm-bindgen --target module --out-dir "${PKG_DIR}/module" "${WASM_TARGET}"
51+
52+
echo " 📦 No-modules target..."
53+
wasm-bindgen --target no-modules --out-dir "${PKG_DIR}/no-modules" "${WASM_TARGET}"
54+
55+
echo " 🌐 Web target..."
56+
wasm-bindgen --target web --out-dir "${PKG_DIR}/web" "${WASM_TARGET}"
4957

5058
# Copy package files
5159
echo "📄 Copying package files..."
@@ -59,11 +67,17 @@ echo "*" > "${PKG_DIR}/.gitignore"
5967
# Optimize WASM
6068
echo "⚡ Optimizing WASM..."
6169

70+
WASM_SUFFIX="_bg.wasm"
71+
WASM_OTPS="-Os --converge --enable-bulk-memory --inline-functions-with-loops"
72+
6273
if command -v wasm-opt &> /dev/null; then
63-
wasm-opt -Oz --enable-bulk-memory "${PKG_DIR}/web/${PROJECT_NAME}_bg.wasm" -o "${PKG_DIR}/web/${PROJECT_NAME}_bg.wasm"
64-
wasm-opt -Oz --enable-bulk-memory "${PKG_DIR}/deno/${PROJECT_NAME}_bg.wasm" -o "${PKG_DIR}/deno/${PROJECT_NAME}_bg.wasm"
65-
wasm-opt -Oz --enable-bulk-memory "${PKG_DIR}/nodejs/${PROJECT_NAME}_bg.wasm" -o "${PKG_DIR}/nodejs/${PROJECT_NAME}_bg.wasm"
66-
wasm-opt -Oz --enable-bulk-memory "${PKG_DIR}/bundler/${PROJECT_NAME}_bg.wasm" -o "${PKG_DIR}/bundler/${PROJECT_NAME}_bg.wasm"
74+
wasm-opt ${WASM_OTPS} "${PKG_DIR}/bundler/${PROJECT_NAME}${WASM_SUFFIX}" -o "${PKG_DIR}/bundler/${PROJECT_NAME}${WASM_SUFFIX}"
75+
wasm-opt ${WASM_OTPS} "${PKG_DIR}/deno/${PROJECT_NAME}${WASM_SUFFIX}" -o "${PKG_DIR}/deno/${PROJECT_NAME}${WASM_SUFFIX}"
76+
wasm-opt ${WASM_OTPS} "${PKG_DIR}/esm/${PROJECT_NAME}${WASM_SUFFIX}" -o "${PKG_DIR}/esm/${PROJECT_NAME}${WASM_SUFFIX}"
77+
wasm-opt ${WASM_OTPS} "${PKG_DIR}/module/${PROJECT_NAME}${WASM_SUFFIX}" -o "${PKG_DIR}/module/${PROJECT_NAME}${WASM_SUFFIX}"
78+
wasm-opt ${WASM_OTPS} "${PKG_DIR}/no-modules/${PROJECT_NAME}${WASM_SUFFIX}" -o "${PKG_DIR}/no-modules/${PROJECT_NAME}${WASM_SUFFIX}"
79+
wasm-opt ${WASM_OTPS} "${PKG_DIR}/nodejs/${PROJECT_NAME}${WASM_SUFFIX}" -o "${PKG_DIR}/nodejs/${PROJECT_NAME}${WASM_SUFFIX}"
80+
wasm-opt ${WASM_OTPS} "${PKG_DIR}/web/${PROJECT_NAME}${WASM_SUFFIX}" -o "${PKG_DIR}/web/${PROJECT_NAME}${WASM_SUFFIX}"
6781
echo "✅ WASM optimized with bulk memory"
6882
else
6983
echo "⚠️ wasm-opt not found, skipping optimization"
@@ -72,10 +86,10 @@ fi
7286

7387
# Verify outputs
7488
echo "🔍 Verifying outputs..."
75-
for target in "/web" "/deno" "/nodejs" "/bundler"; do
76-
if [ -f "${PKG_DIR}${target}/${PROJECT_NAME}_bg.wasm" ]; then
77-
wasm_size=$(stat -f%z "${PKG_DIR}${target}/${PROJECT_NAME}_bg.wasm" 2>/dev/null || stat -c%s "${PKG_DIR}${target}/${PROJECT_NAME}_bg.wasm")
78-
echo "${target:- /web}: ${wasm_size} bytes"
89+
for target in "/bundler" "/deno" "/esm" "/module" "/no-modules" "/nodejs" "/web"; do
90+
if [ -f "${PKG_DIR}${target}/${PROJECT_NAME}${WASM_SUFFIX}" ]; then
91+
wasm_size=$(stat -f%z "${PKG_DIR}${target}/${PROJECT_NAME}${WASM_SUFFIX}" 2>/dev/null || stat -c%s "${PKG_DIR}${target}/${PROJECT_NAME}${WASM_SUFFIX}")
92+
echo "${target}: ${wasm_size} bytes"
7993
else
8094
echo "${target}: WASM file missing"
8195
fi

package.json

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"ndtao2020"
66
],
77
"description": "Base64 SIMD for WebAssembly",
8-
"version": "1.0.0",
8+
"version": "1.1.0",
99
"license": "MIT License",
1010
"repository": {
1111
"type": "git",
@@ -14,6 +14,9 @@
1414
"files": [
1515
"web/",
1616
"deno/",
17+
"esm/",
18+
"module/",
19+
"no-modules/",
1720
"nodejs/",
1821
"bundler/"
1922
],
@@ -33,6 +36,21 @@
3336
"require": "./deno/base64_simd_wasm_vn.js",
3437
"import": "./deno/base64_simd_wasm_vn.js"
3538
},
39+
"./esm": {
40+
"types": "./esm/base64_simd_wasm_vn.d.ts",
41+
"require": "./esm/base64_simd_wasm_vn.js",
42+
"import": "./esm/base64_simd_wasm_vn.js"
43+
},
44+
"./module": {
45+
"types": "./module/base64_simd_wasm_vn.d.ts",
46+
"require": "./module/base64_simd_wasm_vn.js",
47+
"import": "./module/base64_simd_wasm_vn.js"
48+
},
49+
"./no-modules": {
50+
"types": "./no-modules/base64_simd_wasm_vn.d.ts",
51+
"require": "./no-modules/base64_simd_wasm_vn.js",
52+
"import": "./no-modules/base64_simd_wasm_vn.js"
53+
},
3654
"./nodejs": {
3755
"types": "./nodejs/base64_simd_wasm_vn.d.ts",
3856
"require": "./nodejs/base64_simd_wasm_vn.js",

src/lib.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,58 @@ pub fn decode_url_no_pad(str: &str) -> Result<Vec<u8>, JsValue> {
5252
.map_err(|e| JsValue::from_str(&e.to_string()))
5353
}
5454

55+
#[wasm_bindgen]
56+
pub struct Base64 {}
57+
58+
#[wasm_bindgen]
59+
impl Base64 {
60+
#[wasm_bindgen(js_name = encode)]
61+
pub fn encode(data: &[u8]) -> String {
62+
encode(data)
63+
}
64+
65+
#[wasm_bindgen(js_name = decode)]
66+
pub fn decode(str: &str) -> Result<Vec<u8>, JsValue> {
67+
decode(str)
68+
}
69+
70+
#[wasm_bindgen(js_name = encodeNoPad)]
71+
pub fn encode_no_pad(data: &[u8]) -> String {
72+
encode_no_pad(data)
73+
}
74+
75+
#[wasm_bindgen(js_name = decodeNoPad)]
76+
pub fn decode_no_pad(str: &str) -> Result<Vec<u8>, JsValue> {
77+
decode_no_pad(str)
78+
}
79+
}
80+
81+
#[wasm_bindgen]
82+
pub struct Base64Url {}
83+
84+
#[wasm_bindgen]
85+
impl Base64Url {
86+
#[wasm_bindgen(js_name = encode)]
87+
pub fn encode(data: &[u8]) -> String {
88+
encode_url(data)
89+
}
90+
91+
#[wasm_bindgen(js_name = decode)]
92+
pub fn decode(str: &str) -> Result<Vec<u8>, JsValue> {
93+
decode_url(str)
94+
}
95+
96+
#[wasm_bindgen(js_name = encodeNoPad)]
97+
pub fn encode_no_pad(data: &[u8]) -> String {
98+
encode_url_no_pad(data)
99+
}
100+
101+
#[wasm_bindgen(js_name = decodeNoPad)]
102+
pub fn decode_no_pad(str: &str) -> Result<Vec<u8>, JsValue> {
103+
decode_url_no_pad(str)
104+
}
105+
}
106+
55107
#[cfg(test)]
56108
mod tests {
57109
use super::*;

0 commit comments

Comments
 (0)