申し訳ありませんが、翻訳すべきテキストが提供されていないようです。お手元の文章を共有いただければ、喜んで日本語に翻訳いたします。

2026/03/08 18:24

申し訳ありませんが、翻訳すべきテキストが提供されていないようです。お手元の文章を共有いただければ、喜んで日本語に翻訳いたします。

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

概要:
本文書は、Rust と WebAssembly の間で安全にデータを交換しつつ、API を明確かつ堅牢に保つためのベストプラクティスガイドラインをまとめたものです。

  1. Wasm 境界を越える際には値を参照(
    &
    )で渡し、必要がない限りエクスポートされた値を消費しないようにします。薄いエクスポートラッパーに
    Copy
    を派生させることは決して行わず、純粋なデータを
    IntoWasmAbi
    で包んだ場合のみ許可します。
  2. IntoWasmAbi
    に該当しない型については、ハンドルを安全に保ち、排他性が保証できないときに変更可能にするために
    Rc<RefCell<T>>
    Arc<Mutex<T>>
    といった内部可変性ラッパーを使用します。
  3. Rust がエクスポートする型には
    Wasm*
    (例:
    WasmFoo
    )というプレフィックスを付け、
    js_name/js_class
    をプレフィックスなしの名前に設定します。JavaScript からインポートされるインターフェースは
    Js*
    (例:
    JsCharacter
    )とし、ダックタイピングを許可して Rust 型がそれらのインターフェースを満たせるようにします。
  4. コレクション内で境界を越える必要がある型には、
    #[wasm_refgen]
    マクロ(例:
    #[wasm_refgen(js_ref = JsFoo)]
    )を使用します。
  5. Rust のエラーを JavaScript に渡すために
    impl From<YourError> for JsValue
    を実装し、カスタム名(例:"RwError")の
    js_sys::Error
    を生成します。同様に
    From<WasmError>
    JsValue
    用に実装します。
  6. Wasm バンドルにビルド情報(Git ハッシュ、ディーティー状態)を含めるには、
    build.rs
    内で環境変数を生成し、起動時に出力します(例:
    #[wasm_bindgen(start)]
    )。
  7. 境界を越えて可変参照(
    &mut
    )を渡すことは避け、代わりに内部可変性プリミティブを使用します。
  8. js_sys::dyn_into
    を使った手動バインディングは脆弱です;コンパイル時の安全性を確保するためには bindgen が生成したグルーコードに頼ります。
  9. コレクションで使用されるエクスポート型がコストの低い複製(例:
    Rc
    )を実装し、JS ハンドルから安全に変換できるよう名前空間付きの
    clone
    メソッドを公開していることを確認します。

この改訂版サマリーはすべての重要ポイントを網羅し、不必要な推測を避けつつ、読者へ主要メッセージを明確に伝えます。

本文

はじめに

近年、Rust で書く Wasm の量が増えてきました。
インターネット上には Wasm に関するさまざまな意見がありますし、wasm‑bindgen も「好き嫌い分かれる」ツールです。経験を積み、その欠点に対処する方法を学ぶうちに、私の作業効率を劇的に上げるパターンが見えてきました。

本記事では、以下の二点についてはっきりさせておきます。

  • wasm‑bindgen のメンテナ方針や実装には深く感謝しています。
  • ここで紹介する手法よりも優れた方法が存在する可能性があります。これはあくまで私自身の経験に基づくパターンです。

TL;DR(要約)

以下の点を守るだけで、Rust+Wasm の開発はずっと楽になります。

#推奨パターン
1Wasm バウンダリを越える際はすべて
&
参照で渡す。
2
&mut
よりも
Rc<RefCell<T>>
/
Arc<Mutex<T>>
を優先する。
3エクスポート対象の型には
Copy
を派生させない。
4コレクションで渡す必要がある型は wasm_refgen を使う。
5Rust 側でエクスポートする全ての型に
Wasm*
プレフィックスを付け、
js_name/js_class
はプレフィックス無し名に設定する。
6JS からインポートした型は
Js*
をプレフィックスに使う。
7Rust 側でエクスポートしたエラー型は
From<YourError>
を実装し、
js_sys::Error
へ変換して
JsValue
にする。

