1
- <!doctype html>
1
+ <!DOCTYPE html>
2
2
3
3
< head >
4
- < title > Postgres in browser</ title >
5
- < link rel ="
stylesheet "
href ="
https://unpkg.com/[email protected] /css/xterm.css "
/>
6
- < link rel ="stylesheet " href ="./styles.css " />
7
- < script src ="
https://unpkg.com/[email protected] /lib/xterm-addon-fit.js "
> </ script >
8
- < script src ="
https://unpkg.com/[email protected] /lib/xterm.js "
> </ script >
9
- < script src ="./lib/libv86.js "> </ script >
10
- < script >
11
- window . onload = ( ) => {
12
- const baseOptions = {
13
- wasm_path : "./lib/v86.wasm" ,
14
- memory_size : 128 * 1024 * 1024 ,
15
- filesystem : {
16
- basefs : "filesystem/filesystem.json" ,
17
- baseurl : "filesystem/" ,
18
- } ,
19
- screen_container : document . getElementById ( "screen_container" ) ,
20
- serial_container_xtermjs : document . getElementById ( "terminal" ) ,
21
- network_relay_url : "wss://relay.widgetry.org/" ,
22
- autostart : true ,
23
- disable_keyboard : true ,
24
- disable_mouse : true ,
25
- disable_speaker : true ,
26
- acpi : true ,
27
- } ;
28
-
29
- const params = ( new URL ( document . location ) ) . searchParams ;
30
- const boot = params . get ( "boot" ) === "true" ;
31
-
32
- if ( boot ) {
33
- document . getElementById ( "screen_container" ) . style = 'display:block' ;
34
- document . getElementById ( "terminal" ) . style = '' ;
35
- }
36
-
37
- const bzimageUrl = "./filesystem/27d6e559.bin" ;
38
- const options = {
39
- ...baseOptions ,
40
- ...( boot ? {
41
- bzimage : {
42
- url : bzimageUrl ,
43
- } ,
44
- cmdline : [
45
- "rw" ,
46
- "root=host9p rootfstype=9p rootflags=version=9p2000.L,trans=virtio,cache=loose quiet acpi=off console=ttyS0 tsc=reliable mitigations=off random.trust_cpu=on nowatchdog page_poison=on" ,
47
- ] . join ( " " ) ,
48
- bios : {
49
- url : "./bios/seabios.bin" ,
50
- } ,
51
- vga_bios : {
52
- url : "./bios/vgabios.bin" ,
53
- } ,
54
- } : { initial_state : { url : "./state/v86state.bin.zst" } } )
55
- } ;
56
-
57
- var emulator = new V86Starter ( options ) ;
58
-
59
- function initTerm ( ) {
60
- const fitAddon = new FitAddon . FitAddon ( ) ;
61
- emulator . serial_adapter . term . loadAddon ( fitAddon ) ;
62
- fitAddon . fit ( ) ;
63
- window . addEventListener ( "resize" , ( ) => fitAddon . fit ( ) ) ;
4
+ < title > Postgres in browser</ title >
5
+ < link rel ="
stylesheet "
href ="
https://unpkg.com/[email protected] /css/xterm.css "
/>
6
+ < link rel ="stylesheet " href ="./styles.css " />
7
+ < script src ="
https://unpkg.com/[email protected] /lib/xterm-addon-fit.js "
> </ script >
8
+ < script src ="
https://unpkg.com/[email protected] /lib/xterm.js "
> </ script >
9
+ < script src ="./lib/libv86.js "> </ script >
10
+ < script >
11
+ window . onload = ( ) => {
12
+ const baseOptions = {
13
+ wasm_path : "./lib/v86.wasm" ,
14
+ memory_size : 128 * 1024 * 1024 ,
15
+ filesystem : {
16
+ basefs : "filesystem/filesystem.json" ,
17
+ baseurl : "filesystem/" ,
18
+ } ,
19
+ screen_container : document . getElementById ( "screen_container" ) ,
20
+ serial_container_xtermjs : document . getElementById ( "terminal" ) ,
21
+ network_relay_url : "wss://relay.widgetry.org/" ,
22
+ autostart : true ,
23
+ disable_keyboard : true ,
24
+ disable_mouse : true ,
25
+ disable_speaker : true ,
26
+ acpi : true ,
27
+ } ;
28
+
29
+ const params = new URL ( document . location ) . searchParams ;
30
+ const boot = params . get ( "boot" ) === "true" ;
31
+
32
+ if ( boot ) {
33
+ document . getElementById ( "screen_container" ) . style = "display:block" ;
34
+ document . getElementById ( "terminal" ) . style = "" ;
35
+ }
36
+
37
+ const bzimageUrl = "./filesystem/27d6e559.bin" ;
38
+ const options = {
39
+ ...baseOptions ,
40
+ ...( boot
41
+ ? {
42
+ bzimage : {
43
+ url : bzimageUrl ,
44
+ } ,
45
+ cmdline : [
46
+ "rw" ,
47
+ "root=host9p rootfstype=9p rootflags=version=9p2000.L,trans=virtio,cache=loose quiet acpi=off console=ttyS0 tsc=reliable mitigations=off random.trust_cpu=on nowatchdog page_poison=on" ,
48
+ ] . join ( " " ) ,
49
+ bios : {
50
+ url : "./bios/seabios.bin" ,
51
+ } ,
52
+ vga_bios : {
53
+ url : "./bios/vgabios.bin" ,
54
+ } ,
64
55
}
65
-
66
- function sendBackgroundCommands ( commands ) {
67
- const filename = `${ ( Math . random ( ) + 1 ) . toString ( 36 ) . substring ( 7 ) } .sh`
68
- emulator . create_file ( `/inbox/${ filename } ` , ( new TextEncoder ( 'UTF-8' ) ) . encode ( commands . join ( "\n" ) ) ) ;
69
- }
70
-
71
- if ( ! boot ) {
72
- emulator . add_listener ( "emulator-ready" , function ( ) {
73
- initTerm ( ) ;
74
- setTimeout ( ( ) => {
75
- sendBackgroundCommands ( [
76
- "/etc/init.d/S40network restart"
77
- ] ) ;
78
- emulator . serial0_send ( `\\! stty rows ${ emulator . serial_adapter . term . rows } cols ${ emulator . serial_adapter . term . cols } && reset\n` ) ;
79
- emulator . serial_adapter . term . focus ( ) ;
80
- } , 0 ) ;
81
- } ) ;
82
- }
83
-
84
- var state ;
85
-
86
- document . getElementById ( "save_restore" ) . onclick = async function ( ) {
87
- var button = this ;
88
-
89
- if ( state ) {
90
- button . value = "Save state" ;
91
- await emulator . restore_state ( state ) ;
92
- state = undefined ;
93
- }
94
- else {
95
- const new_state = await emulator . save_state ( ) ;
96
- console . log ( "Saved state of " + new_state . byteLength + " bytes" ) ;
97
- button . value = "Restore state" ;
98
- state = new_state ;
99
- }
100
-
101
- button . blur ( ) ;
102
- } ;
103
-
104
- document . getElementById ( "save_file" ) . onclick = async function ( ) {
105
- const new_state = await emulator . save_state ( ) ;
106
- var a = document . createElement ( "a" ) ;
107
- a . download = "v86state.bin" ;
108
- a . href = window . URL . createObjectURL ( new Blob ( [ new_state ] ) ) ;
109
- a . dataset . downloadurl = "application/octet-stream:" + a . download + ":" + a . href ;
110
- a . click ( ) ;
111
-
112
- this . blur ( ) ;
56
+ : { initial_state : { url : "./state/v86state.bin.zst" } } ) ,
57
+ } ;
58
+
59
+ var emulator = new V86Starter ( options ) ;
60
+
61
+ function initTerm ( ) {
62
+ const fitAddon = new FitAddon . FitAddon ( ) ;
63
+ emulator . serial_adapter . term . loadAddon ( fitAddon ) ;
64
+ fitAddon . fit ( ) ;
65
+ window . addEventListener ( "resize" , ( ) => fitAddon . fit ( ) ) ;
66
+ }
67
+
68
+ function sendBackgroundCommands ( commands ) {
69
+ const filename = `${ ( Math . random ( ) + 1 ) . toString ( 36 ) . substring ( 7 ) } .sh` ;
70
+ emulator . create_file (
71
+ `/inbox/${ filename } ` ,
72
+ new TextEncoder ( "UTF-8" ) . encode ( commands . join ( "\n" ) )
73
+ ) ;
74
+ }
75
+
76
+ if ( ! boot ) {
77
+ emulator . add_listener ( "emulator-ready" , function ( ) {
78
+ initTerm ( ) ;
79
+ setTimeout ( ( ) => {
80
+ sendBackgroundCommands ( [ "/etc/init.d/S40network restart" ] ) ;
81
+ emulator . serial0_send (
82
+ `\\! stty rows ${ emulator . serial_adapter . term . rows } cols ${ emulator . serial_adapter . term . cols } && reset\n`
83
+ ) ;
84
+ emulator . serial_adapter . term . focus ( ) ;
85
+ } , 0 ) ;
86
+ } ) ;
87
+ }
88
+
89
+ var state ;
90
+
91
+ document . getElementById ( "save_restore" ) . onclick = async function ( ) {
92
+ var button = this ;
93
+
94
+ if ( state ) {
95
+ button . value = "Save state" ;
96
+ await emulator . restore_state ( state ) ;
97
+ state = undefined ;
98
+ } else {
99
+ const new_state = await emulator . save_state ( ) ;
100
+ console . log ( "Saved state of " + new_state . byteLength + " bytes" ) ;
101
+ button . value = "Restore state" ;
102
+ state = new_state ;
103
+ }
104
+
105
+ button . blur ( ) ;
106
+ } ;
107
+
108
+ document . getElementById ( "save_file" ) . onclick = async function ( ) {
109
+ const new_state = await emulator . save_state ( ) ;
110
+ var a = document . createElement ( "a" ) ;
111
+ a . download = "v86state.bin" ;
112
+ a . href = window . URL . createObjectURL ( new Blob ( [ new_state ] ) ) ;
113
+ a . dataset . downloadurl =
114
+ "application/octet-stream:" + a . download + ":" + a . href ;
115
+ a . click ( ) ;
116
+
117
+ this . blur ( ) ;
118
+ } ;
119
+
120
+ document . getElementById ( "restore_file" ) . onchange = function ( ) {
121
+ if ( this . files . length ) {
122
+ var filereader = new FileReader ( ) ;
123
+ emulator . stop ( ) ;
124
+
125
+ filereader . onload = async function ( e ) {
126
+ await emulator . restore_state ( e . target . result ) ;
127
+ emulator . run ( ) ;
128
+ } ;
129
+
130
+ filereader . readAsArrayBuffer ( this . files [ 0 ] ) ;
131
+
132
+ this . value = "" ;
133
+ }
134
+
135
+ this . blur ( ) ;
136
+ } ;
137
+
138
+ document . getElementById ( "upload_files" ) . onchange = function ( e ) {
139
+ var files = e . target . files ;
140
+ for ( var i = 0 ; i < files . length ; i ++ ) {
141
+ var reader = new FileReader ( ) ;
142
+ reader . onload = ( function ( file ) {
143
+ return function ( e ) {
144
+ var data = new TextEncoder ( "UTF-8" ) . encode ( e . target . result ) ;
145
+ emulator . create_file ( "/" + file . name , data ) ;
146
+ console . log ( "uploaded " + file . name ) ;
113
147
} ;
114
-
115
- document . getElementById ( "restore_file" ) . onchange = function ( ) {
116
- if ( this . files . length ) {
117
- var filereader = new FileReader ( ) ;
118
- emulator . stop ( ) ;
119
-
120
- filereader . onload = async function ( e ) {
121
- await emulator . restore_state ( e . target . result ) ;
122
- emulator . run ( ) ;
123
- } ;
124
-
125
- filereader . readAsArrayBuffer ( this . files [ 0 ] ) ;
126
-
127
- this . value = "" ;
128
- }
129
-
130
- this . blur ( ) ;
131
- } ;
132
-
133
- document . getElementById ( "upload_files" ) . onchange = function ( e ) {
134
- var files = e . target . files ;
135
- for ( var i = 0 ; i < files . length ; i ++ ) {
136
- var reader = new FileReader ( ) ;
137
- reader . onload = function ( file ) {
138
- return function ( e ) {
139
- var data = ( new TextEncoder ( 'UTF-8' ) ) . encode ( e . target . result ) ;
140
- emulator . create_file ( "/" + file . name , data ) ;
141
- console . log ( "uploaded " + file . name ) ;
142
- }
143
- } ( files [ i ] ) ;
144
- reader . readAsText ( files [ i ] ) ;
145
- }
146
- }
147
- } ;
148
-
149
- </ script >
148
+ } ) ( files [ i ] ) ;
149
+ reader . readAsText ( files [ i ] ) ;
150
+ }
151
+ } ;
152
+
153
+ const uploadBtns = document . getElementsByClassName ( "upload-btn" ) ;
154
+ for ( let btn of uploadBtns ) {
155
+ btn . addEventListener ( "click" , ( event ) => {
156
+ const input = btn . getElementsByTagName ( "input" ) [ 0 ] ;
157
+ input . click ( event ) ;
158
+ } ) ;
159
+ }
160
+ } ;
161
+ </ script >
150
162
</ head >
151
163
152
164
< body >
153
- < div id ="screen_container " style ="display:none ">
154
- < div > </ div >
155
- < canvas > </ canvas >
156
- </ div >
165
+ < div id ="screen_container " style ="display: none ">
166
+ < div > </ div >
167
+ < canvas > </ canvas >
168
+ </ div >
169
+ < div id ="menu ">
157
170
< div >
158
- < input id ="save_restore " type ="button " value ="Save state ">
159
- < input id ="save_file " type ="button " value ="Save state to file ">
160
- Restore from file: < input id ="restore_file " type ="file ">
161
- Upload files to the emulator: < input id ="upload_files " type ="file " multiple >
171
+ < input id ="save_restore " type ="button " value ="Save state " />
172
+ < input id ="save_file " type ="button " value ="Save state to file " />
173
+ </ div >
174
+ < div style ="display: flex ">
175
+ < div class ="upload-btn ">
176
+ < input id ="restore_file " type ="file " hidden />
177
+ < p > Restore from file</ p >
178
+ </ div >
179
+ < div class ="upload-btn ">
180
+ < input id ="upload_files " type ="file " multiple hidden />
181
+ < p > Upload files to the emulator</ p >
182
+ </ div >
162
183
</ div >
163
- < hr />
164
- < div class ="container ">
165
- < div class ="xterminal ">
166
- < div id ="terminal "> </ div >
167
- </ div >
184
+ </ div >
185
+ < div class ="container ">
186
+ < div class ="xterminal ">
187
+ < div id ="terminal "> </ div >
168
188
</ div >
169
- </ body >
189
+ </ div >
190
+ </ body >
0 commit comments