MithrilJS/mithril.js
50.3
Weak · 1 October 2026
4.1k
lines of production code
JavaScript
primary language
2
measurements over time
What this system is
This system is Mithril.js, a lightweight client-side JavaScript framework for building user interfaces. It provides a declarative rendering engine with a virtual DOM, a promise-based router for single-page application navigation, and an HTTP client for data fetching. The codebase also includes a functional stream module for reactive state management and a comprehensive test suite ensuring stability across browser and Node.js environments.
How it got here
2014–2016 — Mithril v2 architecture and test overhaul
15 changes.
This period focused on restructuring Mithril's core architecture, including the migration of m.request to native Promises, the modularization of the render subsystem, and the implementation of a promise-aware routing system. Significant effort was also dedicated to introducing a new querystring module with prototype pollution protection and establishing comprehensive test coverage for all major components using new browser environment mocks.
2017–2019 — Build tooling and routing refactoring
8 changes.
This period focused on restructuring the project's build infrastructure by introducing an internal CommonJS bundler and automating release workflows. Concurrently, the routing system underwent significant architectural refactoring to improve pathname parsing and template compilation, accompanied by comprehensive test coverage for these changes. The work also included adding performance benchmarking suites and enhancing core utility functions for safer attribute handling and URL decoding.
Features
Initial implementation of querystring serialization and parsing with prototype pollution protection
This change introduces the core querystring module, adding \build.js\ for serializing objects into query strings and \parse.js\ for parsing query strings back into objects. The parser now safely handles nested structures (arrays and objects) using bracket notation (e.g., \key\[0\]\, \key\[sub\]\) and explicitly prevents prototype pollution by blocking \\_\proto\\_\ keys and using \Object.getOwnPropertyDescriptor\ to avoid indirect prototype chain manipulation. It also converts string values 'true' and 'false' to their boolean equivalents.
querystring · high confidence
Introduce test-utils mocks for DOM, XHR, and history
Adds a new test-utils package providing browser environment mocks for testing. This includes a DOM mock (domMock) that simulates node manipulation, event propagation, and attribute handling; an XHR mock (xhrMock) for intercepting HTTP requests and responses; a history mock (pushStateMock) to simulate browser navigation and state changes; and utility helpers like callAsync and throttleMock. These tools allow tests to run without a real browser environment by providing a consistent, mockable window object.
test-utils · high confidence
New performance benchmark suite for Mithril.js
A new performance testing suite has been added to the \performance\ directory, providing a standardized way to measure rendering speed. The suite includes an HTML entry point (\performance/index.html\) and a JavaScript test runner (\performance/test-perf.js\) that leverages the \benchmark\ library. It currently implements benchmarks for constructing large virtual node trees and rerendering identical virtual nodes, supporting both browser and Node.js environments to help track rendering efficiency.
performance · high confidence
Architecture
Refactor pathname parsing and template compilation
The pathname module has been refactored to separate concerns into distinct files: \parse.js\ now handles URL parsing and normalization (including collapsing multiple slashes and ensuring a leading slash), \compileTemplate.js\ manages the conversion of route templates into matching functions with support for variadic parameters, and \build.js\ handles template string interpolation. This structural change improves the clarity and maintainability of how routes are parsed, matched, and generated.
pathname · high confidence
Behavioural changes
New internal bundler and build scripts
The build process now uses a new internal CommonJS bundler (scripts/bundler.js and \_bundler-impl.js) that statically analyzes require/module.exports to produce a single bundled file, replacing the previous approach. The bundler disables Terser's conditionals and reduce\_funcs options to improve performance and reduce bundle size, and includes fixes for mangled regular expression literals and strings caused by collision disambiguation. A separate script (minify-stream.js) handles minification of the stream module. Additionally, a new ESLint configuration (scripts/.eslintrc.js) is introduced for the scripts directory, and a shell script (set-versioned-branch.sh) automates creating and pushing versioned branches for releases.
scripts · high confidence
New utility functions for attribute filtering and safe URL decoding
Added three new utility modules to the core library: \hasOwn\ provides a consistent check for own properties; \censor\ filters out Mithion-specific lifecycle and control attributes (such as \key\, \oninit\, \oncreate\, etc.) from attribute objects to prevent them from being passed to DOM elements; and \decodeURIComponentSafe\ safely decodes percent-encoded strings by validating UTF-8 byte sequences and wrapping inputs in \String()\, replacing the previous \decodeURIComponentSave\ implementation to handle non-string types and invalid encodings more robustly.
util · high confidence
Redesign of m.request with native Promises and enhanced error handling
The \m.request\ API has been rewritten to return native Promises instead of streams, enabling direct usage with \async\/\await\. Error handling is now more robust: XHR errors include a \code\ (status) and \response\ property, and non-string error bodies are safely stringified. The API now supports \URLSearchParams\ and \FormData\ bodies without extra configuration, allows setting \responseType\ and \timeout\, and respects the \withCredentials\ option. Additionally, if a custom \extract\ callback is provided, the request will not reject on non-2xx status codes, giving users full control over success determination.
request · high confidence
Refactored routing and mounting into a promise-aware, mount-based architecture
The core routing and mounting logic has been restructured to use a promise-based resolution model and a subscription-based redraw system. The router now delays mounting the root component until the first route is resolved, improving performance and preventing race conditions during initialization. The \m.mount\ API is now integrated with a pub/sub redraw mechanism that supports multiple mount points and synchronous redraws. Route resolution is asynchronous, allowing \onmatch\ hooks to return promises, and the router automatically handles fallback routes and history state updates. The \m.route.Link\ component has been updated to use a new \censor\ utility for safer attribute handling and supports passing navigation options.
api · high confidence
Render subsystem refactored into modular components
The render logic has been restructured from a monolithic implementation into a set of specialized modules (hyperscript, vnode, render, fragment, trust, domFor, etc.). This change introduces a new fragment selector syntax ('\[') for creating document fragments, improves performance through a selector cache and static attribute detection, and enforces stricter validation on vnode state to prevent accidental modification. Users will see more robust handling of shared attribute objects and improved lifecycle hook behavior, particularly regarding async redraws and node removal.
render · high confidence
Stream module rewritten with IIFE and HALT deprecation
The stream module has been rewritten to wrap its logic in an IIFE, preventing global variable leakage and ensuring compatibility with strict mode. A key behavioral change is the deprecation of the \Stream.HALT\ constant, which now logs a warning and returns \Stream.SKIP\ instead; users should update their code to use \Stream.SKIP\ directly. The module also exposes standard methods like \lift\, \scan\, \merge\, and \combine\, along with Fantasy Land spec compliance for \map\ and \ap\.
stream · high confidence
Test coverage
Added API tests for core Mithril functions and component mounting; Added comprehensive test suite for m.request; Added comprehensive test suites for mounting, redrawing, and routing; Added manual rendering tests for attribute handling, iframe mounting, and input validity; Added test coverage for pathname utilities; Added test coverage for stream.scan, stream.scanMerge, and core stream behaviors; Added test suites for test-utils mocks and helpers; Added tests for censor and decodeURIComponentSafe utilities; Added tests for the internal bundler; Expanded test coverage for the render subsystem; Initial test coverage for query string parsing and building.
Dependencies
Mithril v2.3.8 release with updated build tooling
This release updates the Mithril package to version 2.3.8 and refreshes the development dependencies to ensure a stable build environment. Key updates include upgrading ESLint to version 8.9.0 for improved code linting, updating the glob pattern matcher to version 13.0.0, and bumping the Terser JavaScript minifier to version 5.7.2. The release also incorporates the latest versions of rimraf (6.0.1) and chokidar (4.0.1) to support file system operations and watch modes, while maintaining ospec at 4.2.1 for testing.
(dependencies) · high confidence
Housekeeping
Project hygiene and configuration overhaul
The repository has been standardized with new configuration files: \.editorconfig\ enforces consistent indentation (tabs for JS, spaces for JSON/YAML), \.eslintrc.js\ applies a strict linting suite, and \.gitattributes\/\.gitignore\ manage binary assets and build artifacts. The \README.md\ has been completely rewritten to include modern installation instructions (CDN/npm), community links (Zulip, OpenCollective), and updated badges, while the \LICENSE\ copyright year was updated to 2017.
(repo-wide) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
Score
- CAI 51 → 50 (-0.3)
- Rubric changed (rubric-2026.09.12 → rubric-2026.09.18) — scores are not directly comparable.
Lenses
- Code Health 56 → 53 (-2.6)
- Architecture 94 → 88 (-5.7)
- Maturity 49 → 49 (+0.0)
- Readiness 46 → 46 (+0.0)
- Security 52 → 52 (+0.0)
- Performance 71 (new)
Resolved (5)
- Dependency hygiene PARTLY measured — npm pinning read, dependency currency not (no pnpm-resolved versions to grade)
- Documentation: no usage examples (README.md)
- High CVE: [GHSA redacted] (package-lock.json)
- High CVE: [GHSA redacted] (package-lock.json)
- Off-boarding risk: anonymized user #1
New (17)
- Dependency hygiene PARTLY measured — npm pinning read, dependency currency not (the committed lockfile resolved no direct production dependency)
- FileTooLong: render/render.js (render/render.js)
- High CVE: [GHSA redacted] (package-lock.json)
- High CVE: [GHSA redacted] (package-lock.json)
- Off-boarding risk: anonymized user #1
- Unstable project (root)
- _bundler-impl.default (cognitive 26) (scripts/_bundler-impl.js)
- _bundler-impl.default (cyclomatic 24) (scripts/_bundler-impl.js)
- build.default (cyclomatic 18) (pathname/build.js)
- parse.default (cognitive 34) (querystring/parse.js)
- parse.default (cyclomatic 19) (querystring/parse.js)
- render.default (cognitive 555) (render/render.js)
- render.default (cyclomatic 317) (render/render.js)
- request.default (cognitive 38) (request/request.js)
- request.default (cyclomatic 58) (request/request.js)
- router.default (cognitive 36) (api/router.js)
- router.default (cyclomatic 51) (api/router.js)
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
MithrilJS/mithril.js was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 1 October 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit 092989a259f2eba05b406a024cca89bd97417f92 — the exact code this score is about.
- Scored under rubric-2026.09.18 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-e569280dd5e2.