



WithCodeMedia-1-pc
WithCodeMedia-2-pc
WithCodeMedia-3-pc
WithCodeMedia-4-pc




WithCodeMedia-1-sp
WithCodeMedia-2-sp
WithCodeMedia-3-sp
WithCodeMedia-4-sp








生徒WebAssemblyをJavaScriptから使いたいんですが、数値は渡せても文字列や配列の渡し方が分からなくて詰まっています……



WebAssemblyとJavaScript間のデータやりとりにはいくつかのパターンがあるんじゃ!プリミティブ型は直接渡せるが、文字列や複雑なオブジェクトはメモリ(ArrayBuffer)を通じて渡す必要があるんじゃ。wasm-bindgenを使えばRustで書いたWasmはこの複雑さを抽象化してくれる!さらにSharedArrayBufferで「ゼロコピー共有」も実現できるし、JSのコールバックをWasmに渡す方法も解説するぞ!
WebAssemblyの基本は分かったものの、「文字列や配列・オブジェクトをどうやってJavaScriptとWasm間でやりとりするか」で詰まることが多いです。WasmはJavaScriptのValueオブジェクトを直接扱えず、メモリ(線形メモリ)を通じてデータを渡す必要があります。
本記事では、Wasm-JavaScript間のデータ受け渡しの基本原則・線形メモリモデルの詳細・プリミティブ型・文字列(TextEncoder/Decoder手動実装)・wasm-bindgenによる自動変換・serde-wasm-bindgenによる構造化データ・SharedArrayBufferゼロコピー共有・JSコールバックのWasmへの渡し方・C++(Emscripten)アプローチ・メモリ管理とリーク防止・TypeScript型の自動生成を完全解説します。


