Upgrade to Pro — share decks privately, control downloads, hide ads and more …

WebエンジニアがSwiftをブラウザで動かすプレイグラウンドを作ってみた

Avatar for uutan1108 uutan1108
September 21, 2025

 WebエンジニアがSwiftをブラウザで動かすプレイグラウンドを作ってみた

WebエンジニアがSwiftをブラウザで動かすプレイグラウンドを作ってみた by うーたん | トーク | iOSDC Japan 2025 #iosdc - fortee.jp
https://fortee.jp/iosdc-japan-2025/proposal/f71e096d-1452-4e81-b0f4-c8a46dac557c

Avatar for uutan1108

uutan1108

September 21, 2025
Tweet

More Decks by uutan1108

Other Decks in Programming

Transcript

  1. TypeScript とは
 JavaScriptのスーパーセットとなるプログラミング言語。静 的型付け言語 であり、プログラムの正しさが静的に検査でき る。(1)
 
 
 
 12


    (1) TypeScript入門『サバイバルTypeScript』〜実務で使うなら最低限ここだけはおさえておきたいこと〜
 https://typescriptbook.jp/
 
 

  2. TypeScript とは
 JavaScriptのスーパーセットとなるプログラミング言語。静 的型付け言語 であり、プログラムの正しさが静的に検査でき る。(1)
 JavaScript は、デベロッパーがインタラクティブなウェブペー ジを作成するために使用するプログラミング言語です。(2)
 13


    (1) TypeScript入門『サバイバルTypeScript』〜実務で使うなら最低限ここだけはおさえておきたいこと〜
 https://typescriptbook.jp/
 (2) JavaScript とは? - JavaScript (JS) の説明 - AWS
 https://aws.amazon.com/jp/what-is/javascript/

  3. Wasm (WebAssembly) とは
 WebAssemblyとは、Webブラウザ上で高速に動作 するバイナリコードの仕様 を指す言葉です。
 C、C++、Rustなど、さまざまなプログラミング言語 で書かれたプログラムをコンパイル でき、既存の コードをWebブラウザ上で実行できる


    17
 WebAssemblyとは?何ができるのか?できないことやユースケースをわかりやすく解説 |パーソルクロステクノロジー 
 https://staff.persol-xtech.co.jp/hatalabo/it_engineer/641.html

  4. print() などのシステムコール を
 Wasm からする場合は、 
 WASI の実装をする必要がある 
 32


    OSのシステムコールの呼び出しとは&バイナリエディタの使い方: main()関数の前には何があるのか( 4)
 (1/3 ページ) - @IT
 https://atmarkit.itmedia.co.jp/ait/articles/1703/01/news169.html

  5. print() などのシステムコール を
 Wasm からする場合は、 
 WASI の実装をする必要がある 
 33


    OSのシステムコールの呼び出しとは&バイナリエディタの使い方: main()関数の前には何があるのか( 4)
 (1/3 ページ) - @IT
 https://atmarkit.itmedia.co.jp/ait/articles/1703/01/news169.html
 TypeScript で実装しました

  6. WASI(WebAssembly System Interface) とは
 
 WASIは、WebAssembly(Wasm)の制約を解決 するため に開発されました。
 WASI によって


    • ファイルやネットワークなどのシステムリソースに直接ア クセス可能にする
 • システムコール を直接できるようにする
 37
 参考:WASI とは? | Fastly https://www.fastly.com/jp/learning/serverless/what-is-wasi
 

  7. 39
 WebAssembly: Docker without containers!
 https://wasmlabs.dev/articles/docker-without-containers/
 システムコール
 システムコール(System Call) は、WindowsやLinuxといった

    OSのカーネルが持つサービス を要求するための命令です。
 システムコールとは【用語集詳細】 
 https://www.sompocybersecurity.com/column/glossary/system-call
 

  8. 今回実装した WASI のメソッド 
 40
 参考:OSのシステムコールの呼び出しとは&バイナリエディタの使い方: main()関数の前には何があるのか( 4)
 (1/3 ページ)

    - @IT
 https://atmarkit.itmedia.co.jp/ait/articles/1703/01/news169.html
 Swiftのメソッド WASIのメソッド システムコール print() fd_write() write() readLine() fd_read() read() exit() proc_exit() _exit() Int.random() random_get() getrandom() Swift が表で示したシステムコールをしているか調べきれてないです。

  9. fd_write: (fd: number, iovs: number, iovsLen: number, nwritten: number) =>

    { if (fd === 1 || fd === 2) { const memory = (instance.exports.memory as WebAssembly.Memory); const buffer = new Uint8Array(memory.buffer); let totalWritten = 0; for (let i = 0; i < iovsLen; i++) { const iovPtr = iovs + i * 8; const strPtr = new DataView(memory.buffer).getUint32(iovPtr, true); const strLen = new DataView(memory.buffer).getUint32(iovPtr + 4, true); const str = new TextDecoder().decode(buffer.slice(strPtr, strPtr + strLen)); setOutput(prev => prev + str); totalWritten += strLen; } new DataView(memory.buffer).setBigUint64(nwritten, BigInt(totalWritten), true); return 0; } return -1; }
 42

  10. fd_write: (fd: number, iovs: number, iovsLen: number, nwritten: number) =>

    { // fd === 1: 標準出力(stdout), fd === 2: 標準エラー出力 (stderr) if (fd === 1 || fd === 2) { // WebAssemblyインスタンスのメモリを取得 const memory = (instance.exports.memory as WebAssembly.Memory); const buffer = new Uint8Array(memory.buffer); let totalWritten = 0; // 実際に書き込まれたバイト数の合計 // iovs(iovec配列)をループ処理 // iovecは { データのポインタ , データの長さ } の構造体 for (let i = 0; i < iovsLen; i++) { // 各iovecの位置を計算(8バイトずつ: ポインタ4バイト + 長さ4バイト) const iovPtr = iovs + i * 8; // DataViewを使ってメモリから値を読み取り const strPtr = new DataView(memory.buffer).getUint32(iovPtr, true); // 文字列の開始アドレス const strLen = new DataView(memory.buffer).getUint32(iovPtr + 4, true); // 文字列の長さ // メモリから文字列データを取得してデコード const str = new TextDecoder().decode(buffer.slice(strPtr, strPtr + strLen)); // Reactのstate更新関数を使って出力を表示 setOutput(prev => prev + str); // 書き込まれたバイト数を累積 totalWritten += strLen; } // nwrittenポインタに実際に書き込まれたバイト数を書き込み // これにより、SwiftWasm側で書き込み結果を確認できる new DataView(memory.buffer).setBigUint64(nwritten, BigInt(totalWritten), true); return 0; // 成功を示す戻り値 } // 標準出力・標準エラー出力以外のファイルディスクリプタの場合はエラー return -1; // エラーを示す戻り値 }
  11. fd_write: (fd: number, iovs: number, iovsLen: number, nwritten: number) =

    (省略) for (let i = 0; i < iovsLen; i++) { const iovPtr = iovs + i * 8; const strPtr = new DataView(memory.buffer).getUint32(iovPtr, tru const strLen = new DataView(memory.buffer).getUint32(iovPtr + const str = new TextDecoder().decode(buffer.slice(strPtr, strPtr + setOutput(prev => prev + str); totalWritten += strLen; } (省略) }
 46
 一文字づつ文字列連結して
 画面に表示する TypeScript の命令