From 38227e92898a049412ddaab6c8596218d32db650 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 5 Aug 2024 16:23:30 -0700 Subject: [PATCH] fuzzer web UI: render PCs with red or green depending on coverage --- lib/fuzzer/index.html | 19 ++++++++++++++----- lib/fuzzer/main.js | 19 +++++++++++++++---- lib/fuzzer/wasm/main.zig | 27 +++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/lib/fuzzer/index.html b/lib/fuzzer/index.html index 0f62f58e6d..16fa879913 100644 --- a/lib/fuzzer/index.html +++ b/lib/fuzzer/index.html @@ -53,11 +53,14 @@ } .l { - display: inline-block; - background: white; - width: 1em; - height: 1em; - border-radius: 1em; + display: inline-block; + background: red; + width: 1em; + height: 1em; + border-radius: 1em; + } + .c { + background-color: green; } .tok-kw { @@ -104,6 +107,12 @@ code a { color: #ccc; } + .l { + background-color: red; + } + .c { + background-color: green; + } .tok-kw { color: #eee; } diff --git a/lib/fuzzer/main.js b/lib/fuzzer/main.js index 42bd72cef5..773cdfe902 100644 --- a/lib/fuzzer/main.js +++ b/lib/fuzzer/main.js @@ -172,12 +172,20 @@ } function renderCoverage() { + if (curNavLocation == null) return; + const sourceLocationIndex = curNavLocation; + for (let i = 0; i < domSourceText.children.length; i += 1) { const childDom = domSourceText.children[i]; if (childDom.id != null && childDom.id[0] == "l") { childDom.classList.add("l"); + childDom.classList.remove("c"); } } + const coveredList = unwrapInt32Array(wasm_exports.sourceLocationFileCoveredList(sourceLocationIndex)); + for (let i = 0; i < coveredList.length; i += 1) { + document.getElementById("l" + coveredList[i]).classList.add("c"); + } } function resizeDomList(listDom, desiredLen, templateHtml) { @@ -203,10 +211,13 @@ domSectSource.classList.remove("hidden"); - const slDom = document.getElementById("l" + sourceLocationIndex); - slDom.scrollIntoView({ - behavior: "smooth", - block: "center", + // Empirically, Firefox needs this requestAnimationFrame in order for the scrollIntoView to work. + requestAnimationFrame(function() { + const slDom = document.getElementById("l" + sourceLocationIndex); + slDom.scrollIntoView({ + behavior: "smooth", + block: "center", + }); }); } diff --git a/lib/fuzzer/wasm/main.zig b/lib/fuzzer/wasm/main.zig index 5d8edf768a..a352458afc 100644 --- a/lib/fuzzer/wasm/main.zig +++ b/lib/fuzzer/wasm/main.zig @@ -395,3 +395,30 @@ export fn sourceLocationFileHtml(sli: SourceLocationIndex) String { }; return String.init(string_result.items); } + +export fn sourceLocationFileCoveredList(sli_file: SourceLocationIndex) Slice(SourceLocationIndex) { + const global = struct { + var result: std.ArrayListUnmanaged(SourceLocationIndex) = .{}; + fn add(i: u32, want_file: Coverage.File.Index) void { + const src_loc_index: SourceLocationIndex = @enumFromInt(i); + if (src_loc_index.ptr().file == want_file) result.appendAssumeCapacity(src_loc_index); + } + }; + const want_file = sli_file.ptr().file; + global.result.clearRetainingCapacity(); + const covered_bits = recent_coverage_update.items[@sizeOf(abi.CoverageUpdateHeader)..]; + var sli: u32 = 0; + for (covered_bits) |byte| { + global.result.ensureUnusedCapacity(gpa, 8) catch @panic("OOM"); + if ((byte & 0b0000_0001) != 0) global.add(sli + 0, want_file); + if ((byte & 0b0000_0010) != 0) global.add(sli + 1, want_file); + if ((byte & 0b0000_0100) != 0) global.add(sli + 2, want_file); + if ((byte & 0b0000_1000) != 0) global.add(sli + 3, want_file); + if ((byte & 0b0001_0000) != 0) global.add(sli + 4, want_file); + if ((byte & 0b0010_0000) != 0) global.add(sli + 5, want_file); + if ((byte & 0b0100_0000) != 0) global.add(sli + 6, want_file); + if ((byte & 0b1000_0000) != 0) global.add(sli + 7, want_file); + sli += 8; + } + return Slice(SourceLocationIndex).init(global.result.items); +}