Finish client side wasm rendering

This commit is contained in:
titaneric 2021-04-01 14:49:53 +08:00
parent bcd57a6b22
commit 6816d47d13
3 changed files with 87 additions and 40 deletions

View File

@ -124,6 +124,9 @@ function playground_text(playground) {
result_block.innerText = "Running..."; result_block.innerText = "Running...";
params = {
code: text
}
// fetch_with_timeout("https://play.rust-lang.org/evaluate.json", { // fetch_with_timeout("https://play.rust-lang.org/evaluate.json", {
// headers: { // headers: {
// 'Content-Type': "application/json", // 'Content-Type': "application/json",
@ -132,35 +135,79 @@ function playground_text(playground) {
// mode: 'cors', // mode: 'cors',
// body: JSON.stringify(params) // body: JSON.stringify(params)
// }) // })
new Promise((resolve, reject) => { prepareSandbox(params).then(src => processHTML(src)).then(html => {
setTimeout(() => {
resolve("foo");
}, 200)
})
// .then(response => response.json())
// .then(response => result_block.innerText = response.result)
// .then(response => result_block.innerHTML = "<div style=\"height: 300px;background-color: red;\"></div>")
// .then(response => result_block.innerHTML = " <div id=\"button_click\"></div><script type=\"module\" src=\"wasm-test.js\"></script>")
.then(response => {
result_block.innerText = ""; result_block.innerText = "";
var iframe = result_block.appendChild(document.createElement('iframe')), var iframe = result_block.appendChild(document.createElement('iframe')),
doc = iframe.contentWindow.document; doc = iframe.contentWindow.document;
iframe.id = "wasm-rendering"; iframe.id = "wasm-rendering";
iframe.style.width = "100%"; iframe.style.width = "100%";
iframe.style.height = "100%"; iframe.style.height = "100%";
var xhr = new XMLHttpRequest(); iframe.border = 0;
xhr.open('GET', 'iframe.html', true); iframe.scrolling = "no";
xhr.onreadystatechange = function () {
if (this.readyState !== 4) return;
if (this.status !== 200) return; // or whatever error handling you want
var html = this.responseText;
doc.open().write(html); doc.open().write(html);
doc.close(); doc.close();
}; })
xhr.send(); }
async function prepareSandbox(params) {
var wasmResult = fetch_with_timeout("http://192.168.217.100:9999/wasm-pack", {
headers: {
'Content-Type': "application/json",
},
method: 'POST',
mode: 'cors',
body: JSON.stringify(params)
})
.then(response => response.json())
.then(({ wasm_js, wasm_bg }) => {
var wasm_bg_blob = base64ToByteArray(wasm_bg);
return {
wasm_js: atob(wasm_js),
wasm_bg: wasm_bg_blob
}
}) })
.catch(error => result_block.innerText = "Playground Communication: " + error.message); .catch(error => result_block.innerText = "Playground Communication: " + error.message);
var htmlSrc = fetch(new Request("iframe.html"))
.then(response => response.text());
var jsSrc = fetch(new Request("wasm-entry.mjs"))
.then(response => response.text());
return Promise.all([htmlSrc, jsSrc, wasmResult])
.catch(error => console.log(error));
}
function base64ToByteArray(src) {
var decode = atob(src);
const byteNumbers = new Array(decode.length);
for (let i = 0; i < decode.length; i++) {
byteNumbers[i] = decode.charCodeAt(i);
}
return new Uint8Array(byteNumbers);
}
async function processHTML([htmlSrc, jsSrc, { wasm_js, wasm_bg }]) {
var src = rewriteJS(jsSrc, wasm_js, wasm_bg);
var blob = new Blob([src], { type: "application/javascript" });
var jsBlob = URL.createObjectURL(blob);
return htmlSrc.replace(/\bsrc\s*=\s*['"](.+?)['"]/g, (all, path) => {
return `src="${jsBlob}"`;
});
}
function rewriteJS(src, wasmJS, bgWasm) {
var blob = new Blob([wasmJS], { type: "application/javascript" });
var wasmJSBlob = URL.createObjectURL(blob);
var blob = new Blob([bgWasm], { type: "application/wasm" });
var bgWasmBlob = URL.createObjectURL(blob);
// replace wasm.js
src = src.replace(/\bfrom\s+['"](.+?)['"](\s*[;\n])/g, (all, path, sep) => {
return `from "${wasmJSBlob}"${sep}`;
})
// replace `input` of init to object URL
src = src.replace(/\(['"](.+?)['"]\)/g, (all, url) => {
return `("${bgWasmBlob}")`;
})
return src
} }
// Syntax highlighting Configuration // Syntax highlighting Configuration

View File

@ -1,18 +1,18 @@
<!-- Code injected from iframe.html --> <!DOCTYPE html>
<html>
<head> <head>
<script> <meta charset="utf-8">
// dynamically create script element and append to head <style>
// call wasm-entry to load the built wasm.js body {
function body_onload() { background-color: rgb(255, 255, 255);
var d = document;
var script = d.createElement('script');
script.type = 'module';
script.src = 'wasm-entry.mjs';
d.getElementsByTagName('head')[0].appendChild(script);
} }
</script> </style>
</head> </head>
<body onload="body_onload();"> <body>
<div id="_start"></div> <span id="container"></span>
<script src="wasm-entry.mjs" type="module"></script>
</body> </body>
</html>

View File

@ -1,3 +1,3 @@
import init from './wasm.js'; import init from './wasm.js';
init(); await init("WASM_URL");