Commit db69641061

Andrew Kelley <andrew@ziglang.org>
2024-08-05 03:22:09
fuzzing web ui: make entry point links clickable
1 parent e64a009
Changed files (2)
lib
fuzzer
lib/fuzzer/wasm/main.zig
@@ -4,6 +4,7 @@ const abi = std.Build.Fuzz.abi;
 const gpa = std.heap.wasm_allocator;
 const log = std.log;
 const Coverage = std.debug.Coverage;
+const Allocator = std.mem.Allocator;
 
 const Walk = @import("Walk");
 const Decl = Walk.Decl;
@@ -263,12 +264,26 @@ fn updateCoverage(
 }
 
 export fn sourceLocationLinkHtml(index: u32) String {
-    const sl = coverage_source_locations.items[index];
-    const file_name = coverage.stringAt(coverage.fileAt(sl.file).basename);
-
     string_result.clearRetainingCapacity();
-    string_result.writer(gpa).print("{s}:{d}:{d}", .{
-        file_name, sl.line, sl.column,
-    }) catch @panic("OOM");
+    sourceLocationLinkHtmlFallible(index, &string_result) catch @panic("OOM");
     return String.init(string_result.items);
 }
+
+fn sourceLocationLinkHtmlFallible(index: u32, out: *std.ArrayListUnmanaged(u8)) Allocator.Error!void {
+    const sl = coverage_source_locations.items[index];
+    const file = coverage.fileAt(sl.file);
+    const file_name = coverage.stringAt(file.basename);
+    const dir_name = coverage.stringAt(coverage.directories.keys()[file.directory_index]);
+
+    out.clearRetainingCapacity();
+    try out.appendSlice(gpa, "<a href=\"#");
+    _ = html_render.missing_feature_url_escape;
+    try out.writer(gpa).print("{s}/{s}:{d}:{d}", .{
+        dir_name, file_name, sl.line, sl.column,
+    });
+    try out.appendSlice(gpa, "\">");
+    try html_render.appendEscaped(out, dir_name);
+    try out.appendSlice(gpa, "/");
+    try html_render.appendEscaped(out, file_name);
+    try out.writer(gpa).print(":{d}:{d}</a>", .{ sl.line, sl.column });
+}
lib/fuzzer/main.js
@@ -15,6 +15,8 @@
     return response.arrayBuffer();
   });
   var wasm_exports = null;
+  var curNavSearch = null;
+  var curNavLocation = null;
 
   const text_decoder = new TextDecoder();
   const text_encoder = new TextEncoder();
@@ -47,11 +49,52 @@
       wasm_array.set(js_array);
       wasm_exports.unpack(ptr, js_array.length);
 
+      window.addEventListener('popstate', onPopState, false);
+      onHashChange(null);
+
       domStatus.textContent = "Waiting for server to send source location metadata...";
       connectWebSocket();
     });
   });
 
+  function onPopState(ev) {
+    onHashChange(ev.state);
+  }
+
+  function onHashChange(state) {
+    history.replaceState({}, "");
+    navigate(location.hash);
+    if (state == null) window.scrollTo({top: 0});
+  }
+
+  function navigate(location_hash) {
+    curNavLocation = null;
+    curNavSearch = null;
+
+    if (location_hash.length > 1 && location_hash[0] === '#') {
+      const query = location_hash.substring(1);
+      const qpos = query.indexOf("?");
+      let nonSearchPart;
+      if (qpos === -1) {
+        nonSearchPart = query;
+      } else {
+        nonSearchPart = query.substring(0, qpos);
+        curNavSearch = decodeURIComponent(query.substring(qpos + 1));
+      }
+
+      if (nonSearchPart.length > 0) {
+        curNavLocation = nonSearchPart;
+      }
+    }
+
+    render();
+
+    if (curNavLocation != null) {
+      // TODO
+      // scrollToSourceLocation(findSourceLocationIndex(curNavLocation));
+    }
+  }
+
   function connectWebSocket() {
     const host = window.document.location.host;
     const pathname = window.document.location.pathname;
@@ -104,8 +147,9 @@
     domStatus.classList.add("hidden");
     domSectSource.classList.add("hidden");
 
-    // TODO this is temporary debugging data
-    renderSource("/home/andy/dev/zig/lib/std/zig/tokenizer.zig");
+    if (curNavLocation != null) {
+      renderSource(curNavLocation.split(":")[0]);
+    }
   }
 
   function renderStats() {
@@ -122,7 +166,7 @@
     resizeDomList(domEntryPointsList, entryPoints.length, "<li></li>");
     for (let i = 0; i < entryPoints.length; i += 1) {
       const liDom = domEntryPointsList.children[i];
-      liDom.innerText = unwrapString(wasm_exports.sourceLocationLinkHtml(entryPoints[i]));
+      liDom.innerHTML = unwrapString(wasm_exports.sourceLocationLinkHtml(entryPoints[i]));
     }