>【WebAssemblyとJavaScript間のデータ受け渡しの基本原則】
✅ 直接渡せるもの(プリミティブ型):
→ 整数(i32, i64):JavaScriptの number と直接やりとり可能
→ 浮動小数点(f32, f64):JavaScriptの number と直接やりとり可能
→ bigint (i64 の大きな値):JavaScriptの BigInt と対応
❌ 直接渡せないもの(参照型):
→ 文字列(string)
→ 配列(Array, TypedArray の高レベルAPI)
→ オブジェクト({ key: value })
→ これらは「WebAssembly.Memory(線形メモリ)を通じた間接的な渡し方」が必要
【データ受け渡しの3つの手段】
1. エクスポート関数の引数/戻り値(数値のみ直接)
2. WebAssembly.Memory(共有線形メモリ)を介したバッファ渡し
3. wasm-bindgen(Rust)/ Emscripten(C/C++): 複雑な型を自動変換
【Wasmの線形メモリとは】
→ Wasmモジュールは「線形メモリ」という連続したバイト配列を持つ
→ JavaScriptからは ArrayBuffer としてアクセス可能
→ Uint8Array, Int32Array 等のTypedArrayで読み書きできる
→ 初期サイズは page(64KB)単位で指定、memory.grow() で拡張可能
>// WebAssembly.Memory の基本操作
const memory = new WebAssembly.Memory({
initial: 1, // 1 page = 64KB
maximum: 100, // 最大100 page = 6.4MB
shared: false, // trueにするとSharedArrayBufferになる
})
// JavaScript側でメモリにアクセス
const buffer = memory.buffer // ArrayBuffer
const view = new Uint8Array(buffer) // バイト単位で読み書き
const int32View = new Int32Array(buffer) // 4バイト整数として読み書き
// メモリにデータを書き込む
view[0] = 72 // 'H'
view[1] = 101 // 'e'
view[2] = 108 // 'l'
view[3] = 108 // 'l'
view[4] = 111 // 'o'
// メモリを拡張する
const prevPages = memory.grow(1) // 1ページ(64KB)拡張
// grow()後は buffer が新しいArrayBufferになるため再取得が必要
>// Rust で数値関数を定義してJSから呼び出す例
// src/lib.rs
use wasm_bindgen::prelude::*;
// i32(32ビット整数)
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
// f64(64ビット浮動小数点)
#[wasm_bindgen]
pub fn square(x: f64) -> f64 {
x * x
}
// bool(i32の0/1として変換)
#[wasm_bindgen]
pub fn is_even(n: i32) -> bool {
n % 2 == 0
}
// 複数の数値を処理
#[wasm_bindgen]
pub fn calculate_stats(values: &[f64]) -> f64 {
if values.is_empty() { return 0.0; }
values.iter().sum::() / values.len() as f64 // 平均値
}
// i64 と BigInt(JavaScript側でBigIntを使う必要がある)
#[wasm_bindgen]
pub fn factorial(n: u32) -> u64 {
(1..=n as u64).product()
}
>// JavaScript 側
import init, { add, square, is_even, calculate_stats, factorial } from './pkg/my_wasm.js'
await init()
console.log(add(3, 4)) // → 7
console.log(square(2.5)) // → 6.25
console.log(is_even(42)) // → true
console.log(calculate_stats([1, 2, 3, 4, 5])) // → 3(平均値)
// i64はBigIntとして返ってくる
const result = factorial(20)
console.log(result) // → 2432902008176640000n(BigInt)
>// Rust + wasm-bindgen: &str を直接受け取れる(wasm-bindgenが変換を行う)
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
format!("こんにちは、{}さん!", name)
}
#[wasm_bindgen]
pub fn reverse_string(s: &str) -> String {
s.chars().rev().collect()
}
// 文字列の配列を受け取る(wasm-bindgenがjs_sys::Array経由で変換)
#[wasm_bindgen]
pub fn join_strings(separator: &str, parts: js_sys::Array) -> String {
let strs: Vec = parts
.iter()
.filter_map(|v| v.as_string())
.collect();
strs.join(separator)
}
>// JavaScript 側 - wasm-bindgenが文字列変換を自動で行う
import init, { greet, reverse_string, join_strings } from './pkg/my_wasm.js'
await init()
const message = greet('田中')
console.log(message) // → "こんにちは、田中さん!"
const reversed = reverse_string('Hello, World!')
console.log(reversed) // → "!dlroW ,olleH"
// wasm-bindgenの内部処理(透過的に行われる):
// 1. JSのstring → TextEncoder でUTF-8バイト列に変換
// 2. Wasmのメモリ(alloc確保)に書き込む
// 3. ポインタと長さをWasm関数に渡す
// 4. Wasm関数が戻り値のポインタと長さを返す
// 5. JSがメモリからUTF-8デコードしてstringに変換
// 6. Wasmのメモリを解放
>// WebAssembly.instantiate でWasmを直接読み込む場合
const wasmModule = await WebAssembly.instantiateStreaming(
fetch('./module.wasm'),
{
env: {
abort: () => console.error('Wasm abort called'),
}
}
)
const { instance } = wasmModule
const wasmMemory = new Uint8Array(instance.exports.memory.buffer)
// ===== JSからWasmへ文字列を渡す =====
function writeStringToWasm(str, ptr) {
const encoder = new TextEncoder()
const bytes = encoder.encode(str) // UTF-8エンコード
wasmMemory.set(bytes, ptr)
wasmMemory[ptr + bytes.length] = 0 // null終端(Cスタイル文字列)
return bytes.length
}
// ===== Wasmのメモリから文字列を読み取る =====
function readStringFromWasm(ptr) {
// null終端まで読み進める
let end = ptr
while (wasmMemory[end] !== 0) end++
const slice = wasmMemory.slice(ptr, end)
return new TextDecoder('utf-8').decode(slice)
}
// 使い方例
const inputPtr = instance.exports.alloc(100) // 100バイト確保
const byteLen = writeStringToWasm('Hello, Wasm!', inputPtr)
const outputPtr = instance.exports.process_string(inputPtr, byteLen)
const result = readStringFromWasm(outputPtr)
console.log(result)
instance.exports.dealloc(inputPtr, 100) // メモリ解放(重要!)
>// Rust: Vec / &[u8] を受け取ってバイト操作
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn process_bytes(data: &[u8]) -> Vec {
// バイト列を逆順にする例
data.iter().rev().cloned().collect()
}
// 画像処理(グレースケール変換)
#[wasm_bindgen]
pub fn grayscale(rgba_data: &[u8]) -> Vec {
let mut output = rgba_data.to_vec()
// RGBA形式: 4バイトごとにRGBAが並ぶ
for chunk in output.chunks_mut(4) {
let r = chunk[0] as f64
let g = chunk[1] as f64
let b = chunk[2] as f64
// 輝度の重み付け平均(標準的な変換式)
let gray = (0.299 * r + 0.587 * g + 0.114 * b) as u8
chunk[0] = gray
chunk[1] = gray
chunk[2] = gray
// chunk[3]はα値なのでそのまま
}
output
}
>// JavaScript 側 - Uint8Array で受け渡し
import init, { process_bytes, grayscale } from './pkg/my_wasm.js'
await init()
// バイト配列の処理
const input = new Uint8Array([1, 2, 3, 4, 5])
const reversed = process_bytes(input)
console.log(Array.from(reversed)) // → [5, 4, 3, 2, 1]
// Canvas の ImageData をWasmで処理
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
// 画像を Canvas に描画
const img = document.getElementById('source-image')
ctx.drawImage(img, 0, 0)
// ImageData を取得してWasmに渡す
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
// Uint8Array として wasm-bindgen に渡す
const processed = grayscale(imageData.data)
// 処理結果を Canvas に戻す
const outputImageData = new ImageData(processed, canvas.width, canvas.height)
ctx.putImageData(outputImageData, 0, 0)
// パフォーマンス比較
const start = performance.now()
// Wasmで処理(典型的に3〜10倍高速)
const wasmResult = grayscale(imageData.data)
console.log(`Wasm: ${performance.now() - start}ms`)
>// Cargo.toml の依存関係
[dependencies]
wasm-bindgen = "0.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde-wasm-bindgen = "0.6" # 高速なシリアライズ
>// Rust - JSON文字列として受け渡し
use wasm_bindgen::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct User {
pub id: u32,
pub name: String,
pub email: String,
pub scores: Vec,
}
#[derive(Serialize, Deserialize)]
pub struct UserStats {
pub name: String,
pub average_score: f64,
pub max_score: f64,
pub grade: String,
}
#[wasm_bindgen]
pub fn analyze_user(json: &str) -> String {
let user: User = match serde_json::from_str(json) {
Ok(u) => u,
Err(e) => return format!("{{\"error\": \"{}\"}}", e),
};
let avg = if user.scores.is_empty() {
0.0
} else {
user.scores.iter().sum::() / user.scores.len() as f64
};
let max = user.scores.iter().cloned().fold(f64::NEG_INFINITY, f64::max);
let grade = match avg as u32 {
90..=100 => "S",
80..=89 => "A",
70..=79 => "B",
60..=69 => "C",
_ => "D",
};
let stats = UserStats {
name: user.name,
average_score: avg,
max_score: max,
grade: grade.to_string(),
};
serde_json::to_string(&stats).unwrap()
}
>// JavaScript 側 - JSON経由
import init, { analyze_user } from './pkg/my_wasm.js'
await init()
const user = {
id: 1,
name: '山田太郎',
email: 'yamada@example.com',
scores: [85, 92, 78, 95, 88],
}
const resultJson = analyze_user(JSON.stringify(user))
const stats = JSON.parse(resultJson)
console.log(stats)
// → { name: "山田太郎", average_score: 87.6, max_score: 95, grade: "A" }
>// Rust - serde-wasm-bindgen使用(JSON変換オーバーヘッドなし)
use wasm_bindgen::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct AnalysisResult {
pub total: f64,
pub mean: f64,
pub std_dev: f64,
pub percentile_90: f64,
}
#[wasm_bindgen]
pub fn analyze_data(data: JsValue) -> Result {
// JsValue → Rust型に変換(serde-wasm-bindgen)
let numbers: Vec = serde_wasm_bindgen::from_value(data)
.map_err(|e| JsValue::from_str(&e.to_string()))?;
let n = numbers.len() as f64;
let total: f64 = numbers.iter().sum();
let mean = total / n;
let variance = numbers.iter()
.map(|x| (x - mean).powi(2))
.sum::() / n;
let std_dev = variance.sqrt();
let mut sorted = numbers.clone();
sorted.sort_by(|a, b| a.partial_cmp(b).unwrap());
let p90_idx = (n * 0.9) as usize;
let percentile_90 = sorted[p90_idx.min(sorted.len() - 1)];
let result = AnalysisResult { total, mean, std_dev, percentile_90 };
// Rust型 → JsValue に変換(serde-wasm-bindgen)
serde_wasm_bindgen::to_value(&result)
.map_err(|e| JsValue::from_str(&e.to_string()))
}
// JavaScript 側
// const data = [1, 5, 3, 8, 2, 9, 4, 7, 6]
// const result = analyze_data(data)
// → { total: 45, mean: 5, std_dev: ..., percentile_90: ... }
>// SharedArrayBuffer を使ったゼロコピー共有
// 注意: COOP/COEP ヘッダーが必要(cross-origin isolation)
// JavaScriptとWasmがSharedArrayBufferを共有してコピーなしでアクセス
// まず SharedArrayBuffer 対応のメモリでWasmを初期化
const memory = new WebAssembly.Memory({
initial: 10, // 640KB
maximum: 100, // 6.4MB
shared: true, // SharedArrayBuffer を使用
})
const wasmModule = await WebAssembly.instantiateStreaming(
fetch('./wasm_module.wasm'),
{ env: { memory } }
)
const { instance } = wasmModule
// 共有メモリ(Int32Array)の作成
const sharedArray = new Int32Array(memory.buffer)
// 大量データをゼロコピーでWasmに渡す
const dataOffset = 0
const dataLength = 1000000 // 100万要素
// データを書き込む(コピーなし、直接書き込み)
for (let i = 0; i < dataLength; i++) {
sharedArray[dataOffset + i] = Math.random() * 1000 | 0
}
// Wasmで処理(データのコピーは発生しない)
const sum = instance.exports.sum_array(dataOffset, dataLength)
console.log('合計:', sum)
// Web Worker との連携でメインスレッドをブロックしない
const worker = new Worker('./wasm_worker.js')
worker.postMessage({ memory, dataOffset, dataLength })
worker.onmessage = (e) => {
console.log('処理完了:', e.data.result)
}
>// Rust + wasm-bindgen: JSの関数をコールバックとして受け取る
use wasm_bindgen::prelude::*;
use js_sys::Function;
// JS関数をコールバックとして受け取る
#[wasm_bindgen]
pub fn process_with_callback(
data: &[i32],
callback: &Function, // JSの関数
) {
for (i, &value) in data.iter().enumerate() {
let this = JsValue::null()
let result = JsValue::from(value * 2)
let index = JsValue::from(i as u32)
// JSのコールバックを呼び出す
callback.call2(&this, &result, &index).unwrap()
}
}
// 進捗コールバックつきの重い処理
#[wasm_bindgen]
pub fn heavy_computation(
n: u32,
on_progress: Option, // オプショナルなコールバック
) -> f64 {
let mut result = 0.0
for i in 0..n {
// 重い計算...
result += (i as f64).sqrt()
// 100回に1回プログレス報告
if i % (n / 100) == 0 {
if let Some(ref cb) = on_progress {
let progress = JsValue::from((i as f64 / n as f64) * 100.0)
let _ = cb.call1(&JsValue::null(), &progress)
}
}
}
result
}
>// JavaScript 側 - コールバック関数を渡す
import init, { process_with_callback, heavy_computation } from './pkg/my_wasm.js'
await init()
// コールバックを渡す
const results = []
process_with_callback(
new Int32Array([1, 2, 3, 4, 5]),
(doubled, index) => {
results.push({ index, doubled })
console.log(`index=${index}: ${doubled}`)
}
)
console.log(results)
// → [{ index: 0, doubled: 2 }, { index: 1, doubled: 4 }, ...]
// 進捗コールバック付きの重い計算
const progressBar = document.getElementById('progress')
const result = heavy_computation(1_000_000, (progress) => {
progressBar.style.width = `${progress}%`
progressBar.textContent = `${progress.toFixed(0)}%`
})
console.log('計算結果:', result)
>// C++ のコードを Emscripten でWasmにコンパイル
// module.cpp
#include
#include
#include
#include
// 文字列を受け取る関数
std::string greet(const std::string& name) {
return "Hello, " + name + "!";
}
// ベクターを受け取る関数
float calculate_average(const std::vector& values) {
if (values.empty()) return 0.0f;
float sum = 0;
for (float v : values) sum += v;
return sum / values.size();
}
// embind でJSにバインディングを生成
EMSCRIPTEN_BINDINGS(my_module) {
emscripten::function("greet", &greet);
emscripten::function("calculate_average", &calculate_average);
emscripten::register_vector("FloatVector");
}
// コンパイルコマンド
// emcc module.cpp -o module.js \
// -lembind \
// -s WASM=1 \
// -s EXPORTED_RUNTIME_METHODS='["ccall","cwrap"]' \
// -s ALLOW_MEMORY_GROWTH=1
>// Emscripten で生成されたJSモジュールを使う
import Module from './module.js'
const instance = await Module()
// 文字列を渡す(embind が自動変換)
const greeting = instance.greet('World')
console.log(greeting) // → "Hello, World!"
// FloatVector(C++のvector)を使う
const vec = new instance.FloatVector()
vec.push_back(1.5)
vec.push_back(2.5)
vec.push_back(3.5)
const avg = instance.calculate_average(vec)
console.log(avg) // → 2.5
// メモリ解放(重要!)
vec.delete()
// ccall/cwrap を使う低レベルな方法
const add = instance.cwrap('add', 'number', ['number', 'number'])
console.log(add(3, 4)) // → 7
>// Rust + wasm-bindgen: 所有権とメモリ管理
// wasm-bindgenを使うと Rust の所有権システムにより
// メモリ管理は自動化される(ガベージコレクション不要)
// → VecはWasm内で生成・破棄される(自動)
// ただし、Rustで#[wasm_bindgen]を付けたstructは注意が必要
#[wasm_bindgen]
pub struct DataProcessor {
data: Vec,
result: Option,
}
#[wasm_bindgen]
impl DataProcessor {
// コンストラクター
#[wasm_bindgen(constructor)]
pub fn new() -> Self {
DataProcessor { data: Vec::new(), result: None }
}
pub fn add_data(&mut self, value: f64) {
self.data.push(value)
}
pub fn compute(&mut self) -> f64 {
let mean = self.data.iter().sum::() / self.data.len() as f64;
self.result = Some(mean);
mean
}
// 明示的なクリーンアップ(free()メソッド)
pub fn clear(&mut self) {
self.data.clear();
self.result = None;
}
}
// JavaScript 側 - WasmのStructを使う場合はfree()を呼ぶ必要がある
import init, { DataProcessor } from './pkg/my_wasm.js'
await init()
const processor = new DataProcessor()
try {
processor.add_data(1.5)
processor.add_data(2.5)
processor.add_data(3.5)
const mean = processor.compute()
console.log('平均:', mean) // → 2.5
} finally {
// Wasmのメモリを解放(重要!)
// wasm-bindgenが生成するstructはfree()が必要
processor.free()
}
// ===== 一般的なメモリリーク防止パターン =====
// 1. wasm-bindgenのstructは必ず .free() を呼ぶ
// 2. Emscriptenのvectorは必ず .delete() を呼ぶ
// 3. 手動メモリ管理の場合は alloc/dealloc を対で使う
// 4. 重い処理はWeb Workerで実行(メインスレッドのメモリ節約)
>// wasm-bindgenはTypeScriptの型定義(.d.ts)を自動生成する
// wasm-pack ビルド後に生成される my_wasm.d.ts(例)
/* tslint:disable */
/* eslint-disable */
/**
* WASMモジュール初期化
* @param {RequestInfo | URL | BufferSource | WebAssembly.Module} input
*/
export default function init(input?: RequestInfo | URL | BufferSource | WebAssembly.Module): Promise
export interface InitOutput {
readonly memory: WebAssembly.Memory
readonly add: (a: number, b: number) => number
readonly square: (a: number) => number
readonly greet: (a: number, b: number) => [number, number]
readonly process_bytes: (a: number, b: number) => [number, number, number]
readonly analyze_user: (a: number, b: number) => [number, number]
readonly __wbg_dataprocessor_free: (a: number, b: number) => void
readonly dataprocessor_new: () => number
readonly dataprocessor_add_data: (a: number, b: number) => void
readonly dataprocessor_compute: (a: number) => number
// ...その他のエクスポート
}
// 型安全なインポートと使用
import init, { add, square, greet, DataProcessor } from './pkg/my_wasm'
// 型補完が効く!
const result: number = add(3, 4)
const msg: string = greet('World')
const processor = new DataProcessor()
processor.add_data(1.5) // TypeScriptが引数の型をチェック
const mean: number = processor.compute()
processor.free()
>// データ受け渡しのパフォーマンスオーバーヘッドを計測
// 各方法のオーバーヘッド比較
const N = 1000000 // 100万要素
// ===== 方法1: プリミティブ(最速)=====
const start1 = performance.now()
for (let i = 0; i < 1000; i++) {
wasmAdd(i, i + 1) // 数値のみ: ほぼゼロオーバーヘッド
}
console.log(`プリミティブ: ${performance.now() - start1}ms`)
// ===== 方法2: TypedArray(ほぼ無コスト)=====
const data = new Float64Array(N)
data.fill(1.5)
const start2 = performance.now()
const result = wasmProcessArray(data) // Uint8Arrayへの参照渡し: 高速
console.log(`TypedArray: ${performance.now() - start2}ms`)
// ===== 方法3: JSON変換(最もオーバーヘッドあり)=====
const obj = { values: Array.from({ length: 1000 }, (_, i) => i) }
const start3 = performance.now()
for (let i = 0; i < 100; i++) {
const json = JSON.stringify(obj) // シリアライズオーバーヘッド
wasmProcessJson(json)
JSON.parse(wasmGetResult()) // デシリアライズオーバーヘッド
}
console.log(`JSON経由: ${performance.now() - start3}ms`)
// 最適化のヒント:
// 1. 大量データは TypedArray (Uint8Array/Float64Array) で渡す
// 2. 頻繁に呼び出す関数はオブジェクトをWasm側で保持(DataProcessor パターン)
// 3. SharedArrayBuffer でコピーを完全に排除
// 4. 小さなデータは JSON でも問題なし(1KB以下)
直接はできません。WasmはDOM APIを直接呼び出す機能を持っていません。wasm-bindgenを使うと、JavaScriptのDOM操作関数をWasmにインポートして、Rustのコードからindirect的にDOMを操作できます。web_sysクレートを使うとdocument.getElementById()やelement.set_inner_html()などのDOM操作をRustから呼び出せます。ただし頻繁なDOM操作はJSとの境界コストがかかるため、計算処理はWasm・UI更新はJSという分担が効率的です。
wasm-bindgenはRustのコードとJavaScript間の型変換・バインディング生成を行うライブラリです。wasm-packはwasm-bindgenを活用してWasmプロジェクト全体のビルド・テスト・パッケージング(npm公開)を行うCLIツールです。実際の開発ではwasm-pack buildコマンドでビルドすると、wasm-bindgenのバインディング生成・TypeScript型定義の出力・npm用のpackage.json生成まで一括で行われます。
数値のプリミティブ型はほぼゼロオーバーヘッドです。文字列はUTF-8エンコード・デコードとメモリコピーが発生するため、短い文字列(数十バイト)で数マイクロ秒程度のオーバーヘッドがあります。大きなTypedArray(数MB)は参照渡しで高速ですが、wasm-bindgenを通じると内部でコピーが発生することがあります。パフォーマンスが最重要な場合はSharedArrayBufferを使ったゼロコピー共有が最も効率的です。
SharedArrayBufferを使用するにはCross-Origin Isolation(クロスオリジン分離)が必要です。サーバーから以下のHTTPヘッダーを送信してください。
Cross-Origin-Opener-Policy: same-originCross-Origin-Embedder-Policy: require-corpこれらのヘッダーが設定されていないとSharedArrayBuffer is not definedエラーが発生します。Vercelではvercel.jsonのheaders設定で追加できます。
Wasmのヒープメモリがリークします。JavaScriptのガベージコレクターはEmscriptenが管理するWasmヒープを追跡できないため、vec.delete()を呼び出さないと使用済みメモリが解放されません。長時間動作するアプリケーションではメモリ使用量が増加し続け、最終的にクラッシュする可能性があります。必ずtry/finallyブロックでdelete()を確実に呼び出すパターンを使用してください。
WebAssemblyとJavaScriptのデータ受け渡しは「メモリを介した間接的なやりとり」が基本です。wasm-bindgenを使えばこの複雑さがほぼ隠蔽されるため、Rustでの実装から始めることを強く推奨します。特に画像処理・音声解析・暗号化処理のように大量バイナリデータを扱う処理では、TypedArrayを使った高速な受け渡しを活用することでJavaScript単体の3〜10倍の処理速度が達成できます。
公式サイト より
今すぐ
無料カウンセリング
を予約!