Link
BASE64及びBASE32(RFC4648)のピュアECMAScriptによる実装(Uint8Arrayとstringの間でのエンコード/デコード)。 及び、テーブル文字列を渡すことで生成できるジェネリックBASE(Power of 2)の実装。
base64.js: ループ文とletを一切使わないBASE64実装(ビット演算)
base32.js: ループ文とletを一切使わないBASE64実装(数値演算)
basepow2.js: 文字テーブルを渡してencode()/decode()を作る汎用BASE Power-of-2 実装(数値演算)
BASE32では、5ビットと8ビットの最小公倍数の40ビットが処理単位になり、 ECMAScriptの32ビットでのビット演算を超えるので、52ビット整数まで正確に扱える数値演算を利用した。 n >> mはn / 2 ** m (小数部切り捨て)と同じである。 2進数で相互に相手の0部分にだけに1がある2数のビットORのn | mは、n + mと同じである。
ちなみに、16進hexも、ジェネリックなBASE2^2処理で行う仕様の一種である。
なお���BASE32で0と1が除外される理由はIとOに似ているかららしいが、 それをいったら除外されなかった2もZとかなり似てると思うのだが....
8 notes
·
View notes
Link
WHATWG Streams API](https://streams.spec.whatwg.org/)を使うための、簡単なコード例11個。 Promiseの非同期処理記述はthen()ではなく、asyncとawaitを用いるようにしている。
01-object-readable.js: ReadableStreamを作り、読み込むコード例:
ReadableStreamは、任意のオブジェクトや値を次々非同期でread()できるストリームである
ReadableStreamのコンストラクタで渡すsourceオブジェクトは、完了を表すPromiseを返すメソッド群で機能を実装する (簡単に定義したいならasyncにすればいい)
引数のcontrollerのメソッドenqueue()に渡したオブジェクトがReaderのread()メソッドから順に受け取れる (ReaderはReadableStreamのgetReader()メソッドで取り出せる)
controllerのキューしてる量が不足状態になると、pull()メソッドが呼び出される (コンストラクタの第二引数のオプションのhighWaterMarkプロパティで不足数を指定できる)
注: getReader()を呼ぶたびに別々のReaderオブジェクトが得られるが、read()できるのは最初の一つだけ (ReaderのreleaseLock()メソッドを呼べば、そのオブジェクトが��放され、次のReaderオブジェクトがread()できるようになる)
Readerのread()でかえるPromiseの値は、iteratorと同じvalueとdoneを持ったオブジェクトである
現状の仕様では、コメントアウトしたコードのように、基本forループの中でawait呼び出しするのが楽か
02-bytes-readable.js: バイト列に特化したReadableStreamを作り、読み込む例:
バイト列のストリームの場合、sourceのtypeプロパティで"bytes"を入れると、TypedArrayに特化したReadableStreamを使うことができる
バイト列のcontrollerのenqueue()メソッドにはTypedArrayのArrayBufferViewのみ渡せる(オブジェクトや数値を渡すとTypeError)
どのArrayBufferViewをenqueue()したとしても、Readerのread()で得られるPromise値はUint8Arrayである
03-writable.js: WritableStreamを作り、書き込む例
WritableStreamは、任意のオブジェクトや値を次々write()されたものを非同期に処理できるストリームである (WritableStreamには、ReadableStreamのようなバイト列特化実装はない)
WritableStreamのコンストラクタで渡すsinkオブジェクトは、完了を表すPromiseを返すメソッド群で機能を実装する
write()を呼び出せるWriterは、getWriter()で取り出せる(Reader同様にロックによって一つだけwrite()が呼び出せる)
Writerのwrite()の返すPromiseは、sinkでのwrite()が完了した時にresolveされる (awaitすれば完了待ちするし、awaitしないで連続でwrite()すると、controller内部のキューに貯めさせることになる)
04-transform.js: (未策定の)TransformStreamの作り方と使い方の例:
WHATWGのリファレンス実装にはあるが、現状の仕様内にはTransformStreamクラスは含まれていない
ただし、{readable: ReadableStream, writable: WritableStream}なオブジェクトがReadableStreamのpipeThrough()メソッドに渡す TransformStream扱いされることは仕様内にある
TransformStreamとは、writable側のwrite()で渡されたそれぞれの値を、変換したりフィルタしたりした結果を、 readable側のread()から取り出せる仕組みである(つまり、writable => readableな関係)
writableのWriterでwrite()したときに、コンストラクタに渡したオブジェクトのtransform()メソッドが呼ばれ、 そこでcontrollerのenqueue()に変換したオブジェクトを渡せば、readableのReaderのread()で得ることができるようになる
writableでclose()すると、コンストラクタに渡したオブジェクトのflush()メソッドが呼ばれる
現実装では、TransformStreamのwritableのWriterのwrite()が完了するのは、readableのReaderのread()されたときである
05-transform-pair.js: ReadableStreamとWritableStreamを使って、簡単なTransformStreamを実装する例:
readableのsourceのstart()で得たcontrollerと、wruitableのsinkのstart()で得たcontrollerを保持し、 sourceのメソッドではsinkのcontrollerを使い、逆にsinkのメソッドではsourceのcontrollerを使うことで、 TransformStreamっぽいものが作れる(この実装の通り、この2つのペアでメソッドの対応関係がある)
06-tee.js: ReadableStreamのtee()メソッドで、ReadableStreamを複製するコード例
getReader()で得るReaderは排他制御されるので、二箇所から同一内容を購読する場合は、ReadableStreamをtee()メソッドで 複製して、その2つのReadableStreamを使う必要がある
注: tee()の2つのReadableStreamで両方cancel()されたとき、tee()元がcancel()される
07-pipeto.js: ReadableStreamのpipeTo()メソッドで、WritableStreamに流すコード例
ReadableStreamのpipeTo()メソッドにWritableStreamを渡せば、非同期で、自動で読み書き��流される (つまりreadable => writableな関係)
pipeTo()の戻り値のPromiseで、読み書き完了���待つことができる
デフォルトでは、ReadableStreamのcontrollerでclose()呼び出しをすると、WritableStreamもclose()される (同様に、ReadableStreamのcontrollerのerror()呼び出しはWritableStreamのabort()を呼び出す、 WritableStreamのcontrollerのerror()呼び出しはReadableStreamのcancel()を呼び出す、つながりがある)
pipeTo()の第二引数のオプションオブジェクトで、これらのclose()/cancel()/abort()のつながりをを抑制できる (たとえば、ReadableStreamを消費しきったあと、 同じWritableStreamに追加で別のReadableStreamを加えるときは最初のpipeTo()でのclose()を抑制する必要がある)
08-pipethrough.js: ReadableStreamのpipeThrough()メソッドにTransformStreamを渡せば、変換された値が受け取れるReadbleStreamになる
pipeThrough()の戻り値は、引数に渡したTransformStreamのreadableそのものである
注: pipeTo(ts.writable)と一緒だが、戻り値に対してpipeThrough()チェーン記述できる (自動で読み込ませるには、チェーンの最後でpipeTo(ws)するとよい)
pipeThrough()の第二引数には、pipeTo()と同じオプションを渡せる
09-await-write-ready.js: WritableStreamの内部キューの消費待ちをするコード例
WritableStreamコンストラクタ台に引数のオプションのhighWaterMarkプロパティで、キューの空き待ちの目安を設定できる
注: キュー自体の保持数のリミットではなく、sinkのwrite()消費待ち状態に入る最小のキューされた数で設定する (つまり、たとえhighWaterMarkを超えても、write()できキューに積める)
キューに積まれたsinkで未消費のオブジェクトの数が、highWaterMarkを超えると、Writerのreadyで得られるPromiseが 待ち状態になり、sinkで諸費されhighWaterMark未満になったときresolveされる
注: write()の戻り値のPromiseは処理完了のための(逐次的な)待ちであり、readyは(並列的な)キューの空き待ちに使う
10-cancel.js: ReadableStreamのcacnel()の使い方
ReadableStreamのcancel()とReaderのcancel()がある。read()同様、getReader()した場合はそのReaderのcancel()だけ機能する (ReadableStreamのcancel()はロック保持してるReaderが一つもない場合だけ使える)
sourceのpull()でresolve/rejectされないPromiseを渡しても、cancel()すればread()が完了(done: true)する
11-read-with-async-iteration.js: ECMAScriptのasync iteration提案でReadableStreamを読み込むコード例
Readerのread()呼び出しをasync iteratorでラップして呼び出す
Symbol.asyncIteratorメソッドを持ったオブジェクトがfor await ofループ構文で使える仕様がasync iteration
このループでは、ofの右のSymbol.asyncIteratorメソッドが返すオブジェクトのnext()メソッドが呼び出される
next()メソッドの返り値はイテレータと同じ意味の{value, done}オブジェクトのPromiseである
async function*なAsyncGeneratorFunctionが返すオブジェクトがこの形式になっている
0 notes
Link
じつは、nodejsの組み込みAPI(fs, crypto, zlib)だけをつかった単純なコードで、gitコマンドで機能するgitリポジトリを作れてしまう。
以下この100行程度のスクリプトコード内の説明:
emptyRepo(): git init直後のような".git/"以下の基本ファイル構造を作る手続き
saveObject(): オブジェクトファイルは、タイプに限らず共通した、ファイル名と圧縮内容の仕様となっている。戻り値でSHA1ハッシュIDを返す。
saveBlob(), saveTree(), saveCommit(): gitオブジェクトの必要最小限の基本の3タイプblob,tree,commitのフォーマットにエンコードする処理をして、それをsaveObject()でファイルに書き込ませる。戻り値でSHA1ハッシュIDを返す。
blob: ファイルそのまんまのバイナリバイト列
tree: エントリが連続するバイト列。各エントリは(パス要素名で)可変長になる{モード文字列, 空白、UTF8パス要素名、NUL文字、20バイトSHA1ハッシュバイナリ値}のバイト列
commit: MIMEに似た形式のヘッダ&ボディなテキスト(コメントつきtagオブジェクトも同じ形式である)。ヘッダエントリはcommit, parent, author, committer
setRef(): タグやbranchを表すrefをセットする手続き。最低限HEADで指定している"refs/heads/master"にcommitが参照されている必要がある。
exampleRepo(): 上記手続きを使って、リポジトリを構築する例。
ちなみに、js-git等のgitライブラリでもこの粒度での機能の呼び出しでリポジトリを操作する。(git addコマンドで操作するステージindexのような)更新差分で操作するような高レベル機能をもつAPIがあるものはlibgit2くらいである。
このスクリプトファイルをnodejsで実行すると、"hello/.git/"以下にリポジトリ構造ができあがる(ワーキングは空のまま)。 そして、この"hello"ディレクトリに対して、"git clone hello hello-clone"ができ、そこではワーキングのファイルも復元される。
5 notes
·
View notes
Link
タブWebサーバReverse Proxyゲートウェイ の実用型の例として、get clone(pull/fetch)できるgit リポジトリHTTPサーバ。
demoページ
js-gitにはfetchクライアント側の実装はあっても fetchサーバ側の実装はないので、pktline処理を始めとして、やり取りはほぼすべてこのスクリプト上で実装した (refsResponse()とpackResponse())。 サーバとして機能することは、標準のgitコマンドでcloneできることで確認した。
実装の参考にしたのはhttp_proxy経由でキャプチャした、gitコマンドがやり取りするreq/resの内容である。 苦労したのはPACKデータの送信部分で、マルチバンドのエンコードが必要なことが、 解説したドキュメントになかったからである (4年前なので古いプロトコルなのだろう。reponseのcontent-typeも現行のgitコマンドと違っている)。
pktlineでの、サイズ文字4バイト���直後の1バイトに0x1や0x2を入れるのがマルチバンド(side-band)のパケットらしい。 バンド1(=直後1バイトが0x1)にPACKデータを一括して載せ、バンド2はgit コマンドで"remote:"で出てくる文字列が乗る という仕組みになっている。
分散CVSとしては、PULL型のpullのほうが本質的である。 書き換えは本人の手元だけで行うので、パブリック空間ではpullだけで完結する。
一方、相手に対して認証承認を必然的に行うpushは、 複数の主体が存在する空間では承認管理の中間システムが必要となり、 そのための事前やり取りが必須になる。
しかし、WebでPULL可能にするには、publicアドレスを持ったWebサーバが必要で、 そのせいでgithubのようなクラウドサービス上でホスティングしたpushできる中間者を 使う状況になっているにすぎない。
0 notes
Link
タブWebサーバReverse Proxyゲートウェイ の実用型の例としてのファイル転送システムページ。
demoページ
端的に言えば、Firefox Sendのような機能を、 70行程度のブラウザ上でのスクリプトだけで実現したものである(中継点対策でのエンドポイントでの暗��化はしてないけど)。
このコードが短いのは、標準APIのFileとResponseがシームレスに扱えるからである(fileResponse()のコード)。
もちろん、ローカルのfile: なページからでも、このデモは機能する。
こういうラージデータの送受信はWebRTCのようなP2Pでやりたいものだ。
0 notes
Link
タブWebサーバ用汎用rever seproxyゲートウェイを使って、 シグナリングを実装したWebRTC Offer/Answer分割コードexampleの拡張example。
モバイルネットワークの(OS層から各中間者の全段階での)ネットワークタイムアウト設定が早すぎて(2、3秒)、コピペじゃ時間内にSDPやり取りするのは不可能なので、 仕方なく実装してみた。
Answer側ページ
Offer側ページ
シグナリングに応答するため。先にAnswer側を立ち上げ、WebサーバとしてのURLをreveerse proxyゲートウェイに確保する必要がある。 Offer側がそのURLを入力することで、接続フローが開始され、自動でSDPをやり取りするようになっている。 またOffer側でもタイムアウト防止のため、fetchを1秒間隔でポーリングしている。
とはいえ、モバイルネットワークだと、プロバイダによってはSTUNでのホールパンチングしたホールも安定確保されにくいので、 現状では(コメントアウトしてあるが)TURNサーバにフォールバックして中継しないと安定利用できない。
(某NTTの某SkyWay"サービス"のような、)WebRTCだが、実際にはシグナリングサービス+TURN経路なんて、 (まったくP2Pじゃない)スター型ネットワーク構造になるのは冗談でしかない。 こんなのはインターネットやWebじゃなく、表層を偽装した専用ネットワークにすぎない。
下層でのタイムアウトが速すぎると、上層で無駄な送受信が増えることになるのではないか。 モバイルネットワークでは、STUNのパンチホールのタイムアウトも速いので、TURNじゃないと安定しないというのは、 通信量が増える要因にもなるだろう。
とはいえ、インターネットがIPv4/NATな多段ネットワークになってしまっている点がそもそもの問題で、 Webがクラウドサービスで中央化し��しまいやすいのも、パケットreachabilityがない点に起因する。
0 notes
Link
タブでWebサーバのreverse proxyゲートウェイの プロトタイプをもとに、 EventTargetやRequest/Responseといったモダンブラウザ標準APIで利用可能にしたものである。
さらに、公開鍵のハッシュ値と電子��名を使って、タブ固有のURLをreverse proxyで利用するようにしてある。 非公開鍵暗号処理ではサーバブラウザともに、ellipticを使っている。
そして、package.jsonの文字列に埋めてあるように、かんたんにherokuに設置可能にした。
内容:
proxyd.js: 汎用reverse proxyゲートウェイのnodejsサーバ(npm i && node proxyd.jsでポート3000で実行)
proxyd-browser.js: ブラウザ用のエンドポイントライブラリ(ReverseTargetをexport)
proxyd-browser.m.js: ES6モジュールなブラウザ用エンドポイントライブラリ(内容はproxyd-browser.jsと一緒)
tab-web-server-example.{html,js}: hello Worldコード例
コード例にあるように、エンドポイントのAPIはServiceWorkerの"fetch"イベント(FetchEvent)とまったく同じ構造にしている。 ユーザは、ブラウザ標準のclassであるRequestと Responseを処理するだけにしてある。
demoページ
** NOTE for Streams API
ResponseやRequestのbodyを一度に全体処理しかできないのは現行の標準APIの制限である。 Web Socket層も単純化のため1コネクション上での一括パケット送受信で実装してある。
これはWHATWG Streams APIで拡張される予定になっている。 もしRequest/ResponseともにbodyでReadableStreamが使えるようになり、 対応させるにはWeb Socket層も何らかの手段で多重化する必要があるだろう。
パケットとして、{乱数ID32バイト、タイプ1バイト、データ任意バイト}になるだろうか。 パケットタイプはHEADER(utf8), BODY(binary), CLOSE(utf8)の3種になるだろう。
(たとえ別コネクションを使っても、WebSocketにはhalf closeがないので、 Readderのclose状態に対応した 終了マーカーは必要になる。)。
2 notes
·
View notes
Link
js-gitをブラウザ上で使うコード例。
ここでは、ブラウザで直接使えるようにビルドしたjs-git-browserを、 unpkg.com経由で利用させてもらった。これはjs-gitのnodeスタイルの非同期APIをpromise化してあって、だいぶ扱いやすくなっている。
このコードは全体的に非同期呼び出しであるため、async functionにしてある。 リポジトリの内容をコード上で作り、作ったリポジトリからcommit起点のオブジェクトを集めて、コンソール上で表示している。
また、圧縮かつ通信上でのオブジェクト用の形式であるPACK形式のデータで取り出す例もつけている。 js-git固有のstream構造の読み込み利用例でもある。
js-git-browserには、通信用のパケット形式であるpktline処理用の部分はexportされてないので、 pktline化のコードも入れてある。
demo: Webコンソール上でログを確認できるだけ
js-gitというのは、gitのワーキングファイルやindexといったgitユーザーが使う高レベルの仕組みはなく、".git/"以下のリポジトリデータを操作する機能の集まりである。 よってjs-gitでプログラミングするには、まずcommit,tree,blob,refsといったgitの低レベルでの構造について知っている必要がある。 (これは、libgit2など他のgitライブラリを使うプログラミングでも言えることである)。
0 notes
Link
ブラウザタブ上でもWebサーバ処理できるようにするための汎用のreverse proxyゲートウェイのプロトタイプ。 webserver-proxy間のやりとりにはWebSocketを用いている。
node proxyd.jsで汎用reverse proxyゲートウェイを起動
direct.htmlをブラウザで開くとタブがWebサーバになり、ページ上で出てくるURLにアクセス可能になる
ここで、direct.htmlは別にWebサーバ上に置く必要はなく、file:プロトコルで開いても機能する。
WebRTCでのシグナリングシステムもそうだが、(たとえばsnapchatだとか)P2P的なシステムというのは、 下のレイヤーにHTTPでreachableなしくみさえあれば、 本質的にはクラウド上に別々の目的のために機能を埋め込んだ専用のアプリ��ーションサーバなどいらないはずである。
3 notes
·
View notes
Link
nodejsのREPLを、トップレベルでawait式が使えるようにしたコマンドラインREPL。
依存パッケージなしで、npxから実行可能にしてある。例:
$ npx https://gist.github.com/bellbind/b43e459a889a0214fcfc05a910cfa1b6 > console.log(await util.promisify(fs.stat)(".")) > let {foo = 50, bar} = await Promise.resolve({bar: 100}) > await new Promise(r => setTimeout(r, 500))
注意: awaitの直後を(、)でくくると、VMはawaitを (関数な)変数扱いでパーズできてしまい、実行してReferenceErrorとなるので注意。
0 notes
Link
接続処理をOffer(呼び出し)側とAnswer(応答)側で分離して実装した、極力単純化したWebRTCプログラム。
巷にあるWebRTCコード例が難しくなっているのは、以下の要因のせいである:
Offer側とAnswer側を混ぜ、一体化したコードになっている
WebSocket等を使う、独自の自動シグナリングのシステムのコードを混ぜ込んでいる
ICE candidateの逐次受け渡しが接続処理フローに並列して行うコードを混ぜ込んでいる
カメラを用いたWeb media stream APIでのやり取りを行うコードを混ぜ込んでいる
仕様策定関係者による一次提供のコード例も含めて、とにかくごちゃまぜなコードが使われている。
そこで、このコードでは、
Offer側とAnswer側で別々のコードを用い
ICE candidateをすべて埋め込んだSDPデータを双方一度だけ相手に渡し
シグナリングシステム無しで、Offer->AnswerとAnswer->Offerの2つのSDPデータは画面上で手渡しさせ
データチャネルだけ用いてテキストメッセージを流し会う
ことで、WebRTCの呼び出しと応答を行ってP2Pでメッセージを流し合うだけにしてある。 接続フローで主体が変わるところで渡すデータを手渡しさせることで、 それぞれ100行未満のコードとなって全体を把握できるレベルに抑えている。
Offer側ページ
Answer側ページ
一応言及しておくと、シグナリングシステムがないので、サーバ側など���在しない。 本質的にWebRTCとはP2P的なモデルであって、専用の中央サーバは前提にないのである。
100行のうち頭の20行はinput UIのリストアップ部分でしかなく、続く30行は RTCPeerConnectionの作成とデータチャネルの作成newPC()関数で、 (UIのdisable/enable変更を除けば)Offer/Answerで変わらないコードである。
[データチャネル(``RTCDataChannel))](https://developer.mozilla.org/ja/docs/Web/API/RTCDataChannel)は、(TCP Socketではなく、)UDP Socketのように、 双方で作って作ったチャネルを使って相手にメッセージを送り、"datachannel"イベントで受け取ったチャネルから相手からのデータを読む一方向に専念させ、 双方同じコードとなるようにしてある。 また、データチャネルでは、RTCPeerConnection自体には存在しない、"close"`イベントが扱えるようになっている。
接続フローの本質である後半50行の構成はすべて、Offer/Answer接続フローの各ステップが、ボタンclickで起動されるイベントハンドラ内 で完結するコードとなっている。フロー内でのOffer->Answerの切り替えと、Answer->Offerの切り替え では textareaにSDPテキストを出し、それを画面上でコピペさせてボタンを押すようにしてある。
[Offer] 1. RTCPeerConnectionでOffer用SDPを作る(pc.createOffer())
[Answer] 2. Offer側のSDPをRTCPeerConnectionにセット(pc.setRemoteDescription())し、RTCPeerConnectionでAnswer用SDPを作る(pc.createAnswer())
[Offer] 3. Answer側のSDPをRTCPeerConnectionにセットする(pc.setRemoteDescription())
RTCPeerConnection接続でやることは、本来たった3ステップである。 双方でsetRemoteDescription()するのを一度だけですむように、OfferやAnswerをcreateした直後ではなく、 "icecnidatate"イベントでこれ以上ICE candidateが追加されない状態(event.candidateのデータがないと最後)になったあとで、 ICE candidate情報が全て埋まったSDPを使って、相手に渡すようにしている。
このフローの結果、(双方で)相手作成のデータチャネルを受け付けるdatachannelイベントを受けることで接続完了扱いにすることで、 双方からメッセージングを行える状態に入る
[Offer/Answer] メッセージを流す(dc.send())
[Offer/Answer] RTCPeerConnectionをpc.close()する
ちなみに、この100行内のうち20行ほど占める、copyボタンのイベント、 UI制御であるdisabled代入と、console.log()を全部コメントアウトしても動く。
0 notes
Link
HMACというのは、ハッシュ対象データへ秘密鍵(もしくはnonce)を加える暗号ハッシュである。
HMACは、個別のハッシュアルゴリズムに依存せず、 内部でハッシュアルゴリズムを抽象的に用いるジェネリックなアルゴリズムとなっている。 そのコードは、JavaScriptにして10行程度である。
0 notes
Link
ES6のPromiseは、拡張可能なclassとなっている。
ここでいう拡張可能というのは、Promiseの各メソッドで生成されるPromiseインスタンスは、 拡張されたclassのインスタンスになっているという意味である。 staticメソッドでも同様に拡張classのインスタンスになる。
単純な拡張可能Promise class例として、finally()メソッドをつけたFinally Promiseと done()メソッドをつけたDone Promiseを独立して用意した。
class生成の引数として2段重ねることで、finally()とdone()の双方を持つPromiseにすることができる。
0 notes
Link
ES6のPromiseは、拡張可能なclassとなっている点で興味深いものである。
ここでいう拡張可能というのは、Promiseの各メソッドで生成されるPromiseインスタンスは、 拡張されたclassのインスタンスになっているという意味である。 staticメソッドでも同様に拡張classのインスタンスになる。
cancel()メソッドを拡張したPromise、Cancellableを作ってみた。 ただcancel()メソッドがあるだけではなく、staticなall()やrace()も キャンセル対応にしている(race()は確定時点で他をcancelするようにしてある)。使い方はexample-basic.js参照(コンストラクタに渡す関数の戻り値でキャンセル実行時に呼びだされる関数を返す仕様)。
ちなみに、Promiseのようにclassを拡張可能にするには、インスタンス作成のコンストラクタは、 thisを起点に取り出した関数でnewする必要がある。 決して、ベタでclass名を埋めてははいけない。
また、多段で拡張可能にするには、functionで包んでextendsするclassを引数化する必要がある。 メソッドでも、現在は使っていない引数があるとして、それをそのままsuperに渡すようにする必要があるだろう (なぜなら、古い実装から順にextendsされるとは限らないからである)。
0 notes
Link
鳥の群れの動きをシミュレートするモデルBoidのcanvas実装。
demo
まず(2次元)ベクトル関数を用意し、それを使ってBoidを実装すれば、コードは非常に単純明快になる。 Boidというのは、
(敵から逃げる)
接触を避ける
周りについていく
群れの中央によるようにする
(ランダムにブレる)
から自分の向きを変えるのを毎ステップ行うだけである。 (このコードでは速度も変化するようにしているが、最高速に収束する。)
0 notes
Link
OpenGLのkhronosが提唱する3Dモデル(シーン)フォーマットとしてglTFがある。 COLLADAがモデル編集用であるのに対し、glTFはシーンのアウトプットフォーマットに位置する (pngの3D版みたいな位置にしたいらしい)。
ThreeJSには、すでにexamplesにこのglTFローダが入っている。 しかしThreeJSのexamplesプログラムは、いかんせんべた書きの余計な部分が大半のコードなので、使うときのリファレンスには向かない。 そこで、ロードで必要な部分だけでスリム化したのがこのコード(script.js)である。
0 notes
Link
SHA512アルゴリズムをWebAssembly Text Formatでコーディングしたもの。
sha512noupdate.wast: コード生成するupdate()関数の実装を含まない手書きwastプログラム (これ単体でもビルド可能で、関数もjavascript側から呼び出しチェックできる)
sha512update-call.js: update()関数の実装wastコードを生成するJavaScriptプログラム。sha512noupdate.wastに置いたサブ実装を呼び出す実装
sha512update-reduce-local.js: update()関数の実装wastコードを生成するJavaScriptプログラム。一切関数呼出ししない実装でかつローカル変数を使いまわして変数数を減らしたコード。
sha512.js: wasmモジュールをcommonsjsモジュール化するコード
main.js: coreutilsのsha512sumと同じアウトプット、チェックをするコマンドラインコード
package.json: コード生成及び、binaryenのwams-asを使うビルドスクリプト。npx実行にも対応
JavaScriptと違い、WebAssemblyでは64ビット変数の演算が可能なので、sha256とさほど変わらず実装できるのが良い。
0 notes