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)とかを再帰的に呼び出して、ぐるぐる回るようになっている。メインループぽい。

ざっとこんなところで。