wasm‑bindgen の仕組みを簡単に

wasm‑bindgen は Rust の構造体・メソッド・関数を JS/TS 側から呼び出せるように、ラッパーコード(glue code)を生成します。

IntoWasmAbi
を実装した型は直接 JS へ渡せますが、それ以外の型は Wasm サイドで管理され、JS 側では
{ __wbg_ptr: 12345 }
のようなハンドルとして扱われます。

この仕組みを使う上で重要なのは、JavaScript と Rust が異なるメモリモデル(GC vs. 所有権)を持つことです。
bindgen はそのギャップを埋めるために多くのチェックと変換ロジックを提供しますが、一部は過剰であったり不十分である場合があります。


手動バインディングを書かなければいい?

「手動か自動か」は好みの問題です。

js_sys
を使って手作業で型変換する方法もありますが、変更に弱く、コンパイル時のフィードバックが得られません。
bindgen の生成コードを利用し、上記のパターンに沿うだけでほとんどの場合は十分です。


名前付けの重要性

名前は「最も難しい二つの問題」の一つ(他方は off‑by‑one エラー)として語られます。
bindgen では、型が JS 側に渡る際の表現を明確にするため、次のような命名規則を採用します。

IntoWasmAbi

u32
,
String
,
Vec<u8>
のように直接 ABI で渡せるプリミティブ型は特別扱いしません。
これらは JS と Rust の間で自動的に変換されます。

Rust 側のエクスポート構造体 →
Wasm*

Rust の列挙や構造体を JS に公開する際、

Wasm*
というプレフィックスを付けてラップします。
JS 側ではプレフィックスを除去して一意に扱います。

#[derive(Debug, Clone)]
pub enum StreetLight { Red, Yellow, Green }

#[wasm_bindgen(js_name = StreetLight)]
pub struct WasmStreetLight(StreetLight);

JS からインポートしたインターフェース →
Js*

extern "C"
で宣言された JS の型は、Rust 側ではダックタイプ(任意の実装)として扱います。
名前衝突を防ぐためにメソッド名には必ず
js_
プレフィックスを付けます。

#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(js_name = logCurrentTime)]
    pub fn js_log_current_time(timestamp: u32);

    #[wasm_bindgen(js_name = Hero)]
    type JsCharacter;

    #[wasm_bindgen(method, getter, js_name = hp)]
    pub fn js_hp(this: &JsCharacter) -> u32;
}

Copy
を派生させない

Copy
は値を暗黙に複製してしまうため、ハンドル(リソースへのポインタ)を持つ型がコピーされると「空の」ハンドルになり、後で使用するとランタイムエラーになります。
したがって、export 用ラッパーは
Copy
を派生させないようにしましょう。


ハンドル破損を防ぐ

wasm‑bindgen は実行時にハンドルが壊れることを検知できません。典型的な失敗例は、所有権を Rust 側で消費してしまうケースです。

#[wasm_bindgen(js_class = Foo)]
impl WasmFoo {
    #[wasm_bindgen]
    pub fn do_something(&self, bar: Bar) -> Result<(), Error> { ... }
}

Bar
を所有していると、Rust 側で解放されてしまい、JS からは無効なハンドルが渡ってきます。
対策:常に参照渡し(
&
)を行い、必要なら内部可変性(
Rc<RefCell<_>>
等)を利用する。


&mut
は避ける

JS の非同期実行モデルは Rust のコンパイル時排他チェックを尊重しません。そのため

