zig/lib/fuzzer/main.js
Andrew Kelley 517cfb0dd1 fuzzing: progress towards web UI
* libfuzzer: close file after mmap
* fuzzer/main.js: connect with EventSource and debug dump the messages.
  currently this prints how many fuzzer runs have been attempted to
  console.log.
* extract some `std.debug.Info` logic into `std.debug.Coverage`.
  Prepares for consolidation across multiple different executables which
  share source files, and makes it possible to send all the
  PC/SourceLocation mapping data with 4 memcpy'd arrays.
* std.Build.Fuzz:
  - spawn a thread to watch the message queue and signal event
    subscribers.
  - track coverage map data
  - respond to /events URL with EventSource messages on a timer
2024-08-07 00:48:32 -07:00

95 lines
2.9 KiB
JavaScript

(function() {
const domSectSource = document.getElementById("sectSource");
const domSourceText = document.getElementById("sourceText");
let wasm_promise = fetch("main.wasm");
let sources_promise = fetch("sources.tar").then(function(response) {
if (!response.ok) throw new Error("unable to download sources");
return response.arrayBuffer();
});
var wasm_exports = null;
const text_decoder = new TextDecoder();
const text_encoder = new TextEncoder();
const eventSource = new EventSource("events");
eventSource.addEventListener('message', onMessage, false);
WebAssembly.instantiateStreaming(wasm_promise, {
js: {
log: function(ptr, len) {
const msg = decodeString(ptr, len);
console.log(msg);
},
panic: function (ptr, len) {
const msg = decodeString(ptr, len);
throw new Error("panic: " + msg);
},
},
}).then(function(obj) {
wasm_exports = obj.instance.exports;
window.wasm = obj; // for debugging
sources_promise.then(function(buffer) {
const js_array = new Uint8Array(buffer);
const ptr = wasm_exports.alloc(js_array.length);
const wasm_array = new Uint8Array(wasm_exports.memory.buffer, ptr, js_array.length);
wasm_array.set(js_array);
wasm_exports.unpack(ptr, js_array.length);
render();
});
});
function onMessage(e) {
console.log("Message", e.data);
}
function render() {
domSectSource.classList.add("hidden");
// TODO this is temporary debugging data
renderSource("/home/andy/dev/zig/lib/std/zig/tokenizer.zig");
}
function renderSource(path) {
const decl_index = findFileRoot(path);
if (decl_index == null) throw new Error("file not found: " + path);
const h2 = domSectSource.children[0];
h2.innerText = path;
domSourceText.innerHTML = declSourceHtml(decl_index);
domSectSource.classList.remove("hidden");
}
function findFileRoot(path) {
setInputString(path);
const result = wasm_exports.find_file_root();
if (result === -1) return null;
return result;
}
function decodeString(ptr, len) {
if (len === 0) return "";
return text_decoder.decode(new Uint8Array(wasm_exports.memory.buffer, ptr, len));
}
function setInputString(s) {
const jsArray = text_encoder.encode(s);
const len = jsArray.length;
const ptr = wasm_exports.set_input_string(len);
const wasmArray = new Uint8Array(wasm_exports.memory.buffer, ptr, len);
wasmArray.set(jsArray);
}
function declSourceHtml(decl_index) {
return unwrapString(wasm_exports.decl_source_html(decl_index));
}
function unwrapString(bigint) {
const ptr = Number(bigint & 0xffffffffn);
const len = Number(bigint >> 32n);
return decodeString(ptr, len);
}
})();