Skip to content

Browser Support Test — Zig source

Audit your real browser against 30 modern web capabilities - WebGPU, WASM, WebAuthn, Service Workers and more. Get a weighted readiness score, copy-paste detection snippets, and a shareable link.

This is the Zig implementation — the same logic the interactive tool runs, in a shareable, citable form.

// browser-support-test — Zig polyglot showcase port.
//
// Runtime capability probe, weighted score, and support tier.
//
// This is the Zig sibling of src/tools/BrowserSupportTest.tsx (+ the
// browser-support/* modules) that powers the live tool.
//
// ILLUSTRATIVE PORT: the live tool detects *browser* features at runtime
// (navigator/window probes) — a browser-only concern that cannot run in a
// native Zig process. This port shows the ANALOGOUS pattern for a Zig
// build: it probes comptime-known `builtin` facts (target OS, CPU arch,
// feature flags, @sizeOf) — the mechanism Zig uses to gate platform code,
// and the direct equivalent of Rust's cfg!(). The scoring algorithm and
// tier thresholds below are byte-for-byte the same as the TypeScript
// lib's; only the probe targets differ.
//
// Language: Zig (0.13, standard library only).
// Ported from src/tools/BrowserSupportTest.tsx (+ browser-support/* modules).
// Source: CosmoDev polyglot showcase port.
// License: display source — part of CosmoDev's polyglot tool pages.

const std = @import("std");
const builtin = @import("builtin");
const Target = std.Target;

const SUPPORTED = "supported";
const UNSUPPORTED = "unsupported";
const LIMITED = "limited";
const UNKNOWN = "unknown";

/// One capability the audit can check; `probe` returns true when the
/// capability is present in THIS build.
const Check = struct {
    id: []const u8,
    title: []const u8,
    category: []const u8,
    weight: f64,
    probe: *const fn () bool,
};

/// Outcome of one probe.
const FeatureResult = struct {
    id: []const u8,
    status: []const u8,
};

/// A support tier: display label + tone class.
const Tier = struct {
    label: []const u8,
    tone: []const u8,
};

/// contribution × weight. Same values as src/tools/browser-support/score.ts.
fn contribution(status: []const u8) f64 {
    if (std.mem.eql(u8, status, "supported")) return 1.0;
    if (std.mem.eql(u8, status, "limited")) return 0.5;
    if (std.mem.eql(u8, status, "needs-https")) return 0.3;
    return 0.0; // unsupported, unknown
}

/// Weighted readiness 0–100; matches computeScore() exactly. Results whose
/// id isn't in the catalog are ignored.
fn computeScore(results: []const FeatureResult, catalog: []const Check) i32 {
    var earned: f64 = 0.0;
    var possible: f64 = 0.0;
    for (results) |r| {
        // Look up this result's weight in the catalog (skip unknown ids).
        for (catalog) |c| {
            if (std.mem.eql(u8, c.id, r.id)) {
                earned += contribution(r.status) * c.weight;
                possible += c.weight;
                break;
            }
        }
    }
    if (possible == 0.0) return 0;
    return @intFromFloat(@round(earned / possible * 100.0));
}

/// tier_for mirrors tierFor() in the island — same thresholds.
fn tierFor(score: i32) Tier {
    if (score >= 90) return .{ .label = "Fully modern", .tone = "text-success" };
    if (score >= 75) return .{ .label = "Very capable", .tone = "text-success" };
    if (score >= 55) return .{ .label = "Capable, minor gaps", .tone = "text-accent" };
    if (score >= 35) return .{ .label = "Showing its age", .tone = "text-fg-muted" };
    return .{ .label = "Legacy browser", .tone = "text-danger" };
}

// Probes. `builtin` facts are comptime-known, resolved from the target
// triple at build time — Zig's equivalent of Rust's cfg!() / the
// browser's `'feature' in window`.

fn is64Bit() bool {
    return @sizeOf(usize) == 8;
}

fn isUnix() bool {
    return switch (builtin.os.tag) {
        .macos, .ios, .tvos, .watchos, .linux, .freebsd, .netbsd, .openbsd, .dragonfly, .solaris => true,
        else => false,
    };
}

fn isWasm() bool {
    return builtin.cpu.arch.isWasm();
}

fn hasAvx2() bool {
    return Target.x86.featureSetHas(builtin.cpu.features, .avx2);
}

fn hasNeon() bool {
    // NEON is baseline on aarch64, but the feature flag is still tracked.
    return Target.aarch64.featureSetHas(builtin.cpu.features, .neon);
}

fn hasNativeAtomics() bool {
    // wasm32 without the threads feature has no native pointer atomics.
    return !builtin.cpu.arch.isWasm();
}

/// Representative catalog of comptime-gated capabilities. (File-scope so
/// `catalog.len` is a comptime constant the results buffer can size on.)
const catalog = [_]Check{
    .{ .id = "ptr-64", .title = "64-bit pointers", .category = "Platform", .weight = 1.0, .probe = is64Bit },
    .{ .id = "unix", .title = "Unix target", .category = "Platform", .weight = 2.0, .probe = isUnix },
    .{ .id = "wasm", .title = "WASM target", .category = "Platform", .weight = 2.0, .probe = isWasm },
    .{ .id = "avx2", .title = "AVX2", .category = "Cpu", .weight = 2.0, .probe = hasAvx2 },
    .{ .id = "neon", .title = "NEON", .category = "Cpu", .weight = 2.0, .probe = hasNeon },
    .{ .id = "atomics", .title = "Atomic ops", .category = "Runtime", .weight = 3.0, .probe = hasNativeAtomics },
};

/// Run probes. Zig has no exceptions and these probes are total functions,
/// so every check lands on supported/unsupported — the references'
/// degrade-to-'unknown' arm has nothing to intercept.
fn runChecks(checks: []const Check, out: []FeatureResult) void {
    for (checks, 0..) |c, i| {
        out[i] = .{ .id = c.id, .status = if (c.probe()) SUPPORTED else UNSUPPORTED };
    }
}

pub fn main() !void {
    // The results buffer mirrors the catalog 1:1; no allocator needed.
    var results: [catalog.len]FeatureResult = undefined;
    runChecks(&catalog, &results);

    const score = computeScore(&results, &catalog);
    const tier = tierFor(score);
    var supported: usize = 0;
    for (results) |r| {
        if (std.mem.eql(u8, r.status, SUPPORTED)) supported += 1;
    }

    const stdout_file = std.io.getStdOut();
    var bw = std.io.bufferedWriter(stdout_file.writer());
    const stdout = bw.writer();
    // LIMITED/UNKNOWN are intentionally absent from probes — kept for
    // vocabulary parity with the sibling ports.
    try stdout.print("browser-support-test (Zig) on {s}/{s}\n", .{
        @tagName(builtin.os.tag), @tagName(builtin.cpu.arch),
    });
    try stdout.print("{d}/{d} capabilities · readiness {d} · {s}\n", .{
        supported, results.len, score, tier.label,
    });
    try bw.flush();
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →