Initial commit
This commit is contained in:
commit
512332d439
27 changed files with 959 additions and 0 deletions
20
README.md
Normal file
20
README.md
Normal file
|
@ -0,0 +1,20 @@
|
|||
Source code for the webvm.io webpage.
|
||||
|
||||
Please use github.com/webvm/issues to signal any bug.
|
||||
|
||||
|
||||
This project depends on xterm.js (https://xtermjs.org/) and on its add-on xterm-addon-fit
|
||||
|
||||
To update the xterm-related files do:
|
||||
```
|
||||
mkdir build
|
||||
cd build
|
||||
npm install --save xterm
|
||||
npm install --save xterm-addon-fit
|
||||
cd ../xterm
|
||||
cp ../build/node_modules/xterm/lib/xterm.js .
|
||||
cp ../build/node_modules/xterm/css/xterm.css .
|
||||
cp ../build/node_modules/xterm-addon-fit/lib/xterm-addon-fit.js .
|
||||
cd ..
|
||||
rm -r build
|
||||
```
|
BIN
assets/webvm.jpeg
Normal file
BIN
assets/webvm.jpeg
Normal file
Binary file not shown.
After Width: | Height: | Size: 102 KiB |
13
examples/c/Makefile
Normal file
13
examples/c/Makefile
Normal file
|
@ -0,0 +1,13 @@
|
|||
SRCS = $(wildcard *.c)
|
||||
|
||||
PROGS = $(patsubst %.c,%,$(SRCS))
|
||||
|
||||
all: $(PROGS)
|
||||
|
||||
%: %.c
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f $(PROGS)
|
||||
|
||||
.PHONY: all clean
|
12
examples/c/env.c
Normal file
12
examples/c/env.c
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include <stdio.h>
|
||||
|
||||
// Most of the C compilers support a third parameter to main which
|
||||
// store all envorinment variables
|
||||
int main(int argc, char *argv[], char * envp[])
|
||||
{
|
||||
int i;
|
||||
for (i = 0; envp[i] != NULL; i++)
|
||||
printf("\n%s", envp[i]);
|
||||
getchar();
|
||||
return 0;
|
||||
}
|
6
examples/c/helloworld.c
Normal file
6
examples/c/helloworld.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("Hello, World!\n");
|
||||
}
|
7
examples/c/link.c
Normal file
7
examples/c/link.c
Normal file
|
@ -0,0 +1,7 @@
|
|||
#include <unistd.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
link("env", "env3");
|
||||
return 0;
|
||||
}
|
10
examples/c/openat.c
Normal file
10
examples/c/openat.c
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int ret = openat(AT_FDCWD, "/dev/tty", 0x88102, 0);
|
||||
printf("return value is %d and errno is %d\n", ret, errno);
|
||||
}
|
||||
|
17
examples/c/waitpid.c
Normal file
17
examples/c/waitpid.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int status;
|
||||
|
||||
pid_t p = getpid();
|
||||
// waitpid takes a children's pid, not the current process one
|
||||
// if the pid is not a children of the current process, it returns -ECHILD
|
||||
pid_t res = waitpid(1001, &status, WNOHANG);
|
||||
|
||||
printf("res is %d, p is %d and errno is %d\n", res, p, errno);
|
||||
|
||||
}
|
20
examples/lua/fizzbuzz.lua
Normal file
20
examples/lua/fizzbuzz.lua
Normal file
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env luajit
|
||||
cfizz,cbuzz=0,0
|
||||
for i=1,20 do
|
||||
cfizz=cfizz+1
|
||||
cbuzz=cbuzz+1
|
||||
io.write(i .. ": ")
|
||||
if cfizz~=3 and cbuzz~=5 then
|
||||
io.write(i)
|
||||
else
|
||||
if cfizz==3 then
|
||||
io.write("Fizz")
|
||||
cfizz=0
|
||||
end
|
||||
if cbuzz==5 then
|
||||
io.write("Buzz")
|
||||
cbuzz=0
|
||||
end
|
||||
end
|
||||
io.write("\n")
|
||||
end
|
12
examples/lua/sorting.lua
Normal file
12
examples/lua/sorting.lua
Normal file
|
@ -0,0 +1,12 @@
|
|||
fruits = {"banana","orange","apple","grapes"}
|
||||
|
||||
for k,v in ipairs(fruits) do
|
||||
print(k,v)
|
||||
end
|
||||
|
||||
table.sort(fruits)
|
||||
print("sorted table")
|
||||
|
||||
for k,v in ipairs(fruits) do
|
||||
print(k,v)
|
||||
end
|
19
examples/lua/symmetric_difference.lua
Normal file
19
examples/lua/symmetric_difference.lua
Normal file
|
@ -0,0 +1,19 @@
|
|||
A = { ["John"] = true, ["Bob"] = true, ["Mary"] = true, ["Elena"] = true }
|
||||
B = { ["Jim"] = true, ["Mary"] = true, ["John"] = true, ["Bob"] = true }
|
||||
|
||||
A_B = {}
|
||||
for a in pairs(A) do
|
||||
if not B[a] then A_B[a] = true end
|
||||
end
|
||||
|
||||
B_A = {}
|
||||
for b in pairs(B) do
|
||||
if not A[b] then B_A[b] = true end
|
||||
end
|
||||
|
||||
for a_b in pairs(A_B) do
|
||||
print( a_b )
|
||||
end
|
||||
for b_a in pairs(B_A) do
|
||||
print( b_a )
|
||||
end
|
6
examples/nodejs/environment.js
Normal file
6
examples/nodejs/environment.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
console.log("process.uptime = ", global.process.uptime());
|
||||
console.log("process.title = ", global.process.title);
|
||||
console.log("process version = ", global.process.version);
|
||||
console.log("process.platform = ", global.process.platform);
|
||||
console.log("process.cwd = ", global.process.cwd());
|
||||
console.log("process.uptime = ", global.process.uptime());
|
161
examples/nodejs/nbody.js
Normal file
161
examples/nodejs/nbody.js
Normal file
|
@ -0,0 +1,161 @@
|
|||
const PI = Math.PI;
|
||||
const SOLAR_MASS = 4 * PI * PI;
|
||||
const DAYS_PER_YEAR = 365.24;
|
||||
|
||||
function Body(x, y, z, vx, vy, vz, mass) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.vx = vx;
|
||||
this.vy = vy;
|
||||
this.vz = vz;
|
||||
this.mass = mass;
|
||||
}
|
||||
|
||||
function Jupiter() {
|
||||
return new Body(
|
||||
4.84143144246472090e+00,
|
||||
-1.16032004402742839e+00,
|
||||
-1.03622044471123109e-01,
|
||||
1.66007664274403694e-03 * DAYS_PER_YEAR,
|
||||
7.69901118419740425e-03 * DAYS_PER_YEAR,
|
||||
-6.90460016972063023e-05 * DAYS_PER_YEAR,
|
||||
9.54791938424326609e-04 * SOLAR_MASS
|
||||
);
|
||||
}
|
||||
|
||||
function Saturn() {
|
||||
return new Body(
|
||||
8.34336671824457987e+00,
|
||||
4.12479856412430479e+00,
|
||||
-4.03523417114321381e-01,
|
||||
-2.76742510726862411e-03 * DAYS_PER_YEAR,
|
||||
4.99852801234917238e-03 * DAYS_PER_YEAR,
|
||||
2.30417297573763929e-05 * DAYS_PER_YEAR,
|
||||
2.85885980666130812e-04 * SOLAR_MASS
|
||||
);
|
||||
}
|
||||
|
||||
function Uranus() {
|
||||
return new Body(
|
||||
1.28943695621391310e+01,
|
||||
-1.51111514016986312e+01,
|
||||
-2.23307578892655734e-01,
|
||||
2.96460137564761618e-03 * DAYS_PER_YEAR,
|
||||
2.37847173959480950e-03 * DAYS_PER_YEAR,
|
||||
-2.96589568540237556e-05 * DAYS_PER_YEAR,
|
||||
4.36624404335156298e-05 * SOLAR_MASS
|
||||
);
|
||||
}
|
||||
|
||||
function Neptune() {
|
||||
return new Body(
|
||||
1.53796971148509165e+01,
|
||||
-2.59193146099879641e+01,
|
||||
1.79258772950371181e-01,
|
||||
2.68067772490389322e-03 * DAYS_PER_YEAR,
|
||||
1.62824170038242295e-03 * DAYS_PER_YEAR,
|
||||
-9.51592254519715870e-05 * DAYS_PER_YEAR,
|
||||
5.15138902046611451e-05 * SOLAR_MASS
|
||||
);
|
||||
}
|
||||
|
||||
function Sun() {
|
||||
return new Body(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, SOLAR_MASS);
|
||||
}
|
||||
|
||||
const bodies = Array(Sun(), Jupiter(), Saturn(), Uranus(), Neptune());
|
||||
|
||||
function offsetMomentum() {
|
||||
let px = 0;
|
||||
let py = 0;
|
||||
let pz = 0;
|
||||
const size = bodies.length;
|
||||
for (let i = 0; i < size; i++) {
|
||||
const body = bodies[i];
|
||||
const mass = body.mass;
|
||||
px += body.vx * mass;
|
||||
py += body.vy * mass;
|
||||
pz += body.vz * mass;
|
||||
}
|
||||
|
||||
const body = bodies[0];
|
||||
body.vx = -px / SOLAR_MASS;
|
||||
body.vy = -py / SOLAR_MASS;
|
||||
body.vz = -pz / SOLAR_MASS;
|
||||
}
|
||||
|
||||
function advance(dt) {
|
||||
const size = bodies.length;
|
||||
|
||||
for (let i = 0; i < size; i++) {
|
||||
const bodyi = bodies[i];
|
||||
let vxi = bodyi.vx;
|
||||
let vyi = bodyi.vy;
|
||||
let vzi = bodyi.vz;
|
||||
for (let j = i + 1; j < size; j++) {
|
||||
const bodyj = bodies[j];
|
||||
const dx = bodyi.x - bodyj.x;
|
||||
const dy = bodyi.y - bodyj.y;
|
||||
const dz = bodyi.z - bodyj.z;
|
||||
|
||||
const d2 = dx * dx + dy * dy + dz * dz;
|
||||
const mag = dt / (d2 * Math.sqrt(d2));
|
||||
|
||||
const massj = bodyj.mass;
|
||||
vxi -= dx * massj * mag;
|
||||
vyi -= dy * massj * mag;
|
||||
vzi -= dz * massj * mag;
|
||||
|
||||
const massi = bodyi.mass;
|
||||
bodyj.vx += dx * massi * mag;
|
||||
bodyj.vy += dy * massi * mag;
|
||||
bodyj.vz += dz * massi * mag;
|
||||
}
|
||||
bodyi.vx = vxi;
|
||||
bodyi.vy = vyi;
|
||||
bodyi.vz = vzi;
|
||||
}
|
||||
|
||||
for (let i = 0; i < size; i++) {
|
||||
const body = bodies[i];
|
||||
body.x += dt * body.vx;
|
||||
body.y += dt * body.vy;
|
||||
body.z += dt * body.vz;
|
||||
}
|
||||
}
|
||||
|
||||
function energy() {
|
||||
let e = 0;
|
||||
const size = bodies.length;
|
||||
|
||||
for (let i = 0; i < size; i++) {
|
||||
const bodyi = bodies[i];
|
||||
|
||||
e += 0.5 * bodyi.mass * ( bodyi.vx * bodyi.vx + bodyi.vy * bodyi.vy + bodyi.vz * bodyi.vz );
|
||||
|
||||
for (let j = i + 1; j < size; j++) {
|
||||
const bodyj = bodies[j];
|
||||
const dx = bodyi.x - bodyj.x;
|
||||
const dy = bodyi.y - bodyj.y;
|
||||
const dz = bodyi.z - bodyj.z;
|
||||
|
||||
const distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
||||
e -= (bodyi.mass * bodyj.mass) / distance;
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
const n = +50000000;
|
||||
|
||||
offsetMomentum();
|
||||
|
||||
console.log(energy().toFixed(9));
|
||||
const start = Date.now();
|
||||
for (let i = 0; i < n; i++) {
|
||||
advance(0.01);
|
||||
}
|
||||
const end = Date.now();
|
||||
console.log(energy().toFixed(9));
|
||||
console.log("elapsed:",end-start);
|
31
examples/nodejs/primes.js
Normal file
31
examples/nodejs/primes.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
(function () {
|
||||
|
||||
function isPrime(p) {
|
||||
const upper = Math.sqrt(p);
|
||||
for(let i = 2; i <= upper; i++) {
|
||||
if (p % i === 0 ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return n-th prime
|
||||
function prime(n) {
|
||||
if (n < 1) {
|
||||
throw Error("n too small: " + n);
|
||||
}
|
||||
let count = 0;
|
||||
let result = 1;
|
||||
while(count < n) {
|
||||
result++;
|
||||
if (isPrime(result)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
console.log("your prime is ", prime(100000));
|
||||
|
||||
}());
|
16
examples/nodejs/wasm.js
Normal file
16
examples/nodejs/wasm.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
(function (){
|
||||
let bytes = new Uint8Array([
|
||||
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,
|
||||
0x01, 0x07, 0x01, 0x60, 0x02, 0x7f, 0x7f, 0x01,
|
||||
0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, 0x07, 0x01,
|
||||
0x03, 0x73, 0x75, 0x6d, 0x00, 0x00, 0x0a, 0x0a,
|
||||
0x01, 0x08, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a,
|
||||
0x0f, 0x0b
|
||||
]);
|
||||
|
||||
console.log(bytes);
|
||||
let mod = new WebAssembly.Module(bytes);
|
||||
let instance = new WebAssembly.Instance(mod, {});
|
||||
console.log(instance.exports);
|
||||
return instance.exports.sum(2020, 1);
|
||||
}());
|
9
examples/python3/factorial.py
Normal file
9
examples/python3/factorial.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
def factorial():
|
||||
f, n = 1, 1
|
||||
while True: # First iteration:
|
||||
yield f # yield 1 to start with and then
|
||||
f, n = f * n, n+1 # f will now be 1, and n will be 2, ...
|
||||
|
||||
for index, factorial_number in zip(range(51), factorial()):
|
||||
print('{i:3}!= {f:65}'.format(i=index, f=factorial_number))
|
||||
|
9
examples/python3/fibonacci.py
Normal file
9
examples/python3/fibonacci.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
def fib():
|
||||
a, b = 0, 1
|
||||
while True: # First iteration:
|
||||
yield a # yield 0 to start with and then
|
||||
a, b = b, a + b # a will now be 1, and b will also be 1, (0 + 1)
|
||||
|
||||
for index, fibonacci_number in zip(range(100), fib()):
|
||||
print('{i:3}: {f:3}'.format(i=index, f=fibonacci_number))
|
||||
|
12
examples/python3/pi.py
Normal file
12
examples/python3/pi.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
from decimal import Decimal, getcontext
|
||||
getcontext().prec=60
|
||||
summation = 0
|
||||
for k in range(50):
|
||||
summation = summation + 1/Decimal(16)**k * (
|
||||
Decimal(4)/(8*k+1)
|
||||
- Decimal(2)/(8*k+4)
|
||||
- Decimal(1)/(8*k+5)
|
||||
- Decimal(1)/(8*k+6)
|
||||
)
|
||||
print(summation)
|
||||
|
14
examples/ruby/helloWorld.rb
Normal file
14
examples/ruby/helloWorld.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
=begin
|
||||
# The famous Hello World
|
||||
# Program is trivial in
|
||||
# Ruby. Superfluous:
|
||||
#
|
||||
# * A "main" method
|
||||
# * Newline
|
||||
# * Semicolons
|
||||
#
|
||||
# Here is the Code:
|
||||
=end
|
||||
|
||||
puts "Hello World!"
|
||||
|
9
examples/ruby/love.rb
Normal file
9
examples/ruby/love.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Output "I love Ruby"
|
||||
say = "I love Ruby"; puts say
|
||||
|
||||
# Output "I *LOVE* RUBY"
|
||||
say['love'] = "*love*"; puts say.upcase
|
||||
|
||||
# Output "I *love* Ruby", 5 times
|
||||
5.times { puts say }
|
||||
|
6
examples/ruby/powOf2.rb
Normal file
6
examples/ruby/powOf2.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
puts(2 ** 1)
|
||||
puts(2 ** 2)
|
||||
puts(2 ** 3)
|
||||
puts(2 ** 10)
|
||||
puts(2 ** 100)
|
||||
puts(2 ** 1000)
|
BIN
favicon.ico
Normal file
BIN
favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 56 KiB |
295
index.html
Normal file
295
index.html
Normal file
|
@ -0,0 +1,295 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" style="height:100%;">
|
||||
<head>
|
||||
<!-- Google Tag Manager -->
|
||||
<script>
|
||||
(function (w, d, s, l, i) {w[l] = w[l] || []; w[l].push({'gtm.start': new Date().getTime(),event: 'gtm.js'});var f = d.getElementsByTagName(s)[0],j = d.createElement(s),dl = l != 'dataLayer' ? '&l=' + l : '';j.async = true;j.src ='https://www.googletagmanager.com/gtm.js?id=' + i + dl;f.parentNode.insertBefore(j, f);})(window, document, 'script', 'dataLayer', 'GTM-5GBJM42');
|
||||
</script>
|
||||
<!-- End Google Tag Manager -->
|
||||
|
||||
<meta charset="utf-8">
|
||||
<title>WebVM</title>
|
||||
|
||||
<meta name="description" content="WebVM - a Bash shell, demo of CheerpX x86 emulation technology, completely client side">
|
||||
<meta name="keywords" content="WebVM, Bash, CheerpX, WebAssembly">
|
||||
<meta property="og:title" content="WebVM" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:site_name" content="WebVM"/>
|
||||
<meta property="og:url" content="/">
|
||||
<meta property="og:image" content="https://webvm.io/assets/webvm.jpeg" />
|
||||
<meta name="twitter:card" content="summary" />
|
||||
<meta name="twitter:site" content="@leaningtech" />
|
||||
<meta name="twitter:title" content="WebVM" />
|
||||
<meta name="twitter:description" content="WebVM - a Bash shell, demo of CheerpX x86 emulation technology, completely client side" />
|
||||
<meta name="twitter:image" content="https://webvm.io/assets/webvm.jpeg" />
|
||||
|
||||
<link rel="shortcut icon" href="/favicon.ico">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com">
|
||||
<link rel="preload" as="style" href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="/xterm/xterm.css" />
|
||||
<script src="/xterm/xterm.js"></script>
|
||||
<script src="/xterm/xterm-addon-fit.js"></script>
|
||||
<script src="https://cheerpxdemos.leaningtech.com/publicdeploy/20220131_600/cx.js"></script>
|
||||
</head>
|
||||
|
||||
<body style="margin:0;height:100%;background:black;color:white;overflow:hidden;">
|
||||
<!-- Google Tag Manager (noscript) -->
|
||||
<noscript>
|
||||
<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-5GBJM42" height="0" width="0"
|
||||
style="display:none;visibility:hidden"></iframe>
|
||||
</noscript>
|
||||
<!-- End Google Tag Manager (noscript) -->
|
||||
|
||||
<main style="display: flex; flex-direction: row; justify-content: space-between; margin:0; height:100%;">
|
||||
<div style="flex-grow:1; height:100%;display:inline-block;margin:0;" id="console">
|
||||
</div>
|
||||
|
||||
</main>
|
||||
<script>
|
||||
|
||||
//Utility namespace to group all functionality related to printing (both error and non error) messages
|
||||
const color= "\x1b[1;35m";
|
||||
const bold= "\x1b[1;37m";
|
||||
const underline= "\x1b[94;4m";
|
||||
const normal= "\x1b[0m";
|
||||
var printOnTerm = {
|
||||
getAsciiTitle: function ()
|
||||
{
|
||||
var title = [
|
||||
color + " __ __ _ __ ____ __ " + normal,
|
||||
color + " \\ \\ / /__| |_\\ \\ / / \\/ | " + normal,
|
||||
color + " \\ \\/\\/ / -_) '_ \\ V /| |\\/| | " + normal,
|
||||
color + " \\_/\\_/\\___|_.__/\\_/ |_| |_| " + normal,
|
||||
|
||||
];
|
||||
return title;
|
||||
},
|
||||
getAsciiText: function ()
|
||||
{
|
||||
var text = [
|
||||
" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+",
|
||||
" | |",
|
||||
" | WebVM is based on Leaning Technologies' virtualization engine, CheerpX. |",
|
||||
" | |",
|
||||
" | CheerpX allows safe client-side execution of x86 apps in a WebAssembly |",
|
||||
" | sandbox. |",
|
||||
" | |",
|
||||
" | CheerpX includes a WebAssembly JIT compiler to achieve |",
|
||||
" | a high level of performance. |",
|
||||
" | |",
|
||||
" | WebVM is an headless, serverless Debian environment. It runs unmodified |",
|
||||
" | binaries from the Debian distribution. |",
|
||||
" | |",
|
||||
" | " +
|
||||
underline + "Medium" + normal + " | " +
|
||||
underline + "GitHub" + normal + " | " +
|
||||
underline + "Issues" + normal + " | " +
|
||||
underline + "Gitter" + normal + " | " +
|
||||
underline + "Twitter" + normal + " | " +
|
||||
underline + "CheerpX's site" + normal + " |",
|
||||
" | |",
|
||||
" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+",
|
||||
"",
|
||||
" Welcome to WebVM! If you don't know what to do, try to create and delete ",
|
||||
" files, or to compile / execute one of the examples. All the data will be ",
|
||||
" saved internally to the browser. If you want to reset the state of WebVM, ",
|
||||
" delete the cache and IndexDB for this page.",
|
||||
"",
|
||||
];
|
||||
return text;
|
||||
},
|
||||
getSharedArrayBufferMissingMessage: function ()
|
||||
{
|
||||
const text = [
|
||||
"",
|
||||
"",
|
||||
color + "CheerpX could not start" + normal,
|
||||
"",
|
||||
"CheerpX depends on JavaScript's SharedArrayBuffer, that your browser",
|
||||
" does not support.",
|
||||
"",
|
||||
"SharedArrayBuffer is currently enabled by default on recent",
|
||||
" versions of Chrome, Edge and Firefox.",
|
||||
"",
|
||||
"Safari and mobile don't support this JavaScript feature, but will do in the future",
|
||||
"",
|
||||
"",
|
||||
"Give it a try from a desktop version / another browser!",
|
||||
]
|
||||
|
||||
return text;
|
||||
},
|
||||
getErrorMessage: function (error_message)
|
||||
{
|
||||
const text = [
|
||||
"",
|
||||
"",
|
||||
color + "CheerpX could not start" + normal,
|
||||
"",
|
||||
"CheerpX internal error message is:",
|
||||
error_message,
|
||||
"",
|
||||
"",
|
||||
"CheerpX is expected to work with recent desktop versions of Chrome, Edge and Firefox",
|
||||
"",
|
||||
"",
|
||||
"Give it a try from a desktop version / another browser!",
|
||||
]
|
||||
|
||||
return text;
|
||||
},
|
||||
printMessage: function (text) {
|
||||
for (var i=0; i<text.length; i++)
|
||||
{
|
||||
term.write(text[i]);
|
||||
term.write('\n');
|
||||
}
|
||||
},
|
||||
printError: function (message)
|
||||
{
|
||||
this.printMessage(message);
|
||||
|
||||
term.write("\n\n");
|
||||
|
||||
function writeCustom(something)
|
||||
{
|
||||
term.write(something);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
var consoleDiv = document.getElementById("console");
|
||||
|
||||
//xterm.js related logic
|
||||
var term = new Terminal({cursorBlink:true,convertEol:true, fontFamily:"'Roboto Mono', monospace", fontWeight: 400, fontWeightBold: 700});
|
||||
var fitAddon = new FitAddon.FitAddon();
|
||||
term.loadAddon(fitAddon);
|
||||
term.open(consoleDiv);
|
||||
term.scrollToTop();
|
||||
|
||||
fitAddon.fit();
|
||||
window.addEventListener("resize", function(ev){fitAddon.fit();}, false);
|
||||
term.focus();
|
||||
var cxReadFunc = null;
|
||||
function writeData(buf)
|
||||
{
|
||||
term.write(new Uint8Array(buf));
|
||||
}
|
||||
function readData(str)
|
||||
{
|
||||
if(cxReadFunc == null)
|
||||
return;
|
||||
for(var i=0;i<str.length;i++)
|
||||
cxReadFunc(str.charCodeAt(i));
|
||||
}
|
||||
term.onData(readData);
|
||||
|
||||
structure = {
|
||||
name: "bash",
|
||||
cmd: "/bin/bash",
|
||||
args: ["--login"],
|
||||
env: ["HOME=/home/user", "TERM=xterm", "USER=user", "SHELL=/bin/bash", "EDITOR=vim", "LANG=en_US.UTF-8", "LC_ALL=C"],
|
||||
expectedPrompt: ">",
|
||||
versionOpt: "--version",
|
||||
comment_line: "#",
|
||||
description_line: "The original Bourne Again SHell",
|
||||
}
|
||||
//Actual CheerpX and bash specific logic
|
||||
function runBash(structure)
|
||||
{
|
||||
if (typeof SharedArrayBuffer === "undefined")
|
||||
{
|
||||
printOnTerm.printError(printOnTerm.getSharedArrayBufferMissingMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
async function runTest(cx)
|
||||
{
|
||||
term.scrollToBottom();
|
||||
|
||||
async function cxLogAndRun(cheerpx, cmd, args, env)
|
||||
{
|
||||
await cheerpx.run(cmd, args, env);
|
||||
printOnTerm.printMessage(" ");
|
||||
}
|
||||
|
||||
cxReadFunc = cx.setCustomConsole(writeData, term.cols, term.rows);
|
||||
|
||||
function preventDefaults (e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}
|
||||
consoleDiv.addEventListener("dragover", preventDefaults, false);
|
||||
consoleDiv.addEventListener("dragenter", preventDefaults, false);
|
||||
consoleDiv.addEventListener("dragleave", preventDefaults, false);
|
||||
consoleDiv.addEventListener("drop", preventDefaults, false);
|
||||
|
||||
var opts = {env:structure.env, cwd:"/home/user"};
|
||||
while (true)
|
||||
{
|
||||
await cxLogAndRun(cx, structure.cmd, structure.args, opts);
|
||||
}
|
||||
}
|
||||
function failCallback(err)
|
||||
{
|
||||
printOnTerm.printError(printOnTerm.getErrorMessage(err));
|
||||
}
|
||||
CheerpXApp.create({devices:[{type:"block",url:"https://disks.leaningtech.com/webvm_20220131.ext2",name:"block1"}],mounts:[{type:"ext2",dev:"block1",path:"/"},{type:"cheerpOS",dev:"/app",path:"/bootstrap"},{type:"devs",dev:"",path:"/dev"}]}).then(runTest, failCallback);
|
||||
}
|
||||
function initialMessage()
|
||||
{
|
||||
printOnTerm.printMessage(printOnTerm.getAsciiTitle());
|
||||
printOnTerm.printMessage(["\n"]);
|
||||
printOnTerm.printMessage(printOnTerm.getAsciiText());
|
||||
const textArray = new Array(6);
|
||||
const linksArray = new Array(6);
|
||||
const rangesArray = new Array(6);
|
||||
var last = 0;
|
||||
const textLinkLine = " | Medium | GitHub | Issues | Gitter | Twitter | CheerpX's site |";
|
||||
const lineWithLinks = 20;
|
||||
function addLink(text, website)
|
||||
{
|
||||
var index = textLinkLine.indexOf(text);
|
||||
const start_x = index+1;
|
||||
const end_x = index + text.length;
|
||||
rangesArray[last] = {start: {x:start_x, y:lineWithLinks}, end: {x:end_x, y:lineWithLinks}};
|
||||
linksArray[last] = website;
|
||||
last++;
|
||||
}
|
||||
|
||||
addLink("Medium", "https://medium.com/leaningtech");
|
||||
addLink("GitHub", "https://github.com/leaningtech/webvm");
|
||||
addLink("Issues", "https://github.com/leaningtech/webvm/issues");
|
||||
addLink("Gitter", "https://gitter.im/leaningtech/cheerpx");
|
||||
addLink("Twitter", "https://twitter.com/leaningtech");
|
||||
addLink("CheerpX's site", "https://leaningtech.com/cheerpx");
|
||||
var provider = {
|
||||
provideLinks(bufferLineNum, callback) {
|
||||
switch(bufferLineNum)
|
||||
{
|
||||
case lineWithLinks:
|
||||
{
|
||||
callback([
|
||||
{range: rangesArray[0], activate() {window.open('' + linksArray[0], '_blank');}},
|
||||
{range: rangesArray[1], activate() {window.open('' + linksArray[1], '_blank');}},
|
||||
{range: rangesArray[2], activate() {window.open('' + linksArray[2], '_blank');}},
|
||||
{range: rangesArray[3], activate() {window.open('' + linksArray[3], '_blank');}},
|
||||
{range: rangesArray[4], activate() {window.open('' + linksArray[4], '_blank');}},
|
||||
{range: rangesArray[5], activate() {window.open('' + linksArray[5], '_blank');}},
|
||||
]);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
term.registerLinkProvider(provider);
|
||||
console.log("Welcome. We appreciate curiosity, but be warned that keeping the DevTools open causes significant performance degradation and crashes.");
|
||||
}
|
||||
|
||||
initialMessage();
|
||||
runBash(structure);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
76
nginx.conf
Normal file
76
nginx.conf
Normal file
|
@ -0,0 +1,76 @@
|
|||
worker_processes 1;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
error_log nginx_main_error.log info;
|
||||
pid nginx_user.pid;
|
||||
daemon off;
|
||||
|
||||
http {
|
||||
access_log nginx_access.log;
|
||||
error_log nginx_error.log info;
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
sendfile on;
|
||||
|
||||
server {
|
||||
# listen 8080 ssl;
|
||||
listen 8081;
|
||||
server_name localhost;
|
||||
|
||||
gzip on;
|
||||
# Enable compression for .wasm, .js and .txt files (used for the runtime chunks)
|
||||
gzip_types application/javascript application/wasm text/plain application/octet-stream;
|
||||
|
||||
charset utf-8;
|
||||
|
||||
# ssl_certificate nginx.crt;
|
||||
# ssl_certificate_key nginx.key;
|
||||
|
||||
location / {
|
||||
root .;
|
||||
autoindex on;
|
||||
index index.html index.htm;
|
||||
add_header 'Access-Control-Allow-Origin' '*' always;
|
||||
add_header 'Access-Control-Expose-Headers' 'content-length' always;
|
||||
add_header 'Cross-Origin-Opener-Policy' 'same-origin' always;
|
||||
add_header 'Cross-Origin-Embedder-Policy' 'require-corp' always;
|
||||
add_header 'Cross-Origin-Resource-Policy' 'cross-origin' always;
|
||||
#auth_basic "CX Demo";
|
||||
#auth_basic_user_file basicauth;
|
||||
}
|
||||
|
||||
location /images/ {
|
||||
root .;
|
||||
if ($arg_s != "") {
|
||||
rewrite ^/images/(.*)$ $1 break;
|
||||
}
|
||||
if ($arg_s = "") {
|
||||
gzip off;
|
||||
}
|
||||
error_page 404 =200 /images_slicer/$uri?$args;
|
||||
}
|
||||
|
||||
location /images_slicer/ {
|
||||
proxy_pass http://localhost:8082/images/;
|
||||
proxy_http_version 1.0;
|
||||
proxy_set_header Range bytes=$arg_s-$arg_e;
|
||||
proxy_hide_header Content-Range;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8082;
|
||||
server_name localhost;
|
||||
|
||||
charset utf-8;
|
||||
|
||||
location / {
|
||||
root .;
|
||||
}
|
||||
}
|
||||
}
|
2
xterm/xterm-addon-fit.js
Normal file
2
xterm/xterm-addon-fit.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.FitAddon=t():e.FitAddon=t()}(self,(function(){return(()=>{"use strict";var e={775:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.FitAddon=void 0;var r=function(){function e(){}return e.prototype.activate=function(e){this._terminal=e},e.prototype.dispose=function(){},e.prototype.fit=function(){var e=this.proposeDimensions();if(e&&this._terminal){var t=this._terminal._core;this._terminal.rows===e.rows&&this._terminal.cols===e.cols||(t._renderService.clear(),this._terminal.resize(e.cols,e.rows))}},e.prototype.proposeDimensions=function(){if(this._terminal&&this._terminal.element&&this._terminal.element.parentElement){var e=this._terminal._core;if(0!==e._renderService.dimensions.actualCellWidth&&0!==e._renderService.dimensions.actualCellHeight){var t=window.getComputedStyle(this._terminal.element.parentElement),r=parseInt(t.getPropertyValue("height")),i=Math.max(0,parseInt(t.getPropertyValue("width"))),n=window.getComputedStyle(this._terminal.element),o=r-(parseInt(n.getPropertyValue("padding-top"))+parseInt(n.getPropertyValue("padding-bottom"))),a=i-(parseInt(n.getPropertyValue("padding-right"))+parseInt(n.getPropertyValue("padding-left")))-e.viewport.scrollBarWidth;return{cols:Math.max(2,Math.floor(a/e._renderService.dimensions.actualCellWidth)),rows:Math.max(1,Math.floor(o/e._renderService.dimensions.actualCellHeight))}}}},e}();t.FitAddon=r}},t={};return function r(i){if(t[i])return t[i].exports;var n=t[i]={exports:{}};return e[i](n,n.exports,r),n.exports}(775)})()}));
|
||||
//# sourceMappingURL=xterm-addon-fit.js.map
|
175
xterm/xterm.css
Normal file
175
xterm/xterm.css
Normal file
|
@ -0,0 +1,175 @@
|
|||
/**
|
||||
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
|
||||
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
||||
* https://github.com/chjj/term.js
|
||||
* @license MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* Originally forked from (with the author's permission):
|
||||
* Fabrice Bellard's javascript vt100 for jslinux:
|
||||
* http://bellard.org/jslinux/
|
||||
* Copyright (c) 2011 Fabrice Bellard
|
||||
* The original design remains. The terminal itself
|
||||
* has been extended to include xterm CSI codes, among
|
||||
* other features.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Default styles for xterm.js
|
||||
*/
|
||||
|
||||
.xterm {
|
||||
position: relative;
|
||||
user-select: none;
|
||||
-ms-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.xterm.focus,
|
||||
.xterm:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.xterm .xterm-helpers {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
/**
|
||||
* The z-index of the helpers must be higher than the canvases in order for
|
||||
* IMEs to appear on top.
|
||||
*/
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.xterm .xterm-helper-textarea {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
/* Move textarea out of the screen to the far left, so that the cursor is not visible */
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
left: -9999em;
|
||||
top: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
z-index: -5;
|
||||
/** Prevent wrapping so the IME appears against the textarea at the correct position */
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.xterm .composition-view {
|
||||
/* TODO: Composition position got messed up somewhere */
|
||||
background: #000;
|
||||
color: #FFF;
|
||||
display: none;
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.xterm .composition-view.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.xterm .xterm-viewport {
|
||||
/* On OS X this is required in order for the scroll bar to appear fully opaque */
|
||||
background-color: #000;
|
||||
overflow-y: scroll;
|
||||
cursor: default;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.xterm .xterm-screen {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.xterm .xterm-screen canvas {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.xterm .xterm-scroll-area {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.xterm-char-measure-element {
|
||||
display: inline-block;
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -9999em;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.xterm {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.xterm.enable-mouse-events {
|
||||
/* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.xterm.xterm-cursor-pointer,
|
||||
.xterm .xterm-cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.xterm.column-select.focus {
|
||||
/* Column selection mode */
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
.xterm .xterm-accessibility,
|
||||
.xterm .xterm-message {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
z-index: 10;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.xterm .live-region {
|
||||
position: absolute;
|
||||
left: -9999px;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.xterm-dim {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.xterm-underline {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.xterm-strikethrough {
|
||||
text-decoration: line-through;
|
||||
}
|
2
xterm/xterm.js
Normal file
2
xterm/xterm.js
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue