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/xterm@4.19.0/css/xterm.css " />
6
- < link rel ="stylesheet " href ="./styles.css " />
7
- < script src ="https://unpkg.com/xterm-addon-fit@0.5.0/lib/xterm-addon-fit.js "> </ script >
8
- < script src ="https://unpkg.com/xterm@4.19.0/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/xterm@4.19.0/css/xterm.css " />
6
+ < link rel ="stylesheet " href ="./styles.css " />
7
+ < script src ="https://unpkg.com/xterm-addon-fit@0.5.0/lib/xterm-addon-fit.js "> </ script >
8
+ < script src ="https://unpkg.com/xterm@4.19.0/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/123ccf58.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
+ if ( ! boot ) {
62
+ emulator . add_listener ( "emulator-ready" , function ( ) {
63
+ const fitAddon = new FitAddon . FitAddon ( ) ;
64
+ emulator . serial_adapter . term . loadAddon ( fitAddon ) ;
65
+ fitAddon . fit ( ) ;
66
+ window . addEventListener ( "resize" , ( ) => fitAddon . fit ( ) ) ;
67
+ // emulator.serial_adapter.term.setOption("allowTransparency", true);
68
+ // emulator.serial_adapter.term.setOption("theme", { background: "transparent" });
69
+ setTimeout ( ( ) => {
70
+ emulator . serial0_send ( "/etc/init.d/S40network restart\n" ) ;
71
+ emulator . serial0_send ( "psql -U postgres\n" ) ;
72
+ emulator . serial0_send ( '\\! echo "boot_completed"; reset\n' ) ;
73
+ } , 0 ) ;
74
+ } ) ;
75
+
76
+ function handleBoot ( line ) {
77
+ if ( line . startsWith ( "postgres=# boot_completed" ) ) {
78
+ emulator . remove_listener ( handleBoot ) ;
79
+ setTimeout ( ( ) => {
80
+ document . getElementById ( "terminal" ) . style = "filter: none;" ;
81
+ emulator . serial_adapter . term . focus ( ) ;
82
+ } , 300 ) ;
83
+ }
84
+ }
85
+ emulator . add_listener ( "serial0-output-line" , handleBoot ) ;
86
+ }
87
+
88
+ var state ;
89
+
90
+ document . getElementById ( "save_restore" ) . onclick = async function ( ) {
91
+ var button = this ;
92
+
93
+ if ( state ) {
94
+ button . value = "Save state" ;
95
+ await emulator . restore_state ( state ) ;
96
+ state = undefined ;
97
+ } else {
98
+ const new_state = await emulator . save_state ( ) ;
99
+ console . log ( "Saved state of " + new_state . byteLength + " bytes" ) ;
100
+ button . value = "Restore state" ;
101
+ state = new_state ;
102
+ }
103
+
104
+ button . blur ( ) ;
105
+ } ;
106
+
107
+ document . getElementById ( "save_file" ) . onclick = async function ( ) {
108
+ const new_state = await emulator . save_state ( ) ;
109
+ var a = document . createElement ( "a" ) ;
110
+ a . download = "v86state.bin" ;
111
+ a . href = window . URL . createObjectURL ( new Blob ( [ new_state ] ) ) ;
112
+ a . dataset . downloadurl =
113
+ "application/octet-stream:" + a . download + ":" + a . href ;
114
+ a . click ( ) ;
115
+
116
+ this . blur ( ) ;
117
+ } ;
118
+
119
+ document . getElementById ( "restore_file" ) . onchange = function ( ) {
120
+ if ( this . files . length ) {
121
+ var filereader = new FileReader ( ) ;
122
+ emulator . stop ( ) ;
123
+
124
+ filereader . onload = async function ( e ) {
125
+ await emulator . restore_state ( e . target . result ) ;
126
+ emulator . run ( ) ;
127
+ } ;
128
+
129
+ filereader . readAsArrayBuffer ( this . files [ 0 ] ) ;
130
+
131
+ this . value = "" ;
132
+ }
133
+
134
+ this . blur ( ) ;
135
+ } ;
136
+
137
+ document . getElementById ( "upload_files" ) . onchange = function ( e ) {
138
+ var files = e . target . files ;
139
+ for ( var i = 0 ; i < files . length ; i ++ ) {
140
+ var reader = new FileReader ( ) ;
141
+ reader . onload = ( function ( file ) {
142
+ return function ( e ) {
143
+ var data = new TextEncoder ( "UTF-8" ) . encode ( e . target . result ) ;
144
+ emulator . create_file ( "/" + file . name , data ) ;
145
+ console . log ( "uploaded " + file . name ) ;
113
146
} ;
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 >
147
+ } ) ( files [ i ] ) ;
148
+ reader . readAsText ( files [ i ] ) ;
149
+ }
150
+ } ;
151
+
152
+ const uploadBtns = document . getElementsByClassName ( "upload-btn" ) ;
153
+ for ( let btn of uploadBtns ) {
154
+ btn . addEventListener ( "click" , ( event ) => {
155
+ const input = btn . getElementsByTagName ( "input" ) [ 0 ] ;
156
+ input . click ( event ) ;
157
+ } ) ;
158
+ }
159
+ } ;
160
+ </ script >
150
161
</ head >
151
162
152
163
< body >
153
- < div id ="screen_container " style ="display:none ">
154
- < div > </ div >
155
- < canvas > </ canvas >
156
- </ div >
164
+ < div id ="screen_container " style ="display: none ">
165
+ < div > </ div >
166
+ < canvas > </ canvas >
167
+ </ div >
168
+ < div id ="menu ">
157
169
< 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 >
170
+ < input id ="save_restore " type ="button " value ="Save state " />
171
+ < input id ="save_file " type ="button " value ="Save state to file " />
172
+ </ div >
173
+ < div style ="display: flex ">
174
+ < div class ="upload-btn ">
175
+ < input id ="restore_file " type ="file " hidden />
176
+ < p > Restore from file</ p >
177
+ </ div >
178
+ < div class ="upload-btn ">
179
+ < input id ="upload_files " type ="file " multiple hidden />
180
+ < p > Upload files to the emulator</ p >
181
+ </ div >
162
182
</ div >
163
- < hr />
164
- < div class ="container ">
165
- < div class ="xterminal ">
166
- < div id ="terminal "> </ div >
167
- </ div >
183
+ </ div >
184
+ < div class ="container ">
185
+ < div class ="xterminal " style ="margin-right: 25px ">
186
+ < div id ="terminal " style ="filter: blur(3px) "> </ div >
168
187
</ div >
169
- </ body >
188
+ </ div >
189
+ </ body >
0 commit comments