Initial wasm loader
commit
8a907ad6d9
@ -0,0 +1,7 @@
|
||||
(module
|
||||
(memory (export "memory") 10)
|
||||
|
||||
(func (export "run")
|
||||
|
||||
)
|
||||
)
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Ashelyn's AOC 2022</title>
|
||||
<link rel="stylesheet" href="/resources/style.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="selector">
|
||||
<label for="day-selector">
|
||||
Select a day to run its entry:
|
||||
</label>
|
||||
<select value="">
|
||||
<option class="loading" selected value="">Loading days...</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<p class="output">
|
||||
|
||||
</p>
|
||||
|
||||
<div class="ui">
|
||||
<p>input:</p>
|
||||
<textarea class="input"></textarea>
|
||||
|
||||
<p>output:</p>
|
||||
<textarea disabled readonly class="output"></textarea>
|
||||
<button>Run</button>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="https://unpkg.com/wabt@1.0.29/index.js"></script>
|
||||
<script type="text/javascript" src="/resources/loader.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,115 @@
|
||||
let wasmInstance
|
||||
|
||||
const textEncoder = new TextEncoder()
|
||||
const textDecoder = new TextDecoder()
|
||||
const daySelector = document.querySelector('.selector select')
|
||||
const output = document.querySelector('.output')
|
||||
const inputTextArea = document.querySelector('.ui textarea.input')
|
||||
const outputTextArea = document.querySelector('.ui textarea.output')
|
||||
const runButton = document.querySelector('.ui button')
|
||||
|
||||
async function getDayList() {
|
||||
const days = []
|
||||
|
||||
for (let i = 1; i <= 25; i++) {
|
||||
const response = await fetch(`/days/${i}/code.wat`)
|
||||
|
||||
if (response.status === 200) {
|
||||
days.push(i)
|
||||
}
|
||||
}
|
||||
|
||||
for (const day of days) {
|
||||
const option = document.createElement('option')
|
||||
option.value = day
|
||||
option.innerText = day
|
||||
daySelector.appendChild(option)
|
||||
}
|
||||
|
||||
document.querySelector('.loading').innerText = "Select a day"
|
||||
}
|
||||
|
||||
async function loadDay(dayNum) {
|
||||
output.className = ''
|
||||
output.innerText = `loading day ${dayNum}... `
|
||||
|
||||
try {
|
||||
const { WabtModule } = window;
|
||||
const wabt = await WabtModule()
|
||||
const url = `/days/${dayNum}/code.wat`
|
||||
|
||||
// Download wasm code
|
||||
const wasmText = await fetch(url)
|
||||
.then(res => res.text())
|
||||
|
||||
// initialize module
|
||||
const module = wabt.parseWat(url, wasmText)
|
||||
const { buffer: codeBuffer } = module.toBinary({
|
||||
write_debug_names: true
|
||||
})
|
||||
|
||||
const { instance } = await WebAssembly.instantiate(codeBuffer)
|
||||
wasmInstance = instance
|
||||
} catch (err) {
|
||||
output.className = 'error'
|
||||
output.innerText = 'Error: ' + err.message
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const inputText = await fetch(`/days/${dayNum}/input.txt`)
|
||||
.then(res => res.text())
|
||||
|
||||
inputTextArea.value = inputText
|
||||
} catch (err) {
|
||||
inputTextArea.value = ''
|
||||
console.error(err)
|
||||
}
|
||||
|
||||
output.innerText = 'Loaded day ' + dayNum
|
||||
}
|
||||
|
||||
function runLoaded() {
|
||||
const { run, memory } = wasmInstance.exports;
|
||||
const wasmBuffer = memory.buffer;
|
||||
|
||||
const inputBuffer = textEncoder.encode(inputTextArea.value)
|
||||
|
||||
// Set length and file contents
|
||||
const inputLength = inputBuffer.length
|
||||
const inputLargeArray = new Uint32Array(wasmBuffer)
|
||||
const inputSmallArray = new Uint8Array(wasmBuffer)
|
||||
const fileInputNums = new Uint8Array(inputBuffer)
|
||||
|
||||
inputLargeArray[0] = inputLength
|
||||
inputSmallArray.set(fileInputNums, 4)
|
||||
|
||||
// run the wasm
|
||||
outputTextArea.value = ""
|
||||
const outputLocation = run()
|
||||
|
||||
// Read the output
|
||||
const outputBuffer = wasmBuffer.slice(outputLocation)
|
||||
const outputLargeArray = new Uint32Array(outputBuffer)
|
||||
const outputSmallArray = new Uint8Array(outputBuffer)
|
||||
|
||||
const outputLength = outputLargeArray[0]
|
||||
const outputBytes = outputSmallArray.slice(4, 4 + outputLength)
|
||||
const outputText = textDecoder.decode(outputBytes)
|
||||
outputTextArea.value = outputText
|
||||
}
|
||||
|
||||
daySelector.value = ""
|
||||
inputTextArea.value = ""
|
||||
outputTextArea.value = ""
|
||||
|
||||
getDayList().then(() => {
|
||||
daySelector.addEventListener('change', ev => {
|
||||
loadDay(ev.target.value)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
runButton.addEventListener('click', ev => {
|
||||
runLoaded()
|
||||
})
|
@ -0,0 +1,3 @@
|
||||
.error {
|
||||
color: red;
|
||||
}
|
Loading…
Reference in New Issue