mirror of
https://github.com/ziglang/zig.git
synced 2025-02-08 21:50:33 +00:00
fuzzer web UI: navigate by source location index
This will help scroll the point of interest into view
This commit is contained in:
parent
db69641061
commit
ef4c2193fc
@ -68,6 +68,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function navigate(location_hash) {
|
function navigate(location_hash) {
|
||||||
|
domSectSource.classList.add("hidden");
|
||||||
|
|
||||||
curNavLocation = null;
|
curNavLocation = null;
|
||||||
curNavSearch = null;
|
curNavSearch = null;
|
||||||
|
|
||||||
@ -82,23 +84,19 @@
|
|||||||
curNavSearch = decodeURIComponent(query.substring(qpos + 1));
|
curNavSearch = decodeURIComponent(query.substring(qpos + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nonSearchPart.length > 0) {
|
if (nonSearchPart[0] == "l") {
|
||||||
curNavLocation = nonSearchPart;
|
curNavLocation = +nonSearchPart.substring(1);
|
||||||
|
renderSource(curNavLocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render();
|
render();
|
||||||
|
|
||||||
if (curNavLocation != null) {
|
|
||||||
// TODO
|
|
||||||
// scrollToSourceLocation(findSourceLocationIndex(curNavLocation));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function connectWebSocket() {
|
function connectWebSocket() {
|
||||||
const host = window.document.location.host;
|
const host = document.location.host;
|
||||||
const pathname = window.document.location.pathname;
|
const pathname = document.location.pathname;
|
||||||
const isHttps = window.document.location.protocol === 'https:';
|
const isHttps = document.location.protocol === 'https:';
|
||||||
const match = host.match(/^(.+):(\d+)$/);
|
const match = host.match(/^(.+):(\d+)$/);
|
||||||
const defaultPort = isHttps ? 443 : 80;
|
const defaultPort = isHttps ? 443 : 80;
|
||||||
const port = match ? parseInt(match[2], 10) : defaultPort;
|
const port = match ? parseInt(match[2], 10) : defaultPort;
|
||||||
@ -139,17 +137,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function onSourceIndexChange() {
|
function onSourceIndexChange() {
|
||||||
console.log("source location index metadata updated");
|
|
||||||
render();
|
render();
|
||||||
|
if (curNavLocation != null) renderSource(curNavLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
function render() {
|
function render() {
|
||||||
domStatus.classList.add("hidden");
|
domStatus.classList.add("hidden");
|
||||||
domSectSource.classList.add("hidden");
|
|
||||||
|
|
||||||
if (curNavLocation != null) {
|
|
||||||
renderSource(curNavLocation.split(":")[0]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderStats() {
|
function renderStats() {
|
||||||
@ -186,22 +179,23 @@
|
|||||||
return ((Number(a) / Number(b)) * 100).toFixed(1);
|
return ((Number(a) / Number(b)) * 100).toFixed(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderSource(path) {
|
function renderSource(sourceLocationIndex) {
|
||||||
const decl_index = findFileRoot(path);
|
const pathName = unwrapString(wasm_exports.sourceLocationPath(sourceLocationIndex));
|
||||||
if (decl_index == null) throw new Error("file not found: " + path);
|
if (pathName.length === 0) return;
|
||||||
|
|
||||||
const h2 = domSectSource.children[0];
|
const h2 = domSectSource.children[0];
|
||||||
h2.innerText = path;
|
h2.innerText = pathName;
|
||||||
domSourceText.innerHTML = declSourceHtml(decl_index);
|
domSourceText.innerHTML = unwrapString(wasm_exports.sourceLocationFileHtml(sourceLocationIndex));
|
||||||
|
|
||||||
domSectSource.classList.remove("hidden");
|
domSectSource.classList.remove("hidden");
|
||||||
}
|
|
||||||
|
|
||||||
function findFileRoot(path) {
|
const slDom = document.getElementById("l" + sourceLocationIndex);
|
||||||
setInputString(path);
|
if (slDom != null) {
|
||||||
const result = wasm_exports.find_file_root();
|
slDom.scrollIntoView({
|
||||||
if (result === -1) return null;
|
behavior: "smooth",
|
||||||
return result;
|
block: "center",
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeString(ptr, len) {
|
function decodeString(ptr, len) {
|
||||||
@ -224,10 +218,6 @@
|
|||||||
wasmArray.set(jsArray);
|
wasmArray.set(jsArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
function declSourceHtml(decl_index) {
|
|
||||||
return unwrapString(wasm_exports.decl_source_html(decl_index));
|
|
||||||
}
|
|
||||||
|
|
||||||
function unwrapString(bigint) {
|
function unwrapString(bigint) {
|
||||||
const ptr = Number(bigint & 0xffffffffn);
|
const ptr = Number(bigint & 0xffffffffn);
|
||||||
const len = Number(bigint >> 32n);
|
const len = Number(bigint >> 32n);
|
||||||
|
@ -235,7 +235,59 @@ export fn entryPoints() Slice(u32) {
|
|||||||
return Slice(u32).init(entry_points.items);
|
return Slice(u32).init(entry_points.items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Index into `coverage_source_locations`.
|
||||||
|
const SourceLocationIndex = enum(u32) {
|
||||||
|
_,
|
||||||
|
|
||||||
|
fn haveCoverage(sli: SourceLocationIndex) bool {
|
||||||
|
return @intFromEnum(sli) < coverage_source_locations.items.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ptr(sli: SourceLocationIndex) *Coverage.SourceLocation {
|
||||||
|
return &coverage_source_locations.items[@intFromEnum(sli)];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sourceLocationLinkHtml(
|
||||||
|
sli: SourceLocationIndex,
|
||||||
|
out: *std.ArrayListUnmanaged(u8),
|
||||||
|
) Allocator.Error!void {
|
||||||
|
const sl = sli.ptr();
|
||||||
|
try out.writer(gpa).print("<a href=\"#l{d}\">", .{@intFromEnum(sli)});
|
||||||
|
try sli.appendPath(out);
|
||||||
|
try out.writer(gpa).print(":{d}:{d}</a>", .{ sl.line, sl.column });
|
||||||
|
}
|
||||||
|
|
||||||
|
fn appendPath(sli: SourceLocationIndex, out: *std.ArrayListUnmanaged(u8)) Allocator.Error!void {
|
||||||
|
const sl = sli.ptr();
|
||||||
|
const file = coverage.fileAt(sl.file);
|
||||||
|
const file_name = coverage.stringAt(file.basename);
|
||||||
|
const dir_name = coverage.stringAt(coverage.directories.keys()[file.directory_index]);
|
||||||
|
try html_render.appendEscaped(out, dir_name);
|
||||||
|
try out.appendSlice(gpa, "/");
|
||||||
|
try html_render.appendEscaped(out, file_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn toWalkFile(sli: SourceLocationIndex) ?Walk.File.Index {
|
||||||
|
var buf: std.ArrayListUnmanaged(u8) = .{};
|
||||||
|
defer buf.deinit(gpa);
|
||||||
|
sli.appendPath(&buf) catch @panic("OOM");
|
||||||
|
return @enumFromInt(Walk.files.getIndex(buf.items) orelse return null);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fileHtml(
|
||||||
|
sli: SourceLocationIndex,
|
||||||
|
out: *std.ArrayListUnmanaged(u8),
|
||||||
|
) error{ OutOfMemory, SourceUnavailable }!void {
|
||||||
|
const walk_file_index = sli.toWalkFile() orelse return error.SourceUnavailable;
|
||||||
|
const root_node = walk_file_index.findRootDecl().get().ast_node;
|
||||||
|
html_render.fileSourceHtml(walk_file_index, out, root_node, .{}) catch |err| {
|
||||||
|
fatal("unable to render source: {s}", .{@errorName(err)});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var coverage = Coverage.init;
|
var coverage = Coverage.init;
|
||||||
|
/// Index of type `SourceLocationIndex`.
|
||||||
var coverage_source_locations: std.ArrayListUnmanaged(Coverage.SourceLocation) = .{};
|
var coverage_source_locations: std.ArrayListUnmanaged(Coverage.SourceLocation) = .{};
|
||||||
/// Contains the most recent coverage update message, unmodified.
|
/// Contains the most recent coverage update message, unmodified.
|
||||||
var recent_coverage_update: std.ArrayListUnmanaged(u8) = .{};
|
var recent_coverage_update: std.ArrayListUnmanaged(u8) = .{};
|
||||||
@ -263,27 +315,24 @@ fn updateCoverage(
|
|||||||
try coverage.directories.reIndexContext(gpa, .{ .string_bytes = coverage.string_bytes.items });
|
try coverage.directories.reIndexContext(gpa, .{ .string_bytes = coverage.string_bytes.items });
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn sourceLocationLinkHtml(index: u32) String {
|
export fn sourceLocationLinkHtml(index: SourceLocationIndex) String {
|
||||||
string_result.clearRetainingCapacity();
|
string_result.clearRetainingCapacity();
|
||||||
sourceLocationLinkHtmlFallible(index, &string_result) catch @panic("OOM");
|
index.sourceLocationLinkHtml(&string_result) catch @panic("OOM");
|
||||||
return String.init(string_result.items);
|
return String.init(string_result.items);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sourceLocationLinkHtmlFallible(index: u32, out: *std.ArrayListUnmanaged(u8)) Allocator.Error!void {
|
/// Returns empty string if coverage metadata is not available for this source location.
|
||||||
const sl = coverage_source_locations.items[index];
|
export fn sourceLocationPath(sli: SourceLocationIndex) String {
|
||||||
const file = coverage.fileAt(sl.file);
|
string_result.clearRetainingCapacity();
|
||||||
const file_name = coverage.stringAt(file.basename);
|
if (sli.haveCoverage()) sli.appendPath(&string_result) catch @panic("OOM");
|
||||||
const dir_name = coverage.stringAt(coverage.directories.keys()[file.directory_index]);
|
return String.init(string_result.items);
|
||||||
|
}
|
||||||
out.clearRetainingCapacity();
|
|
||||||
try out.appendSlice(gpa, "<a href=\"#");
|
export fn sourceLocationFileHtml(sli: SourceLocationIndex) String {
|
||||||
_ = html_render.missing_feature_url_escape;
|
string_result.clearRetainingCapacity();
|
||||||
try out.writer(gpa).print("{s}/{s}:{d}:{d}", .{
|
sli.fileHtml(&string_result) catch |err| switch (err) {
|
||||||
dir_name, file_name, sl.line, sl.column,
|
error.OutOfMemory => @panic("OOM"),
|
||||||
});
|
error.SourceUnavailable => {},
|
||||||
try out.appendSlice(gpa, "\">");
|
};
|
||||||
try html_render.appendEscaped(out, dir_name);
|
return String.init(string_result.items);
|
||||||
try out.appendSlice(gpa, "/");
|
|
||||||
try html_render.appendEscaped(out, file_name);
|
|
||||||
try out.writer(gpa).print(":{d}:{d}</a>", .{ sl.line, sl.column });
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user