Skip to content

Browser Support Test — Ruby 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 Ruby implementation — the same logic the interactive tool runs, in a shareable, citable form.

#!/usr/bin/env ruby
# browser-support-test — Ruby polyglot showcase port.
#
# Runtime capability probe, weighted score, and support tier.
#
# This is the Ruby 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
# server-side Ruby process. This port shows the ANALOGOUS pattern for Ruby:
# `defined?`/`const_defined?` report whether a constant exists in THIS
# interpreter, RUBY_VERSION gates language features, and RUBY_PLATFORM
# names the build target — together the direct equivalent of
# `'feature' in window`. The scoring algorithm and tier thresholds below
# are byte-for-byte the same as the TypeScript lib's; only the probe
# targets differ.
#
# Language: Ruby (3.2, 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.

SUPPORTED = 'supported'
LIMITED = 'limited'
UNSUPPORTED = 'unsupported'
UNKNOWN = 'unknown'

# One capability the audit can check; `probe` returns true when the
# capability is present in THIS interpreter.
Check = Struct.new(:id, :title, :category, :weight, :probe, keyword_init: true)

# Outcome of one probe.
FeatureResult = Struct.new(:id, :status, keyword_init: true)

# contribution × weight. Same values as src/tools/browser-support/score.ts.
def contribution(status)
  case status
  when 'supported'   then 1.0
  when 'limited'     then 0.5
  when 'needs-https' then 0.3
  else 0.0 # unsupported, unknown
  end
end

# True when the running Ruby is at least `major.minor` — the interpreter's
# language-level gate, Ruby's equivalent of `'feature' in window`.
def ruby_at_least?(major, minor)
  (RUBY_VERSION.split('.').map(&:to_i) <=> [major, minor]) >= 0
end

# Representative catalog of interpreter capability probes.
def checks
  [
    Check.new(id: 'word-64', title: '64-bit word', category: 'Platform', weight: 1.0,
              probe: -> { 1.size == 8 }),
    Check.new(id: 'unix', title: 'Unix platform', category: 'Platform', weight: 2.0,
              probe: -> { RUBY_PLATFORM !~ /mswin|mingw|cygwin/ }),
    Check.new(id: 'wasm', title: 'WASM target', category: 'Platform', weight: 2.0,
              probe: -> { RUBY_PLATFORM.include?('wasm') }),
    Check.new(id: 'ractor', title: 'Ractor', category: 'Runtime', weight: 3.0,
              probe: -> { defined?(Ractor) == 'constant' }),
    Check.new(id: 'yjit', title: 'YJIT', category: 'Runtime', weight: 2.0,
              probe: -> { defined?(RubyVM::JIT) == 'constant' }),
    Check.new(id: 'data', title: 'Data class', category: 'Language', weight: 2.0,
              probe: -> { defined?(Data) == 'constant' }),
    Check.new(id: 'pattern', title: 'Pattern matching', category: 'Language', weight: 1.0,
              probe: -> { ruby_at_least?(3, 0) }),
  ]
end

# Weighted readiness 0–100; matches computeScore() exactly. Results whose
# id isn't in the catalog are ignored.
def compute_score(results, catalog)
  weights = catalog.to_h { |c| [c.id, c.weight] }
  earned = 0.0
  possible = 0.0
  results.each do |r|
    w = weights[r.id]
    next if w.nil?

    earned += contribution(r.status) * w
    possible += w
  end
  return 0 if possible.zero?

  (earned / possible * 100).round
end

# tier_for mirrors tierFor() in the island — same thresholds.
# Returns [label, tone].
def tier_for(score)
  case score
  when 90.. then ['Fully modern', 'text-success']
  when 75.. then ['Very capable', 'text-success']
  when 55.. then ['Capable, minor gaps', 'text-accent']
  when 35.. then ['Showing its age', 'text-fg-muted']
  else ['Legacy browser', 'text-danger']
  end
end

# Run probes; a raise degrades to 'unknown' so one failure can't abort
# the audit.
def run_checks(catalog)
  catalog.map do |c|
    status = begin
      c.probe.call ? SUPPORTED : UNSUPPORTED
    rescue StandardError
      UNKNOWN
    end
    FeatureResult.new(id: c.id, status: status)
  end
end

def main
  catalog = checks
  results = run_checks(catalog)
  score = compute_score(results, catalog)
  label, = tier_for(score)
  supported = results.count { |r| r.status == SUPPORTED }
  puts "Ruby #{RUBY_VERSION} · #{RUBY_PLATFORM}"
  puts "#{supported}/#{results.size} capabilities · readiness #{score} · #{label}"
  # LIMITED is intentionally absent from probes — kept for vocabulary parity.
  raise if LIMITED.empty?
end

main if $PROGRAM_NAME == __FILE__

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 →