jslinuxのコードをちょっと覗いてみた
メモ。
昨日あたりから一部で人気のjslinux。
何をやってるかよく分からなかったのでちょっとだけjsのソースを見てみました。
まずHTMLのソース(の抜粋)。
<body onload="start()"> <script src="term.js"></script> <script src="cpux86.js"></script>
term.jsはJSでterminalをごりごり書いてる感じ。なので、本体はcpux86.jsとstart()メソッド。
start()はcpux86.jsの中にある。cpux86.jsは名前からしてx86のCPUエミュレータ+αとのこと。このファイルの一番最後の部分を整形したのが下記。
function start(){ var Hf,i,start,If,Jf; if(!Gf()){ aa.writeln(""); aa.writeln("Your browser does not support the W3C Typed Arrays and this version of JS/Linux needs them.\n"); aa.writeln("If you really want to try out JS/Linux, you can use the following browsers:"); aa.writeln("- Firefox 4.x"); aa.writeln("- Google Chrome 11"); return; } ya=new ea(); Qe=new vf(); If=32*1024*1024; ya.phys_mem_resize(If); ya.load_binary("vmlinux26.bin",0x00100000); Jf=ya.load_binary("root.bin",0x00400000); start=0x10000; ya.load_binary("linuxstart.bin",start); ya.eip=start; ya.regs[0]=If; ya.regs[3]=Jf; ya.cycle_count=0; ya.ld8_port=Qe.ld8_port.bind(Qe); ya.ld16_port=Qe.ld16_port.bind(Qe); ya.ld32_port=Qe.ld32_port.bind(Qe); ya.st8_port=Qe.st8_port.bind(Qe); ya.st16_port=Qe.st16_port.bind(Qe); ya.st32_port=Qe.st32_port.bind(Qe); ya.get_hard_intno=Qe.pic.get_hard_intno.bind(Qe.pic); xf=Date.now(); setTimeout(yf,10); } Ef();
最後の「Ef();」はstart()とは関係ないけど、cpux86.jsが読み込まれるタイミングで実行される。中身は下記。
function Ef(){aa=new Term(80,30,Ff);aa.open();}
さっきのterm.jsを呼び出してる。ターミナルの初期化。
もとに戻ってstart()の中身。if文の条件で使ってるGf()の定義は下記。
function Gf(){return(window.Uint8Array&&window.Uint16Array&&window.Int32Array&&window.ArrayBuffer);}
要するにTyped Arraysが使えるか調べてるっぽい。
ea()、vf()は飛ばして、物理メモリを定義したあと、ya.load_binary()を呼び出してる。呼び出す時に渡しているのはvmlinux26.bin、root.bin、linuxstart.bin。linux本体ぽい。
load_binary()の定義は下記。
ea.prototype.load_binary=function Je(Ke,ha){ var Le,Me,fd,i,Ne; Le=new XMLHttpRequest(); Le.open('GET',Ke,false); if('responseType'in Le){ Le.responseType='arraybuffer'; }else{ Le.overrideMimeType('text/plain;charset=x-user-defined'); } Le.send(null); if(Le.status!=200&&Le.status!=0){ throw"Error while loading "+Ke; } if(Le.mozResponseArrayBuffer){ Me=Le.mozResponseArrayBuffer; }else if('responseType'in Le){ Me=Le.response; }else{ Me=Le.responseText; } fd=Me.byteLength; Ne=new Uint8Array(Me,0,fd); for(i=0;i<fd;i++){ this.st8_phys(ha+i,Ne[i]); } return fd; };
ざっくり、XMLHttpRequest()でファイルをネットから落として、仮想マシンのメモリに突っ込んでるっぽい。サイトは明記されてないので、ここでは http://bellard.org/jslinux/vmlinux26.bin を読み込むはず。
load_binary()したあとは、その他の値を設定して、yf()を呼び出してるっぽい。yf()は内部でsetTimeout(yf,10)とかを再帰的に呼び出して、ぐるぐる回るようになっている。メインループぽい。
ざっとこんなところで。