&mut self
を渡すと、再入可能性(re‑entrancy)の問題でランタイムエラーが発生します。
代わりに、適切な内部可変性プリミティブ (
RefCell
,
Mutex
) を使用しましょう。


コレクションの扱い

bindgen は

&[T]
IntoWasmAbi
の型(JS 管理型)である場合のみ許容します。
それ以外の場合は、
Vec<T>
という所有型を返す必要がありますが、これは JS 側が配列を自由に変更できるためです。

ワークアラウンド

  1. エクスポートする型を
    Rc
    /
    Arc
    でクローン可能にする。
  2. 名前空間付きの
    clone
    メソッドを公開し、JS インターフェースから呼び出せるようにする。
  3. From<JsType>
    を実装して、
    .into()
    の形で簡潔に変換できるようにする。
#[wasm_bindgen(js_name = Character)]
pub struct WasmCharacter(Rc<RefCell<Character>>);

#[wasm_bindgen(js_class = Character)]
impl WasmCharacter {
    #[doc(hidden)]
    pub fn __myapp_character_clone(&self) -> Self { self.clone() }
}

#[wasm_bindgen]
extern "C" {
    type JsCharacter;
    pub fn __myapp_character_clone(this: &JsCharacter) -> WasmCharacter;
}

wasm_refgen を使う

上記の手動作業を自動化するマクロが

wasm_refgen
です。
#[wasm_refgen(js_ref = JsFoo)]
を付与すると、名前空間付き
clone
が生成され、JS インターフェースとしてインポートされ、
From<JsFoo>
が自動実装されます。

use std::{rc::Rc, cell::RefCell};
use wasm_bindgen::prelude::*;
use wasm_refgen::wasm_refgen;

#[derive(Clone)]
pub struct WasmFoo {
    map: Rc<RefCell<HashMap<String, u8>>>,
    id: u32,
}

#[wasm_refgen(js_ref = JsFoo)]  // ← 自動生成
#[wasm_bindgen(js_class = "Foo")]
impl WasmFoo { /* 通常のメソッド */ }

JS エラーへの自動変換

Wasm 側で発生したエラーを

js_sys::Error
に変換して
JsValue
として返すと、JS からは
TypeError
等として扱われます。
以下のように
From<YourError>
を実装すると便利です。

#[derive(Debug, Clone, thiserror::Error)]
pub enum RwError {
    #[error("cannot read {0}")]
    CannotRead(String),
    #[error("cannot write")]
    CannotWrite,
}

