ソースを参照

Initial commit

Serena Ziviani 3 年 前
コミット
512332d439

+ 20 - 0
README.md

@@ -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


+ 13 - 0
examples/c/Makefile

@@ -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 - 0
examples/c/env.c

@@ -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 - 0
examples/c/helloworld.c

@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main()
+{
+	printf("Hello, World!\n");
+}

+ 7 - 0
examples/c/link.c

@@ -0,0 +1,7 @@
+#include <unistd.h>
+
+int main()
+{
+	link("env", "env3");
+	return 0;
+}

+ 10 - 0
examples/c/openat.c

@@ -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 - 0
examples/c/waitpid.c

@@ -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 - 0
examples/lua/fizzbuzz.lua

@@ -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 - 0
examples/lua/sorting.lua

@@ -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 - 0
examples/lua/symmetric_difference.lua

@@ -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 - 0
examples/nodejs/environment.js

@@ -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 - 0
examples/nodejs/nbody.js

@@ -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 - 0
examples/nodejs/primes.js

@@ -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 - 0
examples/nodejs/wasm.js

@@ -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 - 0
examples/python3/factorial.py

@@ -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 - 0
examples/python3/fibonacci.py

@@ -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 - 0
examples/python3/pi.py

@@ -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 - 0
examples/ruby/helloWorld.rb

@@ -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 - 0
examples/ruby/love.rb

@@ -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 - 0
examples/ruby/powOf2.rb

@@ -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


+ 295 - 0
index.html

@@ -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 - 0
nginx.conf

@@ -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 - 0
xterm/xterm-addon-fit.js

@@ -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 - 0
xterm/xterm.css

@@ -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;
+}

ファイルの差分が大きいため隠しています
+ 0 - 0
xterm/xterm.js


この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません