mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
* libfuzzer: track unique runs instead of deduplicated runs - easier for consumers to notice when to recheck the covered bits. * move common definitions to `std.Build.Fuzz.abi`. build runner sends all the information needed to fuzzer web interface client needed in order to display inline coverage information along with source code.
148 lines
4.8 KiB
JavaScript
148 lines
4.8 KiB
JavaScript
(function() {
|
|
const domStatus = document.getElementById("status");
|
|
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();
|
|
|
|
domStatus.textContent = "Loading WebAssembly...";
|
|
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);
|
|
},
|
|
emitSourceIndexChange: onSourceIndexChange,
|
|
emitCoverageUpdate: onCoverageUpdate,
|
|
},
|
|
}).then(function(obj) {
|
|
wasm_exports = obj.instance.exports;
|
|
window.wasm = obj; // for debugging
|
|
domStatus.textContent = "Loading sources tarball...";
|
|
|
|
sources_promise.then(function(buffer) {
|
|
domStatus.textContent = "Parsing sources...";
|
|
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);
|
|
|
|
domStatus.textContent = "Waiting for server to send source location metadata...";
|
|
connectWebSocket();
|
|
});
|
|
});
|
|
|
|
function connectWebSocket() {
|
|
const host = window.document.location.host;
|
|
const pathname = window.document.location.pathname;
|
|
const isHttps = window.document.location.protocol === 'https:';
|
|
const match = host.match(/^(.+):(\d+)$/);
|
|
const defaultPort = isHttps ? 443 : 80;
|
|
const port = match ? parseInt(match[2], 10) : defaultPort;
|
|
const hostName = match ? match[1] : host;
|
|
const wsProto = isHttps ? "wss:" : "ws:";
|
|
const wsUrl = wsProto + '//' + hostName + ':' + port + pathname;
|
|
ws = new WebSocket(wsUrl);
|
|
ws.binaryType = "arraybuffer";
|
|
ws.addEventListener('message', onWebSocketMessage, false);
|
|
ws.addEventListener('error', timeoutThenCreateNew, false);
|
|
ws.addEventListener('close', timeoutThenCreateNew, false);
|
|
ws.addEventListener('open', onWebSocketOpen, false);
|
|
}
|
|
|
|
function onWebSocketOpen() {
|
|
console.log("web socket opened");
|
|
}
|
|
|
|
function onWebSocketMessage(ev) {
|
|
wasmOnMessage(ev.data);
|
|
}
|
|
|
|
function timeoutThenCreateNew() {
|
|
ws.removeEventListener('message', onWebSocketMessage, false);
|
|
ws.removeEventListener('error', timeoutThenCreateNew, false);
|
|
ws.removeEventListener('close', timeoutThenCreateNew, false);
|
|
ws.removeEventListener('open', onWebSocketOpen, false);
|
|
ws = null;
|
|
setTimeout(connectWebSocket, 1000);
|
|
}
|
|
|
|
function wasmOnMessage(data) {
|
|
const jsArray = new Uint8Array(data);
|
|
const ptr = wasm_exports.message_begin(jsArray.length);
|
|
const wasmArray = new Uint8Array(wasm_exports.memory.buffer, ptr, jsArray.length);
|
|
wasmArray.set(jsArray);
|
|
wasm_exports.message_end();
|
|
}
|
|
|
|
function onSourceIndexChange() {
|
|
console.log("source location index metadata updated");
|
|
render();
|
|
}
|
|
|
|
function onCoverageUpdate() {
|
|
console.log("coverage update");
|
|
}
|
|
|
|
function render() {
|
|
domStatus.classList.add("hidden");
|
|
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);
|
|
}
|
|
})();
|