#[derive(Debug, Clone, thiserror::Error)]
#[error(transparent)]
pub struct WasmRwError(#[from] RwError);

impl From<WasmRwError> for JsValue {
    fn from(err: WasmRwError) -> Self {
        let js_err = js_sys::Error::new(&err.to_string());
        js_err.set_name("RwError");
        js_err.into()
    }
}

これで

Result<T, WasmRwError>
を返すだけで、JS 側にエラーが投げられます。


ビルド情報の出力

ビルド時に Git のハッシュや dirty ステータスを環境変数に設定し、Wasm 起動時にコンソールへ表示すると、デバッグが格段に楽になります。
Cargo ワークスペースで

build.rs
を書き、
GIT_HASH
環境変数を設定するサンプルは上記記事のコードをご参照ください。

#[wasm_bindgen(start)]
pub fn start() {
    web_sys::console.info1(format!(
        "your_package_wasm v{} ({})",
        env!("CARGO_PKG_VERSION"),
        build_info::GIT_HASH
    ));
}

まとめ

  • 明示的に扱う:ハンドルを渡す際は常に参照で、所有権を消費しない。
  • 名前付けを徹底する
    Wasm*
    ,
    Js*
    プレフィックスで型の役割を一目で分かるように。
  • 内部可変性を活用
    Rc<RefCell<_>>
    /
    Arc<Mutex<_>>
    &mut
    のリスクを回避。
  • エラーは JS に変換
    From<YourError>
    を実装し、JS 側に情報が残るように。

これらのパターンを採用すれば、Rust+Wasm 開発は「境界がない」感覚で楽になります。
ぜひ試してみてください。

同じ日のほかのニュース

一覧に戻る →

2026/03/09 5:30

エージェント・セーフハウス – macOS ネイティブサンドボックスによるローカルエージェントの保護 --- **ポイント解説** - **Agent Safehouse** は、macOS 上で動作するローカルエージェント(バックグラウンドプロセスやサービス)を安全に隔離し、外部からの不正アクセスや権限昇格を防ぐための仕組みです。 - 「macOS‑native sandboxing」は、Apple が提供するサンドボックス機能(`sandbox-exec`, `com.apple.security.*` など)を利用しており、追加のソフトウェアやカーネル拡張は不要です。 **主な特徴** 1. **最小権限で実行** – 必要最低限のファイル・ネットワークアクセスのみ許可し、それ以外は自動的にブロック。 2. **監査ログ** – アクセス試行や失敗がすべて記録され、後からトラブルシューティングやセキュリティ調査に利用可能。 3. **設定の柔軟性** – プロファイルベースでポリシーを定義でき、企業規模に合わせた細かな制御が可能。 **実装例(サンドボックスプロファイル)** ```xml <key>com.apple.security.app-sandbox</key> <true/> <key>com.apple.security.files.user-selected.read-write</key> <true/> ``` このように、エージェント・セーフハウスは macOS の標準機能だけで安全性を大幅に向上させるソリューションです。

## Japanese Translation: > Safehouse は、ローカル AI エージェントがアクセスできるファイルを厳密に制御する軽量な macOS ネイティブサンドボックスです。デフォルトでは「deny‑first」ポリシーに従い、指定されたワークスペース外への読み書き試行はカーネルエラー(“Operation not permitted”)を引き起こし、SSH キーや `.aws` などの機密項目やその他個人リポジトリを保護します。ツールは `curl` を使って `~/.local/bin` にインストールされる単一の Bash スクリプト(`safehouse.sh`)でセットアップされます。 > > エージェントは `safehouse claude --dangerously-skip-permissions` のようなコマンドで呼び出され、現在の作業ディレクトリ(通常は git リポジトリルート)への読み書きアクセスを自動的に許可し、インストール済みツールチェーンへの読み取りアクセスのみを許可して残りのホームディレクトリは拒否します。 > > 上級ユーザーは `safe() { safehouse --add-dirs-ro=~/mywork "$@"; }` のようなシェル関数を `.zshrc` や `.bashrc` に追加し、すべてのエージェント呼び出しがデフォルトで Safehouse 内で実行されるようにできます。セッションごとにサンドボックスをバイパスするには、コマンドに文字列 `command` を接頭辞として付けます(例:`command claude`)。 > > このゼロコンフィグ方式により、開発者やチームはローカルファイルとの AI 連携を安全に行い、個人プロジェクト、クラウド認証情報、企業リポジトリでの偶発的なデータ漏洩を減らすことができます。

2026/03/09 6:40

**ブラックスカイ・AppView**

## Japanese Translation: Blacksky の AppView は Bluesky Social PBC の AT Protocol 参考実装をフォークしたもので、**外部からの貢献やプルリクエストは受け付けません**。すべての変更は `packages/bsky`、`services/bsky` の3つのディレクトリと1つのマイグレーションファイルに限定され、参考コードの大部分を保持しています。 リポジトリは組み込みの TypeScript フィーホーズコンシューマーを Rust ベースのインデクサ **rsky‑wintermute** に置き換えており、並列キューを通じて約10 k+ レコード/秒を取り込むことができます。Wintermute はブートストラップツール(`queue_backfill`、`direct_index`、`label_sync` など)を提供し、ライブインデクシングとバックフィルを分離します。 主なパフォーマンス最適化は次の通りです: - PostgreSQL の LATERAL JOIN 再書き込み(`getTimeline` / `getListFeed` 用) - Redis キャッシュレイヤー(アクタープロファイル TTL 60 s、レコード TTL 5 m、相互作用カウント TTL 30 s、投稿メタデータ TTL 5 m) - 通知設定のサーバー側強制 実装された修正: - JWT 検証における古い署名鍵の処理 - JSON のサニタイゼーションで null バイト/制御文字を除去 - アクターメモリキャッシュ内の protobuf タイムスタンプバグへの対策 Blacksky は **コミュニティ投稿サポート** をカスタムレキシコン namespace(`community.blacksky.feed.*`)と専用 `community_post` テーブル、データプレーン/API 層でのメンバーシップゲーティングを通じて追加しています。これは混在した投稿スレッド(`getPostThreadV2`)とも統合されます。 全体アーキテクチャフロー: Bluesky Relay → rsky‑wintermute(フィーホーズコンシューマ/バックファラー/ラベルインデクサ) → PostgreSQL 17 → bsky‑dataplane(gRPC) → オプションの Redis キャッシュ → bsky‑appview(HTTP) → リバースプロキシ、Palomar が OpenSearch 検索機能を提供 バックフィル性能: ライブインデクシングは約1 k イベント/秒。42 M ユーザーと 18.5 B レコードのフルバックフィルは10 k レコード/秒で 2–4 週間、部分的なバックフィルは数時間〜数日で完了 ブートストラップ課題への対策: - PostgreSQL COPY による JSON 腐敗 - null バイト処理 - タイムスタンプ精度の強制 - 通知テーブルの肥大化緩和 - 投稿埋め込みテーブルの人口化 - ラベル否定順序 - Fjall キュー毒性解決 - TLS プロバイダ初期化 - アカウント移行後の署名鍵回転 **フルネットワーク AppView のリソース要件:** ≥ 16 CPU コア(推奨 48+)、≥ 64 GB RAM(256 GB 推奨)、10 TB NVMe ストレージ(28 TB RAID 推奨)、同一マシンまたは低遅延での PostgreSQL、継続的ネットワーク 100 Mbps(1 Gbps+)以上の取り込み帯域 リポジトリは MIT/Apache 2.0 のデュアルライセンスです。アップストリーム同期手順は `git remote add upstream https://github.com/bluesky-social/atproto.git` で提供されています。

2026/03/09 4:58

「エージェント時代にリテラトープログラミングを見直すべきです。」

## Japanese Translation: > 本稿は、コードと説明文を組み合わせたリテラトープログラミングが、AI エージェント(例:Claude や Kimi)が Org‑Mode ファイルを単一の真実源として扱う場合に実用化できることを主張しています。 > > Org の構文を解析することで、これらのエージェントはランブックを生成し、埋め込みコードブロックを実行し、Jupyter ノートブックのように結果を保存し、プローズとコードを同期して自動的に更新できるため、ナラティブと実行可能なスクリプトを分離する手作業「タンギング」ステップが排除されます。 > > 著者は、Org Mode を設定管理に個人的に使用した例でこれを示しています:エディタ内で直接コマンドを書き込み、それらを実行し、メモを自動的に取得します。 > > コードとプローズの2つの並列文書を維持することは採用への一般的な障壁ですが、AI 主導のワークフローは `AGENTS.md` ファイルに記載された指示(実行前のタンギング、常にステップを説明するプローズ、両側を同期させる)に従うことでそのオーバーヘッドを排除します。 > > このアプローチはワークフローを合理化し、コードベースを複数の読みやすいフォーマットへエクスポートしやすくし、「コードを書く」から「コードを読む」へのシフトを促進します。また、大規模プロジェクトにおける Org‑Mode の Emacs 統合の限界を浮き彫りにし、リテラトープログラミングの普及を広げるために Markdown などの類似フォーマットを推奨することも示唆しています。