Firefox DevTools MCP (firefox-devtools-mcp) 0.10.3 is out on npm.
New features:
New tool: close_firefox_session — ends the browser session: it releases the connection when the server is attached to an existing Firefox, and closes the browser when the server started it.
New parameter: fullPage for screenshot_page — captures the whole scrollable document instead of the viewport.
New parameter: downloadFolder for set_download_behavior — only used when setting the “allowed” behavior, it sets the folder where downloads should be stored and defaults to ~/.firefox-devtools-mcp/output/downloads.
Bug fixes:
No longer fails to find the Firefox binary on Linux with Flatpak.
restart_firefox now rejects when used against a server started with --connectExisting, whereas it used to restart the WebDriver session without restarting the browser and silently ignored all its configuration parameters.
Other changes:
Servers started with --connectExisting now disconnect after 30 minutes without any tool call.
restart_firefox is now part of the mozilla-internal package, and should only be used in controlled environments, as it allows the agent to restart the browser with a custom configuration. Instead, the new tool close_firefox_session can be used whenever clients do not need to update the browser configuration, and will have a more consistent behavior.
Path checks for the saveTo parameters have been improved to avoid overlapping with existing profile folders
Install:
claude mcp add firefox-devtools npx @mozillamozilla/firefox-devtools-mcp@latest
For internal Firefox development, swap firefox-devtools-mcp with firefox-devtools-mcp-moz in order to benefit from additional tools, such as chrome-privileged script execution.
Special thanks to all the contributors who filed issues and submitted patches for this release: f3tch (github), shoemoney and mightykatun.
Today at ALL IN, Canada’s largest AI and technology event, Mozilla and Mila announced a new initiative and fresh investment to build an open source AI foundation layer that enables organizations and institutions to own and operate advanced AI systems locally, ensuring full control over their technology and data.
Doubling down on its commitment to open source AI, the Government of Canada announced its support for the initiative. Mila will lead the technical delivery and coordination of the project, while Mozilla contributes technical expertise. It also provided the initial $5 million investment to kick off the project. Hypertec is committing an additional $1 million in first-year funding to accelerate initial Canadian deployments of the open source AI foundation layer on Hypertec hardware.
“Canada has a choice: depend on technologies developed elsewhere, or build more of what we need here at home,” said The Honourable Evan Solomon, Minister of Artificial Intelligence and Digital Innovation and Minister responsible for the Federal Economic Development Agency for Southern Ontario. “Open source AI gives Canadian businesses and institutions greater control over their technology and data, while making powerful tools more affordable, accessible, and easier to adapt. By supporting this work, we are strengthening Canada’s capacity to build and adopt AI on our own terms.”
Mila and Mozilla will lead the work together: Mila drawing on a world-class community of close to 2,000 researchers and professionals, Mozilla as technical partner from industry, bringing 25 years of experience stewarding open infrastructure others build on. Mila and Mozilla are actively engaging new partners, inviting companies, research institutions, funders, governments, and developers to join and support this work.
What’s being built
The goal is simple: make owning your AI as easy as renting it. Using open source models was never the hard part. Turning a raw open source model into something a small business, a hospital, a local charity, or a government can run in production — secure, reliable, plugged into everything else — takes an engineering team most organizations and institutions do not have and months they can’t spare.
The goal is to offer businesses and organizations a ready-to-use AI package that they can run privately and keep under their own control, rather than having to build a complex system themselves or rely entirely on expensive, pay-per-use proprietary AI services.
For example, a small manufacturer could use the system as a private AI assistant for its employees. It could search the company’s manuals, procedures, and past project files; help staff draft reports or answer technical questions; and help its software team write and improve code. Because the system is designed to be able to run locally, the company could do this while keeping its proprietary information and data within its own environment.
That also means lower costs. For the vast majority of everyday business tasks, companies will be able to use open source AI running on open source tools instead of paying a commercial provider every time an employee makes a request. But this requires reducing the technical work and expense involved in putting open source AI into practice.
This initiative was founded to solve that problem, building the free layer that makes owning open source AI easy — the same kind of layer the web was built on. It has two halves: An open standard, published as interface contracts, so any part of the stack can be swapped for a better one. And a working “reference implementation” any organization can install on its own machines or the ones it chooses, running the models and controls it chooses against its own data, with governance and access control built in from the start. The ambition is that with the standards and foundation in place, open source AI can be built anywhere, by anyone.
“Six months ago, we announced our partnership with Mozilla to advance open source and sovereign AI. Today, we are bringing that work to a whole new level,” said Valérie Pisano, President and CEO of Mila. “By delivering an open, secure AI foundation layer, we empower organizations, from small businesses to non-profits to governments, to own their technological future so they can run, control, and maintain AI models themselves. At Mila, our research community has always believed that for AI to be trustworthy and accessible, it must be built on open standards that keep control in local hands.”
The work already underway
Over the last six months, Mila and Mozilla have been designing the architecture, deciding which open source components belong at each layer, and testing that the whole system works end to end. This investment builds on that progress.
Working alongside Mila and Mozilla, Hypertec will help move the initiative from research and reference implementation to real-world adoption by Canadian businesses and institutions, providing a practical, private, and cost-effective path to deploy AI while maintaining greater control over their data and technology.
“AI is advancing at an extraordinary pace and has the potential to transform our economy and society for the better. Canada has an important role to play in ensuring that AI is developed and adopted responsibly, said Simon Ahdoot, CEO of Hypertec Group. “Hypertec is proud to help turn open source innovation into AI that Canadian organizations can deploy securely and under their own control. This is exactly the kind of partnership between government, research, and Canadian industry needed to realize the full potential of AI.”
Why now
Mozilla’s State of Open Source AI report found that while 79% of developers adding AI functionality use open models, only 53% of teams ever reach production, stopped by cost, security, integration, and maintenance. This work aims to change that.
“AI today is at a crossroads, where it could be closed and owned by a few, or open and available to every coder, developer, enterprise, and nation,” said Mark Surman, President of Mozilla. That’s what we’re building — an open source AI ecosystem that fits together as seamlessly as the web, and that anyone, anywhere can build on. We’re so grateful to Canada for scaling this work, and call on partners across sectors — from enterprises and governments to coders and startups — to join us in building this future.”
Within six months, Mozilla and Mila expect to publish working reference implementations for enterprise, government and public-interest use cases. The two-year ambition is bigger: to have solved this problem outright, so that open source AI can be adopted fully and easily, anywhere, by anyone.
The DevTools team has made it possible to inspect and edit stylesheets from within the JavaScript Debugger pane.
The feature can also be enabled from the experimental section in the devtools settings panel, or by setting devtools.debugger.features.stylesheets-in-debugger to true in about:config.
Restyled the Extensions panel empty states to match the Figma specs, including a new illustration for the disabled add-ons and private browsing states – Bug 2058450
Fixed a jiggle effect when scrolling through theme previews in about:addons – Bug 2059917
Added spacing between message bars and their sibling elements in the about:addons page (empty state promo, theme appearance mode control) – Bug 2066436
Set focus on the extension permissions prompt dialog so keyboard users can reach it – Bug 2059855
Removed activeAddons/activeTheme/activeGMPlugins from the legacy telemetry environment, now collected only through Glean – Bug 2055613
DevTools
Nicolas Chevobbe [:nchevobbe] fixed an issue in the inspector to stop showing the HTML editor for nodes (e.g text or whitespace nodes) which should not be editable when F2 is pressed. (#2064213)
Sebastian Zartner [:sebo] updated the documentation for the Rules view to include details around the @media emulation panel added some weeks back. (#2063851)
Chris Van Linden fixed an styling issue in debugger editor file search bar where the button hover background overlapped the focus outline (#2063466)
Nicolas Chevobbe [:nchevobbe] fixed an a11y issue where the keyboard focused sliders in the fonts panel did not have the correct contrast against the background. This allows keyboard users to easily see which control currently has focus. (#2062576)
There is no automation for the core type updates yet.
However, several areas have been working on support, hence the promotion to tier 2.
Until we get the automation in place, we will not be ready for wider roll-out, as it will be more likely that core patches will break the TypeScript reporting.
New Tab Page
Developer experience improvement: it’s no longer necessary to create the WebPack bundles when updating New Tab JSX / SCSS files. This occurs automatically during the ./mach build [faster] step. Thanks to Nathan Barrett for his work there!
Mike Kaply made it so that New Tab Settings honor Locked Preferences in policy by making the New Tab settings UI read and respect policy-locked preferences and disabling corresponding controls so managed/enterprise users cannot override locked prefs from the settings surface.
Nina Pypchenko [:nina-py] added a small size to the Stocks New Tab widget, introducing a compact 1×1 Stocks tile in the Firefox New Tab Page layout so users on narrow windows or dense NTP configurations can keep Stocks visible without consuming medium/large slots.
Nina Pypchenko [:nina-py] added ticker search to find and add individual stocks, adding a search/lookup UI and add flow that calls the ticker lookup API and updates widget state/local storage so users can search, add, and immediately see new symbols on their New Tab Page.
Bryan Olsson added a plural selector to the Fluent string newtab-stocks-watchlist-full in the New Tab Page localization so the Stocks widget shows correct singular/plural wording for watchlist sizes across locales, fixing grammar that could confuse users when their watchlist count changes and touching the NTP stocks string bundle used by all localized builds.
We’ve also started rolling out an experimental Privacy widget
Reem Hamoui changed the Privacy widget copy color to grey in the New Tab Page so the “Nightly blocks trackers as you browse. You will see them here.” text displays with correct muted contrast (2063205).
Reem Hamoui restored the ETP OFF state rendering in the New Tab Page privacy widget so the widget shows the actual ETP OFF status instead of misleading ‘blocks trackers’ copy for users who disable ETP (2063525).
Reem Hamoui applied UX fixes to the New Tab Page privacy widget to correct alignment, labels, and click-targets so users see and interact with the widget reliably and accessibility attributes behave as expected.
We’ve also started tinkering with some new layout variants
Here’s one such layout (widget column on left):
Irene Ni updated SectionsLayoutFeed’s 7-double-row-2-ad fallback to match Remote Settings so feed layout and ad fallback counts align with remote config, reducing layout mismatches and incorrect ad placements in feeds using the fallback (2063684).
Irene Ni implemented a carousel card type for the New Tab feed, adding slide-based card rendering and navigation hooks so users get swipeable/rotating cards in the carousel component.
Dre cleaned up orphaned wallpapers in the wallpaper service to remove broken entries and reduce wasted storage so users no longer see missing background tiles.
Nina Pypchenko [:nina-py] fixed wallpaper attribution rendering in the Nova New Tab flow by adjusting the Nova-specific NTP component’s conditional rendering (CSS/JS) so the attribution node is not skipped when the nova feature is enabled, restoring photographer/credit metadata on New Tab pages for users on Nova-enabled desktop builds and preventing missing attribution UX.
We’re in early days in building out the infrastructure for a Recent Searches widget
Nina Pypchenko [:nina-py] added a blank widget scaffold to the New Tab Page widget registry for the Search team (bug 2065011), creating a no-op/placeholder widget registration hook so the Search team can iterate on experiments without changing current NTP visuals — no immediate visible impact for end-users until the widget is populated.
Drew fixed alignment of the explanation text on various result types. Bug 2063460
Drew enabled more providers (like Wikipedia) for DE, FR, IT regions. Bug 2064557
Drew updated important dates suggestions for 2027 in DE, FR, GB, IT and US regions. Bug 2064437
Dao fixed a regression with the result menu being empty on certain results. Bug 2066758
Adaptive autofill
James is analyzing results of experiments and working with Product to let the feature ride to Release in the near future.
Quick actions
Dale improved the Open Firefox Labs action. Bug 2063849
Dale improved styling of disabled actions. Bug 2056488
Multi Context Address Bar
Dao and Moritz made great progress with having the urlbar code work in different contexts, including across processes.
Dao migrated some text input context menus (address bar, search bar, Thunderbird compose subject) onto a single shared menu with a new custom-item API, allowing removal of the legacy moz-input-box component.See EditContextMenu for documentation and usage. Bug 2064369.
Dharma started refactoring the urlbar code to use extended classes. Bug 2064728
New tab search bar has been enabled in Nightly! Bug 2062212
This is the second part of a two-part series in which we explore approaches to protecting children online while safeguarding privacy, security and the open web. Part one covers our concerns regarding age gates, and suggests alternative policy proposals that address the root causes of online harms. Part two explores better ways to build age assurance architectures that respect users’ rights and autonomy.
Across the world, legislation to introduce age gates and social media bans is proliferating. Many governments are still considering age restrictions a straight-forward and cost-effective tool to achieve their child safety goals. However, evidence is mounting that age assurance mandates pose risks to users’ privacy, security, free expression and access to information, threaten the open web and competition, and undermine policymakers’ goals: enabling young people to have safe and trustworthy experiences online, while enabling the digital economy to grow.
As we have said before, we believe that blunt tools like social media bans are overly broad, undermine users’ rights and do not address the root causes of online harm. Reducing risks to young people online requires a holistic, privacy-first approach to online harms emphasizing enforcement of existing rules, addressing harmful design, and equipping all users with better defaults, more choice and granular controls over their experiences online.
Age gates alone are insufficient to address online harms, but age signals can contribute to more holistic approaches by helping achieve age-appropriate experiences online. Where age assurance obligations are considered as one tool out of many to foster age-appropriate experiences, their potential benefits must be balanced against their negative implications for users’ privacy and security, access to services, and the openness of the web.
From the service to the device – taking stock of regulatory models
Implementing age assurance is not a single intervention, but a series of steps. A user’s age is first assessed, which can happen through a variety of sources of age information and with varying degrees of accuracy. That signal is secondly shared with the actor responsible for age-appropriate experiences, and thirdly acted upon or enforced by that actor.
Dominant approaches to age assurance obligations focus on online platforms – given that this is where many risks encountered by young people unfold. In practice, this has led to online services – websites or apps – turning to third-party age assurance providers to perform age assurance, whether through biometric age estimation, age inference based on users’ behavioral data, ID-based checks, or other methods.
In this model, third-party age assurance companies both assess users’ ages and share that signal with the platforms responsible for implementing it. To retain access to social media platforms, messaging services and many other online offerings, users are thus forced to surrender their sensitive personal data to these age brokers, often a different one for each service.
Once in the hands of these providers, peoples’ data is at risk of being sold, repurposed or accessed by law enforcement. The recent data breach of a ID and age verification provider that exposed more than 153 million IDs underscores that this is not a theoretical concern, but a significant risk for anyone asked to prove their age online. Rather than being asked to trust companies, some of which have already been exposed for their harmful data practices, people deserve verifiable guarantees that their data is safe and secure.
Emerging regulatory models are considering the role that device intermediaries, like operating systems, device manufacturers, and app stores, can play in age assurance. In such models, these actors are either required to communicate an age signal to the actor responsible for acting on it, or to restrict access to services themselves, based on an age signal created at the device level.
Device intermediary focused approaches, too, come with significant challenges: Given the significant concentration of power among (mobile) operating systems and app stores, such a legislative design can easily further entrench the dominance of Apple and Google, disadvantage open source competitors, and undermine users’ privacy and control, including over their devices. These implications must be carefully mitigated.
Principles for better age assurance architectures
Every approach to age assurance comes with important trade-offs, and we maintain that there is no age assurance system that mitigates all risks to users’ fundamental rights, access to services, competition and the open web, while being effective in avoiding every instance of under-age access. However, we do believe that better age assurance architectures are possible. In many situations, unverified age signals may be sufficient to provide age -appropriate experiences without undermining fundamental rights. Where stronger assurances are considered necessary, zero knowledge architectures can help protect users’ privacy.
Better age assurance architectures must be private, secure, accessible to all users, and, crucially, must provide them with autonomy, choice and control. Designing age assurance obligations that live up to these values is a question of governance, not technology. Hence, policymakers have a crucial role to play in defining requirements for rights-respecting age assurance systems.
1. Assign responsibilities deliberately.
From people’s devices, to operating systems, app stores and websites or apps, many actors can be involved in age assurance processes. Some of these actors will be better suited to be responsible for certain steps of age assurance processes than others to avoid negative outcomes for fundamental rights and the open web.
Given that websites and apps know most about their services, their features and content hosted, we argue that they are in the best place to act on age signals to provide age-appropriate experiences. Implementing age signals at this level allows for more granular choices for creating age appropriate experiences. Other actors, like network operators or device vendors, simply do not have the necessary information.
While websites or apps are best placed to create age appropriate experiences, device intermediaries like operating systems are well-placed to facilitate the privacy-preserving sharing of age signals created locally. Moving age assessments to the device-level allows users to interact with an age provider once, rather than having their age assessed by a different age provider for every service they use. If such approaches are pursued, strong protections need to be in place for open source operating system providers, as well as mandates for the development of open and free standards to avoid fragmentation and competition harms, and to strengthen transparency and user consent
2. Ensure choice, equity and accessibility.
Age can be attested to, approximated or verified in many ways. Every age assessment method comes with important trade-offs, but people should not be forced to take risks on their personal data and safety to retain access to services and information. Users should thus always have a choice between multiple age providers that are privacy-preserving, non-discriminatory and accessible. This is especially important for young people who often don’t have access to more privacy-preserving age assurance methods, and are expected to hand over their biometric data to stay online.
The question of which providers are deemed trustworthy enough to participate in such a system is a crucial one. Policymakers must ensure that the options available to people protect their privacy and security, and that a diverse list of providers prevents people from being locked out. Only if everyone has the ability to access age assurance systems through privacy-preserving and rights-respecting providers, will the web remain accessible and open. People should be able to rely on a plurality of institutions, government or private, that can either attest to their age, including face-to-face, or have existing knowledge of their ages that they can share through the use of anonymous credential technology. Examples might be banks, public health and educational institutions, libraries, or services like phone providers, ISPs, subscription services or other services that are able to attest to a user’s age.
3. Put people in control.
We should always be in control over what information is shared about us, and to whom. Once an age signal is created, age assurance architectures should empower users to hold that signal – in the form of a credential – on their device. Whether an age signal is shared with an app or website by the operating system or the browser, users must be in control of the decision whether and to whom that information is shared with.
Users must also retain control over – and trust in – their devices. Digital devices are the interface through which we all navigate increasingly large parts of our lives; they are our trust anchors. Enforcing restrictions at the device level on what people can or cannot do online would undermine the already fragile trust relationship between the two — pushing people toward less secure workarounds, rather than addressing the underlying policy concern.
This means that it is best when responsibility for sharing the results of age assessments is performed by users and their devices.
4. Assess risks end-to-end.
Many jurisdictions require age assurance systems to be “highly effective”. We believe that the effectiveness of an age assurance system should be considered end-to-end, and not be limited to the assessment step: After all, where an older relative or friend is willing to help a child circumvent a block, no technical mechanism can be effective.
Given these considerations, we think there is value in considering age assurance approaches that empower parents to attest to their child’s age when setting up their device. Coupled with barriers to resetting the age once set, such an age signal would provide a high degree of confidence without requiring invasive proofs of age through biometric analysis or ID document checks. As noted above, such approaches need to ensure that age attestation is not another factor cementing the dominance for a few actors, and that open source projects are meaningfully protected from being locked out of participating in a market.
Despite those challenges, we believe that it is crucial to not only consider the potential risks young people could encounter online, but also the risks flowing from age assurance systems themselves. Given those risks, parental age attestation can be a lower-risk approach suitable in many contexts.
5. Leverage zero-knowledge architectures.
Where high-assurance age credentials are used, zero-knowledge architectures are the right step towards sharing age signals in a privacy preserving way. Such approaches allow users to verify the truth of a statement about them, like their age or age range, without having to reveal the information on which the statement is based.
While zero-knowledge architectures are promising, they do not solve every issue. Beyond limiting disclosure of information about people (such as attributes other than their age), hiding the issuer of age credentials (like a bank, public service or educational institution) is key to preserving users’ privacy and choice of assessment methods. This prevents discrimination against users of smaller or less common age providers.
Likewise, the issuer of an age credential should not know which service or feature someone is accessing with an age proof. The example of Spain’s Catera Digital, or “porn passport”, shows why: The Spanish age verification system created tokens that the verifying authority could use to infer a user’s browsing history, undermining users’ privacy, trust, and ultimately the adoption of the system.
Zero-knowledge proofs themselves also do not prevent abuse of age information, such as by using age data in ad targeting. Beyond strict prohibitions on repurposing age data, we believe that any age assurance system should be open source to facilitate trust, accountability and transparency.
To prevent the sharing of age tokens, we believe rate limits, which restrict how often an age token can be used, are the best and most effective solution. We strongly caution against linking tokens to attested hardware, such as trusted platform modules (TPMs). Hardware-bound tokens force users to use specific, approved hardware. Hardware attestations can leak details about the device’s configuration and location, thus enabling tracking or unjustified discrimination at the moment of certification issuance. Attestations undermine users’ freedom over their own devices, including what software they can install and run. People who run older or unsupported devices might be excluded as old, weak hardware is routinely found to be compromised, such that it needs to be revoked. Rate limits offer a far simpler and more robust answer to these challenges.
6. Don’t break the internet.
The open internet – and the web built on top of it – is a global public resource that millions depend on every day, and that has become a cornerstone of our societies. This openness thrives on open standards, shared protocols, and interoperability. Age checks risk fragmenting the web in more ways than one: Incompatible requirements will create a patchwork of age-gated communities, and age gates in the hands of a few will push people further into closed ecosystems, undermining the wider digital competition and the decentralization that gives the internet its strength.
To avoid the hollowing out of fundamental rights online, and the undermining of the open internet, international collaboration and free and open standards are urgently needed to govern age assurance across borders.
***
We believe the principles set out above can help mitigate the large-scale erosion of privacy, security, and agency that the first wave of age assurance laws and social media bans has introduced.
But improved legislative mandates and technical fixes alone are not enough to improve young people’s online experiences in a rights-respecting way. Enabling young people to develop positive relationships with digital technologies is foremost a societal issue, not a technical one. Changing norms around how we engage with technology, what we ask of companies seeking our attention, and how we have conversations about what safety means beyond abstinence and control will require a whole-of-society approach to digital well-being.
We believe that there is an ongoing campaign targeting rust-lang members and
owners of popular crates that is attempting to compromise devices and accounts
in order to use them to publish malware.
What we've seen
A video call is set up for something positive — maybe for a job, maybe for a
project, maybe for a contract opportunity — and then that's used as a vector to
either get the target to install something on their computer (such as a
purportedly missing audio codec) or execute another command (for example, via
putting a command on the clipboard).
These attackers are setting up new but legitimate seeming company profiles,
including plausible LinkedIn presences, in order to pass cursory inspection.
Please take extra care in the near term. Be appropriately suspicious of cold
outreaches, and ensure that any calls you have with new people are on platforms
you trust — ideally, try to be the one who sets up the call on a platform you
already use.
Please also re-check that your accounts look normal: MFA enabled,
no unexpected logins on platforms that can track that, and so on.
If you have any concerns about your accounts, please reach out to
help@crates.io (for crates.io account concerns) and/or
security@rust-lang.org (for any other
concerns). We're very happy to help.
Bug 2069143 - When retrieving comments for a bug(s) via REST API, remove comments that would be collapsed in the web UI unless explicitly asking for them
Bug 2070247 - Support limiting who can needinfo the Hackbot account
Bug 2061445 - Migrate Bugzilla (system info) REST resource to native Mojo API
Bug 1877201 - Post to bug/{bugid}/comment returns wrong comment_id
Bug 2072224 - Update REST API authentication documentation to reflect per-resource migration to native Mojo auth
Bug 2060932 - Support GitHub-style <details>/<summary> collapsible sections in comments
Bug 2072689 - Buglist link on My Dashboard is broken
The AI race is shifting. Again. Practically overnight, competition has expanded from “which AI model is best?” to a new high-stakes battle over which models people can access, through which products, and whether people have meaningful choice about AI at all.
In response, Mozilla and Mistral today announced a partnership built on a shared idea: a new, open-source AI model alternative to Big Tech-default browser ecosystems. The intent: a model deliberately designed to keep the web open to technological diversity, competition, and choice.
And we’re putting this idea into practice in Firefox.
Mistral Small 4 is coming to Firefox Smart Window beta (learn more about Firefox Smart Window here), becoming a new AI model for Smart Window users in the US and Canada, while expanding Smart Window beta access and French-language support to Firefox users in France. Across all markets where Smart Window beta is available, Firefox users can still choose from a multitude of other AI models.
“AI is becoming part of how people experience the web every day. We want to make sure that doesn’t mean people are chained to one company’s self-serving pipeline. With the browser sitting at the heart of the web and online experience, it should be a place where different AI providers can compete and open source has a seat at the table.
This isn’t just a product partnership. A browser shouldn’t be a one-way funnel. It should preserve what made the internet powerful to begin with: the freedom to explore, discover different ideas and tech, and decide for ourselves where to go next,” said Anthony Enzor-DeMeo, CEO of Mozilla Corporation.
Choice and competition are worth protecting
As AI integration becomes increasingly concentrated, we are in jeopardy of a handful of closed-model companies controlling the browser, the search engine, the AI model, and the surrounding services that connect them. Mozilla and Mistral are betting that independent and interoperable models can offer an alternative to global tech monopolies controlling the next digital era.
“This partnership represents two open source advocates working together to bring Mistral’s scientific innovations to Mozilla’s consumers around the world. Together, we are bringing privacy, control, and choice to AI-powered web browsing,” said Arthur Mensch, Co-founder and CEO of Mistral.
Meaningful choice isn’t confined to personal preference for one AI model over another. Web products need to be able to work with different AI providers, and people deserve the option of switching without being locked into a single company’s ecosystem. When a tech layer as far-reaching and influential as AI is controlled by a small handful of players, it risks creating closed systems and closed doors, making it harder for new ideas and better technologies to grow, reach users, and compete on merits.
Mozilla and Mistral aim to keep that door open. The combination of an independent browser with a frontier European AI company gives people and institutions greater access to useful, responsible AI, the opposite of locking them into one company’s singular technology ecosystem.
Selecting Mistral, and expanding to France
Mozilla selected Mistral Small 4 after evaluating its performance for Smart Window Beta, including multilingual performance, an important part of the fit. The companies approached multilingual and multicultural tuning as a core model feature, rather than simply adapting an English-first experience for a new market.
For Firefox users, Mistral access starts with Smart Window Beta, a browsing experience designed to turn AI into a useful assistant for the things we do online: making sense of complex search trails, finding something valuable you clicked away from, presenting data sources, and generally picking up where day-to-day internet use got left off.
France is the first new market for Smart Window with official French-language support. Mozilla is planning additional European expansion later this year.
A different kind of AI competition
Our Mistral partnership puts an ambitious new AI model approach into practice: a multilingual, globally competitive European AI company reaching people through an independent browser, leveraging openness to create more room for new technologies to compete and succeed. Mistral can reach Firefox users without owning the browser, and Mozilla can integrate and recommend Mistral without removing user choice.
It is a natural extension of the principles that have shaped Firefox and the open web, and the kind of AI ecosystem we intend to continue building.
EDIT: Updated to reference gh correctly. Thanks flod!
Sometimes on Github, I need to fetch a patch from a fork I don't typically see everyday so I can try it out locally. I use the line at the top of the patch which has a copy button next to it because it's convenient.
The common steps for this are:
Click the contributor's branch and go to their github fork repository.
Copy the repository link.
Add a new git remote with an alias (typically their username).
git fetch <alias>
git checkout <alias>/<branch>
Here is a one-liner for it that you can add to your gitconfig:
You might ask, why do all of this when the github gh CLI does this for you?
While it does simplify some tasks, I wanted a solution that was independant to a specific git host. The git@github.com remote that is used in the alias can be changed or made configurable if desired. This is something that I wouldn't be able to do with platform-dependant gh.
The fetch also works well with jj too because the fetch and checkout remain headless.
Formatted and commented, it looks less intimidating:
f() { # Get the repository name from your checkout (assuming it is the # original directory name as the remote). PNAME=$(basename `git rev-parse --show-toplevel`); # Parse out the fork's owner. # Example: `<owner>:<branch>` OWNER=$(echo $1 | cut -d':' -f1); # Parse out the branch name. # Example: `<owner>:<branch>` BRANCH=$(echo $1 | cut -d':' -f2); # Do a fetch of that particular branch using the extracted # information from above. # This assumes the remote is hosted on github. git fetch git@github.com:$OWNER/$PNAME.git $BRANCH; # Checkout using the alias `FETCH_HEAD` which git provides. git checkout FETCH_HEAD;};# Execute the function!# It's easier to build a function that holds variables and execute# rather than in-line it.f
Comments
With an account on the Fediverse or Mastodon, you can respond to this post. Since Mastodon is decentralized, you can use your existing account hosted by another Mastodon server or compatible platform if you don't have an account on this one. Known non-private replies are displayed below.
Learn how this was implemented from the original source here.
<noscript><p>Loading comments relies on JavaScript. Try enabling JavaScript and reloading, or visit <a href="https://mindly.social/@jonalmeida/117279142568496801">the original post</a> on Mastodon.</p></noscript>
<noscript>You need JavaScript to view the comments.</noscript>
Hello and welcome to another issue of This Week in Rust!
Rust is a programming language empowering everyone to build reliable and efficient software.
This is a weekly summary of its progress and community.
Want something mentioned? Tag us at
@thisweekinrust.bsky.social on Bluesky or
@ThisWeekinRust on mastodon.social, or
send us a pull request.
Want to get involved? We love contributions.
An important step for RFC implementation is for people to experiment with the
implementation and give feedback, especially before stabilization.
If you are a feature implementer and would like your RFC to appear in this list, add a
call-for-testing label to your RFC along with a comment providing testing instructions and/or
guidance on which aspect(s) of the feature need testing.
Always wanted to contribute to open-source projects but did not know where to start?
Every week we highlight some tasks from the Rust community for you to pick and get started!
Some of these tasks may also have mentors available, visit the task page for more information.
No Calls for participation were submitted this week.
If you are a Rust project owner and are looking for contributors, please submit tasks here or through a PR to TWiR or by reaching out on Bluesky or Mastodon!
Are you a new or experienced speaker looking for a place to share something cool? This section highlights events that are being planned and are accepting submissions to join their event as a speaker.
No Calls for papers or presentations were submitted this week.
If you are an event organizer hoping to expand the reach of your event, please submit a link to the website through a PR to TWiR or by reaching out on Bluesky or Mastodon!
There were almost no regressions this week, and several performance improvements! Though some of them
were reverts of regressions from a previous week. #162422 improved the performance of Polonius, whose
performance is getting closer to the previous NLL borrow checker.
If you are running a Rust event please add it to the calendar to get
it mentioned here. Please remember to add a link to the event too.
Email the Rust Community Team for access.
Last September, the Servo project announced that long-time maintainer Josh Bowman-Matthews (@jdm) would work part-time on improving the Servo contributor experience, entirely funded by the monthly donations on OpenCollective and GitHub.
In his own words, here is a look back over the past year!
First of all, I am enormously grateful to everyone who financially supports Servo, as those donations have enabled me to devote significant time to a project that I care a lot about.
Some highlights from that funded work that I’m proud of:
On top of that, I spent time diagnosing unexpected failures in others’ PRs and fixed numerous intermittent test failures that made merging PRs more difficult for everyone.
A few pieces of work from this period that stand out to me:
supporting a large scale rewrite of Servo’s JS engine integration to address intermittent panics related to garbage collection—I reviewed lots of pull requests, but also filed many issues that enabled the work addressing the panics to be spread across many other contributors
supporting another contributor’s grant proposal to work on Servo that was approved!
This role I’ve carved out means a lot to me—I’ve found a healthy balance that allows me to spend time with my family as well as make meaningful contributions to Servo, and I get to spend a lot of time looking for ways to make the project more accessible for others.
A big thank you to everybody supporting the project and my work; each individual monthly donation makes a big difference!
I’m excited to see what’s possible in the coming year.
As part of the Nova redesign, a “Use Linux system theme” checkbox is being shown on Linux builds for the about:addons theme picker, which will make Firefox’s Nova UI use the colours of the system theme.
Replaced the “more themes” button in the themes list view footer with a promo element when Nova is enabled – Bug 2057200
Removed the testing XPI base url pref from ThemesList.sys.mjs – Bug 2053220
Fixed a mismatch between the popup panel border radius applied by Nova and the border radius applied to the document.body of the WebExtensions popup page loaded into it – Bug 2057844
Moved new strings added as part of the about:addons Nova restyling out of the locales preview – Bug 2052034
As part of legacy telemetry cleanups for the Add-ons related telemetry, migrated addons-search-detection telemetry off the legacy telemetry mirroring path, now collected only through Glean – Bug 2055606
Thanks to Florian Quèze for applying his work on an LLM-based system for investigating intermittent tests to investigating and fixing intermittents and perma failures across the WebExtensions test suite.
DevTools
Ruhollah Majdoddin fixed issues in the Storage panel to make sure we’re only showing relevant cookies (and their values) for the debugged tab (#1856645, #2060029, #2061166) and also did some cleanup in this area (#2061348)
sevenwithawp added a keyboard shortcut (Ctrl+Alt+B, Cmd+Alt+B on Mac) to disable/enable breakpoints (#1642578)
Did a trainhop last week to help with the remote layouts effort
Doing another trainhop this week to make some spacing optimizations, deploying tomorrow if all goes well
We will be experimenting with some more layout variations over the next few months
Example:
We’ve migrated a bunch of ourunittests to Jest/RTL from the deprecated Mocha / Karma framework we’ve historically used.
Joel added a WebNotifications badge to Top Sites on the New Tab Page which surfaces per-origin unread web-notification state directly on TopSites tiles by rendering a compact badge in the activity-stream/TopSites component—users can now glance at NTP tiles to see which sites have pending web notifications without changing navigation or site state (affects desktop and mobile NTP Top Sites UI). This is something we plan on experimenting with later this year.
Similarly, Joel added a TopSites hover card with notifications which expands the to show per-site notification items and actions on hover or long-press, enabling users to read and dismiss notifications from the NTP itself rather than opening each site.
Dre fixed the “Show more widgets” visibility by adjusting the widget container overflow/visibility logic so the Show more control is reliably revealed on constrained viewports, restoring widget discoverability.
Joel fixed newtab.closed and newtab.sections_impression firing unexpectedly on the New Tab Page by gating event emission on section visibility and tab lifecycle, which stops spurious impression and close telemetry pings and improves the accuracy of NTP impression/close counts for affected users.
Joel added a topsite display customization event to newtab ping, updating the New Tab ping schema so user topsite layout and appearance changes are emitted as topsite.display_customization events, enabling reliable capture of pin/remove/resize/customization actions in Telemetry.
Nina Pypchenko [:nina-py] added widgets.stocks.interaction and flip it on user actions so explicit click/tap interactions with the Stocks widget now generate widgets.stocks.interaction events, improving engagement capture for the Stocks surface.
Scott Downe added support for five-column content feed layouts, which enables denser content grids for large displays by updating grid logic and responsive breakpoints and affects NTP rendering on wide screens.
Irene Ni updated the New Tab topsite context menu button to respect prefers-reduced-motion via CSS/media-query changes, so users with reduce-motion enabled no longer see the button’s motion/animation.
Dre reduced the Privacy Widget celebration sparkles on the New Tab Page in Privacy Widget Celebration: Reduce the Sparkles by lowering particle counts and throttling animation cadence in the widget’s CSS/JS animation code, reducing visual noise and a small amount of GPU/animation work for users during the celebration without changing privacy settings.
Nova: continued work on the Nova redesign, focusing on CSS fixes, tab group and container styling, and tab/address bar polish. Efforts are underway to ensure the UI integrates correctly with platform themes and high-contrast modes.
IPC Urlbar / Multi-Context Address Bar (MCAB) on New Tab: Significant progress has been made on the IPC Urlbar implementation. The CI variant is now live and upgraded to Tier 2, allowing for better bug detection. Currently focused on making content modules content-process-safe and preparing for new tab search bar integration. Here’s moz-urlbar rendering something on about:newtab for the first time:
Search & Suggest Telemetry: Development is ongoing for search term telemetry, specifically regarding fetching results from Merino for online suggestions. Also preparing to retire legacy telemetry for certain search service metrics.
We try to be responsible with data. For example, we:
- store as little sensitive data as possible
- monitor changes in incoming data on which we've built models
But what happens when those two approaches conflict?
How do we monitor changes in incoming data that we don't want to store?
This talk explains the schema we use to monitor changes in what people are searching for in Firefox...even when we deliberately don't store some of what people are searching for.
This is the opposite of what I wanted to write about: relocating your MOZ_OBJDIR outside of your source directory will make your IDE faster.
In mozilla-central (the firefox monorepo), a default object files directory is created within the same source directory. This is equivalent to the build/ directory you would typically see in other projects.
While this is typically fine, I've found that Android Studio indexes many of these files and that can be slow when you're not working across all the layers in Gecko and Firefox. I ended up with these build directories that grew over time:
Directory
Last touched
Size
Files
obj-aarch64-unknown-linux-android
2025-11-04
29 G
113,116
objdir-desktop
2025-11-04
19 G
41,010
objdir-frontend
2026-09-09
6.3 G
66,930
obj-aarch64-apple-darwin24.5.0
2025-06-16
4 K
1
That's a lot to index! I figured a way around this problem is to move the OBJDIRs out of the source directory and into something like ~/.mozbuild:
While this does speed up IDE indexing, it's at the cost of developer experience, because now our generated code (e.g. FxNimbus) shows up as red symbols everywhere.
[insert sad trombone sound clip]
I'm uncertain if trimming what we index in these OBJDIRs is worth a large enough performance win, so for now I'll ensure I clean-up my stale copies which I'm not actively using.
P.S. Apologies for the delay in publishing this edition on the community blog. The original newsletter was sent to subscribers on August 27.
Firefox was leveling up in August! GeForce NOW arrived on Firefox for Windows, JPEG XL support was on the way, and the Firefox + NVIDIA teams joined forces for a Reddit AMA. We also invited SUMO and Mozilla Connect contributors to share their experiences through the Mozilla Contributor Survey, which has since closed (thank you to everyone who took the time to participate!).
Read on to catch up on what you may have missed and see what the community was up to!
GeForce NOW is now available on Firefox for Windows
Firefox has joined NVIDIA GeForce NOW’s supported browser lineup, making it possible to stream more than 2,000 PC games directly from Firefox on Windows. There are no downloads, installs, or hardware upgrades required! Just a Windows PC, a GeForce NOW account, and your existing game library.
Share your voice in the Mozilla Contributor Survey 2026
We’re gathering feedback from SUMO and Mozilla Connect contributors to help shape the future of Mozilla’s contributor community. The 2026 Contributor Survey explores what motivates you to contribute, what matters most throughout your contributor journey, and how we can improve areas such as onboarding, recognition, and the upcoming Mozilla Connect migration to SUMO. The survey takes about 10 minutes to complete and is now open until September 1, 2026, end of day UTC.
Firefox plans to ship support for JPEG XL, a modern image format designed to deliver high-quality images more efficiently. With progressive rendering, images can start appearing before they have fully downloaded so it helps make pages feel faster, especially on slower connections.
The Firefox and NVIDIA GeForce NOW teams are hosting a Reddit AMA on September 2 to celebrate GeForce NOW support on Firefox for Windows. Bring your questions about the integration, share your cloud-gaming setup, and let the teams know what else you’d love Firefox to support for online play.
Firefox Telemetry Engineer and Data Steward Chris H-C (:chutten) gives a talk at Ubisoft's Data Summit 2021 about how Responsible Data Collection as practised at Mozilla makes cataloguing easy, stops instrumentation mistakes before they ship, and allows you to build self-serve analysis tooling that gets everyone invested in data quality. Oh, and it's cheaper, too.
The 2021 SciPy conference (https://www.scipy2021.scipy.org/) involved the showcasing of the latest open source Python projects for advancement in scientific computing. Mozilla was a diversity sponsor and a few Mozillians attended and shared their experience of the event.
This talk was given as part of the Data Club Lightning Talk Session on February 11th, 2022.
More on https://blog.mozilla.org/data/2022/02/25/this-week-in-glean-your-personal-glean-data-pipeline
Information about Glean: https://mozilla.github.io/glean/book/index.html
Will Lachance does a retrospective on the Glean Dictionary outreachy internship.
See also "Linh's Outreachy Internship Highlights" https://www.youtube.com/watch?v=UJdIkHDPgGQ
To learn more about Outreachy, see https://www.outreachy.org/
Our goal for this phase of work is to remove the technical jargon, use plain language, and make it effortless for everyone to make informed decisions about their settings. With over 250 blocks of settings content to untangle, we aimed for incremental improvements rather than striving for perfection.
While our previous research leaned heavily on our technical power users, this round intentionally focused on new users to make sure Thunderbird is intuitive from day one.
Summary of research
The new copy tested well: We achieved >80% comprehension across our tested copy for Notifications, Appearance, and Composition settings.
High confidence levels: Users felt confident to change settings without external help (asking someone, referencing docs, or using AI for support).
Interactions need refinement: We found spots where the interface didn’t always match expectations, like using a checkbox instead of an on/off toggle.
Using our content guidelines, we audited all 250+ content blocks to check accuracy, what was overly technical, and if anything was outdated. Our strategy was built up into steps to make it more achievable.
Step 1: Research & prioritization
User journey mapping, insights from research and user needs
Last month, we conducted research where we used a card sorting method to understand what users actually care about most and where they expect settings to live. Catch up on the Research Summary.
Step 2: Inventory audit
Content inventory with Thunderbird on the left and the content table on the right.
We mapped every piece of text in the app to build a full content inventory, assessing each piece of text for accuracy, freshness, and 8th-grade readability.
Step 3: Content redesign
Example of how we updated the notifications content
We removed any developer or system updates from the interface and replaced it with language that speaks to what the setting actually does for the user.
Our findings
We tested prototypes for Notifications, Appearance, and Composition and asked 4 questions to test the purpose of each setting category, scenario comprehension, and user confidence. Our target threshold was 80% comprehension.
Lyssna prototype displaying Appearance settings and question
Here is how the new copy tested with room for improvement around the interactions, visuals, and how the language can be even more clear and user friendly.
Settings Category
Purpose Comprehension
Scenario Accuracy
Confidence Score (out of 5)
Notifications
86%
71%
4.00
Appearance
86%
86%
4.14
Composition
100%
100%
4.43
What’s next
Improve the interactions: Aligning component types with immediate vs. batch actions so the UI behaves the way people expect.
Sharper indicators: Testers liked the visual diagrams for Threaded, Unthreaded, and Grouped messages, but they need a bit more detail to make the visual distinction instant.
Continue iterating on copy: Cleaning up remaining awkward phrasing (like Autosave 5 seconds) that still makes the experience feel slightly dated.
Next, we are taking everything we learned from this copy testing and applying it to the overall settings navigation and layout structure.
Redesigning settings isn’t always glamorous, which is why our team internally nicknamed this effort “Project Toto” inspired by high-tech Japanese toilets. Settings are something most people prefer not to think about, but when they are designed thoughtfully, the experience becomes seamless, intuitive, and surprisingly delightful.
As our new designs take shape, we’ll be reaching back out to both new and long-time users for feedback. Stay tuned for our next update, and let us know your thoughts in the comments!
Hello and welcome to another issue of This Week in Rust!
Rust is a programming language empowering everyone to build reliable and efficient software.
This is a weekly summary of its progress and community.
Want something mentioned? Tag us at
@thisweekinrust.bsky.social on Bluesky or
@ThisWeekinRust on mastodon.social, or
send us a pull request.
Want to get involved? We love contributions.
An important step for RFC implementation is for people to experiment with the
implementation and give feedback, especially before stabilization.
If you are a feature implementer and would like your RFC to appear in this list, add a
call-for-testing label to your RFC along with a comment providing testing instructions and/or guidance on which aspect(s) of the feature need testing.
If you are a feature implementer and would like your RFC to appear on the above list, add the new call-for-testing
label to your RFC along with a comment providing testing instructions and/or guidance on which aspect(s) of the feature
need testing.
Always wanted to contribute to open-source projects but did not know where to start?
Every week we highlight some tasks from the Rust community for you to pick and get started!
Some of these tasks may also have mentors available, visit the task page for more information.
If you are a Rust project owner and are looking for contributors, please submit tasks here or through a PR to TWiR or by reaching out on Bluesky or Mastodon!
Are you a new or experienced speaker looking for a place to share something cool? This section highlights events that are being planned and are accepting submissions to join their event as a speaker.
No Calls for papers or presentations were submitted this week.
If you are an event organizer hoping to expand the reach of your event, please submit a link to the website through a PR to TWiR or by reaching out on Bluesky or Mastodon!
This week we've hit quite a few regressions, both expected and unexpected.
One of them has already been fixed, with fixes for a few others being discussed.
One big improvement comes from caching the sanitizer set in Session, which fixes a large regression from last week.
A few minor improvements landed, including a 75% reduction in memory usage while compiling bevy_render with the next trait solver.
An important step for RFC implementation is for people to experiment with the
implementation and give feedback, especially before stabilization.
If you are a feature implementer and would like your RFC to appear in this list, add a
call-for-testing label to your RFC along with a comment providing testing instructions and/or guidance on which aspect(s) of the feature need testing.
No Items entered Final Comment Period this week for
Rust RFCs,
Compiler Team,
Language Team or
Leadership Council.
Let us know if you would like your PRs, Tracking Issues or RFCs to be tracked as a part of this list.
If you are running a Rust event please add it to the calendar to get
it mentioned here. Please remember to add a link to the event too.
Email the Rust Community Team for access.
Introduced a shared localization module for built-in and curated AMO-hosted theme names, and updated the corresponding about:addons theme test to expect the new “Default” theme name shown when Nova is enabled – Bug 2055936 / Bug 2058235
Added a message bar to the about:addons themes picker to surface AMO-hosted Nova theme download and install failures instead of failing silently – Bug 2054548
WebExtensions Framework
Fixed a startup race where an extension’s restored dynamic content scripts could be missing from the parent WebExtensionPolicy due to stale shared data – Bug 2058719
WebExtension APIs
Fixed publicSuffix.isKnownSuffix() to reject invalid domain-name characters, including wildcard suffixes, that could previously be matched as a known public suffix – Bug 2059819
Fixed the frameId reported by webRequest events for requests made from workers, including importScripts()-loaded scripts, which were previously attributed to the wrong frame – Bug 2048884
Thanks to Giulio B for the fix to webRequest frameId attribution for worker requests.
Standard8 adjusted the source docupload task, that runs on code review, to report failures into phabricator, rather than having a generic error message.
Irene Ni standardized New Tab widgets and sections header spacing (standardize spacing) to remove misaligned tiles and reduce visual jitter when resizing or toggling sections in the New Tab Page.
Mike Conley removed version-153 train-hop compatibility shims for the World Cup newtab logo variations (remove compatibility shims), an internal cleanup that prevents legacy logo-selection fallbacks from influencing current logo variations.
Maxx Crawford exposed available browser themes to New Tab and added apply/install actions (expose and apply themes), allowing users to install or immediately apply themes from the New Tab surface via ThemeManager/Theme API hooks.
Maxx Crawford added New Tab Customize Panel browser theme selection strings (add theme selection strings) so the new theme-selection UI is localized and displays correct labels across locales.
Maxx Crawford added a full browser theme selection sub-panel to the New Tab Customize Panel (theme selection sub-panel) to let users browse, preview, and pick themes directly inside the New Tab customization flow.
Scott Downe fixed Custom newtab wallpapers flash / blink some seconds after loading newtab by ensuring the custom wallpaper is painted only after image data is ready, which removes the multi-second visual flash on about:newtab for users with custom backgrounds and improves perceived stability during initial new-tab load.
Maxx Crawford exposed trainhopConfig values in Discovery Stream Admin tooling, giving operators direct access to trainhop routing/weight values from the admin UI/API so content trains and experiment routing can be adjusted without code deploys—this has no immediate end-user UI change but reduces time-to-rollout for Discovery Stream content changes.
Dre fixed Newtab custom wallpapers flash when selecting from picture of the day widget by deferring the wallpaper swap until the selected Picture of the Day is decoded and ready, which prevents the transient blank/flash users saw when changing wallpapers via the widget and makes wallpaper selection feel instantaneous and stable.
One of the biggest challenges Rust developers report in our
annual surveys is a subpar debugging experience. So, back
in February, we ran our first Rust Debugging Survey,
in the hopes of identifying how Rust developers are using debuggers and what
problems they are facing when doing so. We received over 2,300 responses, and
we'd like to thank everyone who took the time to participate in the survey!
In this report, we'll go over some of the results of the survey. If you'd like,
you can also check out the complete results of the survey.
If you'd like to skip ahead to any particular section, you can do so with this
index:
The first step to making sense of the survey results is understanding who took
the survey. We asked respondents to rate their Rust expertise, from "Never used
it" to "Advanced". Over 80% reported themselves as "Advanced" or "Intermediate",
split roughly evenly between the two:
We also asked respondents if they currently use or have used debuggers in Rust.
Over 46% said they currently do, with the remaining responses split between
"have in the past" and "never have". That means that over half of respondents do
not currently use a debugger for Rust!
Categorized by expertise, the responses reveal that roughly half of "beginners"
have never used debuggers in Rust! On the other hand, nearly half of "advanced
users" currently do use debuggers in Rust:
For respondents who indicated they had previously used Rust but no longer did,
we asked if challenges with debugging support were why they stopped. For nearly
3%, the answer was "yes", with an additional 24% reporting debugging issues as
being partially responsible (though mind the small response count; most
respondents were active users of Rust):
Knowing what debuggers developers are using and how is another important part of
understanding the challenges they face. To this end, we asked respondents how
they were debugging their programs. Unsurprisingly, most developers make use of
print debugging and the dbg! macro. Excluding those, using lldb inside an
IDE was the most popular choice, followed by gdb on the command line:
We can get a more detailed breakdown of these results if we include the
operating system on which the respondents use a given debugging approach. We
examine this from two different angles. The first angle being, "On operating
system X, what percent of responses are using debugger Y?". Print debugging and
the dbg! macro are consistently the top two yet again, but looking beyond
that, things get more interesting. On Linux, using gdb on the command line was
the most popular choice by a thin margin, beating lldb in an IDE by only 0.4%.
On Windows, Windows Subsystem for Linux (WSL), and macOS, lldb in an IDE was
the top pick by at least 6%, making it a very popular choice in general. On
Windows, the three least popular choices were the command line debuggers (gdb
CLI, lldb CLI, and BugStalker), and on both Windows and macOS the third most
popular pick was, "I don't know". Those who were debugging on operating systems
not listed (Other) most frequently used some kind of special embedded debugger
or gdb:
The other angle we can look at these responses from is, "For users of debugger
X, what percent of responses are using it on operating system Y?". For most
debuggers, Linux makes up the largest portion of uses, ranging from about 45% to
about 77%, followed by Windows, then macOS. The most notable exceptions are
WinDbg and the Visual Studio debugger, which are primarily used on Windows, and
lldb, which is used more on macOS than Windows in an IDE and on the command
line:
To the 6 respondents who use WinDbg on Linux: we wish you luck!
As for how people actually use their debugger of choice, the aggregate results
are not particularly surprising. Roughly 87% of users are using debuggers for
stepping line-by-line through programs and a little over half of users are using
debuggers to obtain stack traces from hung/crashed processes. Only a quarter of
the respondents use a debugger to debug async code. That might be partially
caused by the async Rust debugging experience being clumsy and incomplete, or it
could just be that users aren't writing much async code:
If we break these results down by expertise, we can learn a bit more about usage
patterns. As users become more experienced with Rust, their use of debuggers for
learning purposes decreases, and they get more stack traces from crashed
processes:
The final bit of insight into how Rustaceans use debuggers is if they are
debugging programs that use Rust alongside other programming languages. For 44%
of respondents, the answer is "yes", which is a pretty high number!
As for which languages those are, C dominates the scene at a little over 70%,
followed by C++ at about 43% and Python at about 20%:
Instead of diving right into asking, "what problems do you face when using
debuggers?", or something to that effect, we first asked respondents why they
decide against using debuggers whenever they do, including for reasons that
aren't necessarily "problems with debuggers".
The most commonly reported reason was that it was easier or faster to use logs
or print debugging to solve problems, reported by a little over 81% of
respondents. This could partially be explained by the open responses, which
featured complaints that debuggers were too difficult to set up and/or use
(especially on Windows, when dealing with Web Assembly, or in embedded
contexts) and sentiment suggesting that small and/or simple problems just don't
really need a debugger. It does leave one wondering if the user experience could
be made convenient enough to dethrone print debugging, but it seems hard to beat
something so intuitive. This is followed by roughly 37% of respondents who write
code that Just Works. Fair enough. After that, about 26% of respondents
indicated that they've decided not to use debuggers in situations where the
language features they were working with had poor support. This is slightly more
than issues with standard library types, at about 22%, which is slightly more
than issues with external library types, at about 20%:
As stepping through code was anticipated to be one of the most common uses for
debuggers, we directly asked respondents if they faced any issues when doing so.
A little over 51% of respondents said they did! Of those who reported that they
experienced issues stepping through code, we asked when they were experiencing
issues. Async code was the most common case reported at slightly over 28%,
followed by code involving macros at about 23%. The least common case reported
was code involving function pointers, at almost 6%:
We also directly asked respondents which types in the standard library were hard
to work with, if any. This was an open-response question, and reading through
the responses, some particularly common complaints were with enums and
collections, particularly std::collections::HashMap and std::vec::Vec. This
is also visible in the word cloud in the full report.
We asked respondents to indicate which pain points, if any, they have
encountered when using debuggers with Rust. At slightly over 74%, poor
representation of values was the most common pain point by a decent margin,
followed by being unable to print variables at just over 55%:
We asked respondents to indicate if they were library authors, and if so, if
they were aware of and using the debugger_visualizer attribute. Nearly 62% of
respondents indicated that they were library authors who were not aware of this
attribute:
For those who indicated that they were library authors who knew about the
attribute but did not use it, we also asked why. This represented a much smaller
fraction of respondents, so keep that in mind! That said, half of these library
authors indicated that they didn't have the time to maintain visualizer
attributes, and just under half indicated they didn't know how to write
visualizer scripts:
For those of you who have been reading this section asking yourself what the
debugger_visualizer attribute is, you can read up on it in
The Rust Reference: Debugger Attributes. The quick
explanation is that the debugger_visualizer attribute can be applied to
modules or the crate root to embed files in the debug information which improve
the display of values with certain debuggers. The two currently supported file
types are Natvis files, used by Microsoft debuggers such as WinDbg, and GDB
"pretty printers", which are structured Python scripts used by GDB.
Closing Remarks
Thanks to your participation in this survey, we've gained some great insights
about how Rustaceans are using debuggers and what issues they are facing. For
example, knowing that such a high number of users are dealing with poor
representation of values pairs well with knowing which standard library types
are causing issues, knowing that many library authors haven't heard of the
debugger_visualizer attribute, and knowing that many of those who have but
don't use it either don't know how or don't have time to maintain visualizer
scripts.
Looking to the future, the survey results have suggested that there are a few
notable ways we could most significantly improve the debugging experience in
Rust, such as:
Fixing the way enums are represented by debuggers so they show actual
variants
Fixing the way collections (such as HashMap) are represented by debuggers so
they show their contents, rather than their implementation details
Fixing the way string types (such as String and CString) are represented
by debuggers so they render as text, rather than their implementation details
Improving the async debugging experience, particularly with stack traces
Improving stepping through certain state machines (such as iterators and
Futures)
Providing documentation on basic set up and use of some common debuggers
A common suggestion that could resolve those first three points is to use the
Debug implementation of types to display them in debuggers. There are
challenges to that approach, such as the fact that the Debug implementation is
not present in the final binary unless it is actually used somewhere in the
program, but it isn't impossible. Notably, this is already supported by the
BugStalker debugger (given the same condition that the Debug
implementation must actually be used), which some of you first heard about from
the survey! It also appears to have some support for async, with plans to
expand.
One notable way the debugger experience is currently being improved is through
the ongoing Google Summer of Code project improving how we test debug info and
visualizer scripts, making it easier to maintain and improve our own visualizer
scripts and general compatibility with visualizer scripts without silent
breakage or regressions.
Once again, we'd like to thank everyone who took the time to participate in the
survey!
Firefox DevTools MCP (firefox-devtools-mcp) 0.10.2 is out on npm.
New tools:
press_key — sends a single key, optionally with modifiers, to a snapshot element or the focused element (Return, Escape, Tab, arrows, ctrl+shift+t, …).
type_text — types text key by key into the focused element, with an optional key to press afterwards.
set_network_cache — bypass or restore the HTTP cache, for the selected tab or browser-wide. Useful before a performance measurement or when verifying a change a cached asset would otherwise hide.
Other changes:
navigate_page and new_page take an optional wait argument (none, interactive, complete), so an agent can wait for the load event before deciding a page is done.
Windows: per-user Firefox installs are now detected, instead of failing with “unable to find binary in default location”.
aarch64 Linux: geckodriver is now resolved on all platforms, fixing “Unable to obtain browser driver” when a native geckodriver is on PATH.
Several Windows path fixes for --output-file, --log-file and saveTo.
For internal Firefox development, swap firefox-devtools-mcp with firefox-devtools-mcp-moz in order to benefit from additional tools, such as chrome-privileged script execution.
We heard you. You don’t want to open your PerfCompare performance comparison and feel like you need a background in statistics to interpret the Mann-Whitney-U results. Cliff’s Delta, CLES, and normality tests, oh my! It should not feel like you’ve blindly walked into a college stats exam, unless of course, you love statistics. For the rest, all you want is an easy answer to the question: Did my changes make things faster or slower?
So we fixed that. PerfCompare now shows the bare essentials by default and tucks the heavy statistics one click away.
An approachable default for beginners and occasional users
The results table now leads with the platform, the Base and New values, how far the median moved and its direction, the status (which includes the option to filter out noise) and the size of the change. To create a more advanced view, a single “Advanced options” dropdown allows you to add the expert columns (Cliff’s Delta, CLES, Significance) and the info-rich expanded row details below the full-width graph. A small help section at the top of the results provides a quick explanation of the columns. The purpose is to serve a diverse audience while preserving your selections in the URL so a shared link reproduces your view.
The “Advanced options” dropdown lets you add the precise statistics columns:
Cliff’s Delta: An effect-size measure of how far the Base and New distributions have pulled apart
CLES (Common Language Effect Size): The chance a random New run beats a random Base run, e.g. “New wins 78% of the time”
Significance: Whether the difference is a real signal or just noise
Each one toggles on independently, so you can surface only Significance or the whole trio.
Expand a result and you get a clean panel: a full-width graph of how your Base and New runs are spread out, a quick summary (platform, app, which direction is “better”), and a little “how to read this graph” tool-tip for anyone who hasn’t stared at a distribution curve before. You can still poke at the graph’s mode controls if you want to dig in.
You can access the extra expanded row details such as effect size and confidence intervals or the full stats table in the “Advanced options” dropdown. Turn on what you need, and the expanded extras lay out in neat two-column rows. If you turn on mode analysis and there aren’t multiple modes to show, we now say “No mode analysis available” instead of a blank space.
Lastly, the advanced columns and expanded-row details you’ve switched on, along with your filters and sorting, are all encoded in the URL. Paste it to a coworker and they’ll land on the same result you were looking at; for filters and sorting, the shared link takes precedence over whatever they had saved locally. (One exception: the “How to read the results” panel is a personal per-browser preference, so it stays with you rather than tagging along on the link.)
What’s next
Several follow-ups on the way:
Remembering your advanced choices. Right now the advanced columns and expanded-row toggles start from the clean defaults each visit (they only persist in a link). Soon PerfCompare will remember them in your browser the same way we do for filters. However, if you open a shared link from a colleague, their specific view takes priority, overriding your own local settings so you both see the exact same data.
Carrying your selections into subtests. Today, the Advanced options you pick on the main results page don’t follow you when you open a test’s subtests. We’re wiring it up so whatever you’ve enabled up top is automatically enabled in the subtests dropdown too, for one consistent view.
Expanding the “How to read the results” cheat sheet to include Cliff’s Delta, CLES, and Significance definitions.
Share your feedback
We want PerfCompare to work for all users, whether you’re chasing your first regression, or you’re an expert who doesn’t want to lose their favorite metrics to a cleaner view. Our answer is separating the simple view from the power user view, and making the toggle obvious and shareable.
The great news is it’s live now! Go expand a Mann-Whitney-U result, click around the Advanced options, and tell us what you think. Please share your feedback, suggestions, or comments on the #perfcompare channel on Matrix. If you’ve encountered a bug or have a feature request, please file them in Bugzilla. We’re listening.
The Rust team has published a new point release of Rust, 1.98.1. Rust is a programming language that is empowering everyone to build reliable and efficient software.
If you have a previous version of Rust installed via rustup, getting Rust 1.98.1 is as easy as:
rustup update stable
If you don't have it already, you can get rustup from the appropriate page on our website.
In Rust 1.98.0, in some circumstances, rustc would incorrectly generate a trait object vtable with a null pointer
where a function pointer should be. This leads to undefined behavior in the
emitted code. In some cases this may 'just' cause segfaults due to the null
pointer being loaded, but it is possible for it to be justification for
arbitrary effects (as is typical for UB).
If you'd like to help us out by testing future releases, you might consider
using the beta (rustup default beta) and nightly (rustup default nightly) channels locally and in your CI. Please
report any bugs you
might come across!
Contributors to 1.98.1
Many people came together to create Rust 1.98.1. We couldn't have done it without all of you. Thanks!
As many of you know, Microsoft will be disabling Exchange Web Services (EWS) support on its Microsoft 365 platform later this year. The Thunderbird Desktop team has been hard at work to ensure continuity of functionality through this transition, and today we are pleased to announce the release of native Thunderbird support for the Microsoft Graph API! Curious what this means for you? Then keep reading to find out!
IMAP and EWS and Graph, Oh My!
When connecting to either on-premises or hosted Microsoft accounts, Thunderbird users now have an array of options. Users might not know which option is best for their case, so we’ll start with a little bit of guidance to help users decide what will be best for them. First off, if you are currently using IMAP with an on-premises Exchange account or a Microsoft 365 hosted account, and it’s currently working for you, then there’s nothing you need to do! EWS and Graph support are for users whose organizations do not allow IMAP access.
Now for the more complicated part. Last year, we released EWS email support for both on-premises Exchange accounts and Microsoft 365 hosted accounts. If you are using the EWS protocol with an on-premises Exchange account, then you don’t need to do anything.
However, if your organization uses Microsoft 365 for email, and you’re currently using EWS to connect to that account, then you need to take action before October of this year. Earlier this year, Microsoft announced that they would begin a phased shutdown of EWS on Microsoft 365/Exchange Online starting in October of 2026 with the goal of a complete shutdown in 2027. If you are currently using Thunderbird’s EWS support to connect to a Microsoft 365/Exchange Online email account, then you will need to switch to the Microsoft Graph API support to keep using Thunderbird beyond these dates. See below for details.
So the TL;DR is:
IMAP for on-premises or Microsoft 365 hosted email => No action required.
EWS for on-premises Exchange => No action required.
EWS for Microsoft 365/Exchange Online => Set up a new Microsoft Graph account in Thunderbird.
Microsoft only supports the Graph protocol on Microsoft 365, so that is the only provider that offers it. On-premises Exchange servers do not implement the Graph API, so Thunderbird’s EWS support will continue to be the primary mechanism for users on these servers to connect to their email accounts.
Microsoft Graph Account Set Up
Thunderbird does not support migrating accounts to different protocols. Instead, you will need to set up a new account. If you have an existing EWS-connected Microsoft 365 account, first you’ll need to delete that account in Thunderbird. You can do this from the account settings. Deleting the account locally in Thunderbird will not affect any data stored on Microsoft 365, so your data is safe.
Once your previous EWS account has been deleted, you can use Account Hub to set up a new account. In the new account set up dialog, enter your Microsoft 365 hosted email account. Thunderbird should automatically detect that your email is hosted on Microsoft 365 and will give you a few options for getting connected. Choose the Microsoft Graph option, and you should be good to go! If for some reason automatic configuration doesn’t work, you can still configure your account manually using these instructions.
What is currently supported?
As with EWS, Thunderbird’s current Graph support extends only to email. Thunderbird does not yet support Calendar and Address Book functionality with either EWS or Graph.
What’s in ESR?
Thunderbird’s current Extended Support Release, version 153, supports the EWS protocol, but does not support the Microsoft Graph API, which was first enabled in the Thunderbird Release channel in version 154. Users on the ESR channel who are using Microsoft 365 will need to migrate to the Release channel in order to use the Microsoft Graph API support to continue accessing Microsoft 365 hosted mailboxes.
What’s Next?
Calendar and Address Book! The Thunderbird Desktop team has already started working on support for connecting to Microsoft 365-hosted calendars using the Graph protocol. We will be busily working on this throughout the rest of the year. As with our previous work on Thunderbird support for EWS, this is the first new calendar protocol to be added to Thunderbird in many years. We are currently doing some up-front design work to ensure a sustainable product going forward and hopefully make the next calendar protocol easier to add.
How can users give us feedback?
As with all new functionality, there may be features we are missing or unexpected issues. As always, Bugzilla is always open! You can send us feature requests and issue reports using this Bugzilla link. Thunderbird’s greatest strength is its community of users, developers, and supporters who help us deliver the best tools we can to connect people with one another. We welcome community involvement to help us make everything better!
Nitty-Gritty development details
Those of you who have followed along with development throughout EWS and into Graph support might have noticed that, compared to EWS, we were able to implement support for the Microsoft Graph API relatively quickly. This is largely due to the up-front thought and work that went into the design and development of Thunderbird’s EWS support. The Graph implementation was the team’s first test of the extensibility of the new architecture, and we were very pleased with the results. It took 11 months to enable basic synchronization with EWS. With the new architecture, we were able to cut that time down to 4 months with Graph.
Graph’s operations are similar to the operations that EWS provides, but different enough that it served as a great first test case for how the new email client architecture can support future protocols, such as JMAP. Given the results of the Graph implementation, we are optimistic that the same architecture will extend to JMAP once the team decides to move forward to that new protocol. We are hopeful that what we have built here can provide a sustainable base on which to build future protocol support in Thunderbird.
This would not have been possible without many contributions from Thunderbird developers, past and present, and the community of users who have helped us improve Thunderbird by submitting issue reports and feature requests. We are grateful to everyone for their support!
People feel differently about AI, and here at Firefox, we think that is completely reasonable. Something else that is completely reasonable: deciding for yourself how and when you engage with AI features.
For some of you, AI is part of your everyday life, whether you are using it to summarize a large amount of information, brainstorm ideas for work, or research trips and personal purchases. Some of you interact with AI as little as possible, and prefer to keep it that way. And a lot of you are somewhere in between: curious, but exploring on your own terms and at your own pace.
Your personal use of AI is just that, personal. Firefox offers various levels of AI integration into your browser, and the choice between them is entirely yours.
Block new and current AI features in a single switch
Opting out of upcoming and current AI features on your browser should not require endless navigation through multiple Settings pages. That’s why Firefox offers an AI controls section within its General Settings panel. A single, easily located place where you can block current and future AI features and related pop-ups with the swipe of a toggle.
Not only do we want people to have the choice to remove certain AI features from their Firefox browsing experience, we make sure doing so is as easy and accessible as possible.
Choose the features that work for you
For the many people who sit in the middle of the AI usage spectrum, we made sure you can opt in and out of specific features in line with your preferences. Capabilities like AI translations, image alt text in Firefox PDF viewer, tab group suggestions, and key points in link previews can all be individually switched on and off, ensuring you can enjoy such offerings on a case by case basis as it suits your needs.
In addition, if there is an AI chatbot provider you already trust or pay for, you can use it directly inside Firefox’s built-in desktop sidebar. This means you can use your chatbot of choice and browse side by side without ping-ponging between tabs.
While some browsers integrate a singular AI model or chatbot into their system, this can restrict flexibility and concentrate data sharing. Firefox prioritizes transparency and user control by letting you select from multiple providers, allowing you to review each option’s policies before you engage with them.
You can turn on AI chatbot providers in the AI controls section of browser settings and select one of the following: Anthropic Claude, ChatGPT, Google Gemini, and Le Chat Mistral. Once this feature is turned on, you can switch between chatbots within the sidebar itself based on your preferences and task at hand.
Smart Window, for when you want help finishing what you started
Smart Window is Firefox’s most integrated AI experience, but that doesn’t mean it compromises our commitment to choice, privacy, and transparency. Our newest window type, which we’ve been polishing and testing in beta, uses only the context you share with it to help you move work forward and across the finish line.
When permitted by you, its built-in, AI-powered assistant can work directly with your open tabs and browsing history to connect the dots. This means comparing information, generating recommendations, summarizing pages, and planning projects without having to feed every crumb of context from your previous and current browsing activity each time you enter a new prompt.
As we’ve built out Smart Window, we’ve added a few additional features to align its design with how people actually browse. These include the ability to group related tabs together – so you can make sense of what’s open without spending time organizing everything yourself – and visual history previews that help you spot a page you visited earlier when you can’t remember the exact URL or phrase searched. In addition, a new partnership with Exa enables Smart Window to not only locate current web information to include in responses, but also display the sources behind these responses so you can verify what you’re seeing, without breaking your flow.
We understand people use different Firefox windows for different reasons, and often switch between options based on the task at hand. Smart Window is the window you reach for when your browsing turns into a project. When your quick search becomes inspo for the girls’ trip you’ve been meaning to plan, or finding the perfect gift for your partner becomes a dozen tabs comparing prices and reviews, turn the window you’re already using into a Smart Window. Your tabs and progress stay in place while Smart Window helps organize the task and move it forward. Use it for one complex project, use it all the time, or switch it back when you’re done. Smart Window remains in beta as we continue to learn and improve from our community’s feedback. At present, it’s available in English to people in the U.S. and Canada.
Your opinions and preferences on AI usage are individual to you.
We don’t think there is one right answer for how and when to engage with AI, and we’re not going to pretend there is one. What we can do is make sure that whatever level of engagement is right for you, Firefox supports it well. Because the only person telling you how much AI you need should be you.
Hello and welcome to another issue of This Week in Rust!
Rust is a programming language empowering everyone to build reliable and efficient software.
This is a weekly summary of its progress and community.
Want something mentioned? Tag us at
@thisweekinrust.bsky.social on Bluesky or
@ThisWeekinRust on mastodon.social, or
send us a pull request.
Want to get involved? We love contributions.
An important step for RFC implementation is for people to experiment with the
implementation and give feedback, especially before stabilization.
If you are a feature implementer and would like your RFC to appear in this list, add a
call-for-testing label to your RFC along with a comment providing testing instructions and/or
guidance on which aspect(s) of the feature need testing.
Always wanted to contribute to open-source projects but did not know where to start?
Every week we highlight some tasks from the Rust community for you to pick and get started!
Some of these tasks may also have mentors available, visit the task page for more information.
If you are a Rust project owner and are looking for contributors, please submit tasks here or through a PR to TWiR or by reaching out on Bluesky or Mastodon!
Are you a new or experienced speaker looking for a place to share something cool? This section highlights events that are being planned and are accepting submissions to join their event as a speaker.
If you are an event organizer hoping to expand the reach of your event, please submit a link to the website through a PR to TWiR or by reaching out on Bluesky or Mastodon!
This week continues a steady stream of compile time improvements. Most of the impact this week comes from type system
micro-optimization in #160473 and dead_code lint propagation
fix in #161571. We've also hit unexpected regression in a standard library
refactor, but we expect that to be addressed soon.
If you are running a Rust event please add it to the calendar to get
it mentioned here. Please remember to add a link to the event too.
Email the Rust Community Team for access.
WebDriver is a remote control interface that enables introspection and control of user agents. As such, it can help developers to verify that their websites are working and performing well with all major browsers. The protocol is standardized by the W3C and consists of two separate specifications: WebDriver classic (HTTP) and the new WebDriver BiDi (Bi-Directional).This newsletter gives an overview of the work we’ve done as part of the Firefox 155 release cycle.
Contributions
Firefox is an open source project, and we are always happy to receive external code contributions to our WebDriver implementation. We want to give special thanks to everyone who filed issues, bugs, and submitted patches. In Firefox 155, several WebDriver bugs were fixed by contributors:
For more than two decades, Mozilla has advocated for an internet where people, not powerful platforms, determine how technology works for them. Meaningful consumer choice requires more than the ability to select a browser. People should also be able to choose what their browser can do, from the privacy protections it provides to the ways they can customize their experience.
A recent Firefox product initiative brings that longstanding policy concern into focus.
Firefox is bringing a built-in Ad Blocker to Firefox for iOS, giving people an optional way to reduce intrusive ads and ad-related trackers while browsing. The feature uses an EasyList-based filter list and Apple’s WebKit Content Blocker framework. It is off by default and can be enabled or disabled at any time.
The feature responds to years of requests from Firefox users on iPhone. It also illustrates a wider policy problem: dominant mobile platforms can determine which privacy and customization tools competing browsers are able to offer.
On Firefox for desktop and Android, people can install add-ons that change how they experience the web.
Almost 40% of all Firefox users take advantage of this functionality. They include content blockers, accessibility tools, password managers and other extensions that allow people to shape their browser around their own priorities.
Firefox cannot offer that same add-on ecosystem on iOS. Apple’s App Review Guidelines generally require apps to remain self-contained and restrict them from downloading or executing code that introduces or changes an app’s functionality.
Apple also controls the conditions under which browsers may use alternative browser engines, with entitlement pathways available only in certain jurisdictions and subject to detailed requirements that no browser developer has been able to meet. In practice, the combined effect of Apple’s app distribution and browser policies prevents Mozilla from bringing the full Firefox add-on experience available on other platforms to iPhone users.
This is not simply a technical inconvenience but a competition and consumer-choice problem.
A mobile platform owner controls the operating system, the primary app-distribution channel and its own browser.
When that company can also determine which technologies, add-on models and operating-system capabilities competing browsers may use, it sets the boundaries within which browser competition takes place.
Operating system restrictions can prevent independent browsers from differentiating themselves.
Even when users want browsers to differentiate on privacy, operating system restrictions can prevent independent browsers from doing so. They can also force browser developers to recreate individual tools as platform-specific, built-in features rather than allowing people to choose from a broader add-on ecosystem. That increases development costs, slows or restricts innovation and produces uneven experiences across devices.
The new Firefox Ad Blocker is a practical response to those constraints. It gives iPhone users more control today using the technical options currently available to us. But building one feature directly into a browser is not a replacement for a healthy, independent add-on ecosystem. It addresses a specific capability gap for Firefox users on iOS at this time.
A competitive browser ecosystem should focus on the entire user experience.
The EU’s Digital Markets Act has shown that policy interventions can improve user choice, with Mozilla and other browsers reporting significant growth following the introduction of browser choice screens. However, meaningful browser competition must extend to the full user experience. This includes whether people can easily choose and change their default browser. It also includes whether people can benefit from the full set of innovations developed by rival browsers by ensuring adequate interoperability with the operating system. With this deeper focus on the full user experience, people can benefit from differentiated privacy and security features.
People’s privacy choices should not depend on whether a dominant platform permits their browser to offer them.
There’s only so much room on your screen. Pop-ups, overlays, and ads can take over fast, getting between you and what you came to do.
That’s where Ad Blocker for Firefox on iOS comes in: a built-in option that blocks many third-party ads and ad-related trackers before they load, helping reduce clutter and distractions while you browse.
How it works
Ad Blocker uses Apple’s WebKit Content Blocker technology and the EasyList filter list to determine what gets blocked. There’s no separate extension to install, and you can turn it on in Settings > Browsing > Ad Blocker. It’s off by default, so you decide whether to use it.
Ad Blocker won’t block every ad. Ads served directly by the site you’re visiting and ads shown in search results will still appear. Sponsored shortcuts and other sponsored content shown by Firefox when you open a new tab are separate from ads on the web pages you visit, so Ad Blocker doesn’t affect them.
Ad Blocker works alongside the privacy protections already built into Firefox, including Enhanced Tracking Protection, which blocks many trackers and limits tracking across the web.
More control over how you experience the web
On Desktop and Android, Firefox already supports a strong ecosystem of ad-blocking and privacy extensions, giving people the flexibility to choose the tools that work best for them. We value that ecosystem and will keep supporting it.
iOS works differently. Extensions aren’t available in the same way, and we know people want more options. Bringing ad blocking to Firefox on iOS meant building it directly into the browser.
Giving people choice in how they experience the web is important to us. Advertising helps fund much of the open web, supporting the publishers, creators and websites people rely on. We also know that ads can sometimes crowd the screen or interrupt what you’re trying to do.
That’s why Ad Blocker is optional: you decide whether it’s part of how you browse. It’s part of a broader approach across Firefox to give you more control over your experience, from the extensions you use to how AI shows up in your browser.
Try it
To turn on Ad Blocker, go to Settings > Browsing > Ad Blocker.
If you find an ad you expected to be blocked, a site that behaves strangely or something we should improve, let us know on Mozilla Connect.
The rustup team is happy to announce the release of rustup version 1.29.1.
Rustup is the recommended tool to install Rust, a
programming language that empowers everyone to build reliable and efficient
software.
What's new in rustup 1.29.1
The headlines of this release are:
Concurrency in certain rustup operations has been improved:
When running rustup update, rustup will first check for possible updates in parallel. pr#4752
When running rustup component add with multiple components, they will be installed concurrently. pr#4790
Implicit installation of the active toolchain in rustup-init and rustup invocations has
been deprecated where deemed unnecessary and will now produce a warning. pr#4840
Please see our
blog post
for more details regarding this change.
rustup doc now supports the --serve flag which allows serving the docs over local HTTP.
This should help users with containerized browser and/or rustup setups. pr#4986
Installing i686-pc-windows-* host toolchains on 64-bit Windows now requires --force-non-host.
pr#4935
rustup-init will no longer leave unexpected files on disk after cancelled installations. pr#4996
A bug has been fixed which might cause Windows installation to fail when using rustup-init.sh.
pr#4756
If you have a previous version of rustup installed, getting the new one is as easy as stopping
any programs which may be using rustup (e.g. closing your IDE) and running:
$ rustup self update
Rustup will also automatically update itself at the end of a normal toolchain update:
$ rustup update
If you don't have it already, you can get rustup from the appropriate page on our website.
Rustup's documentation is also available in the rustup book.
Caveats
Rustup releases can come with problems not caused by rustup itself but just due to having a new release.
In particular, anti-malware scanners might block rustup or stop it from creating or copying
files, especially when installing rust-docs which contains many small files.
Issues like this should be automatically resolved in a few weeks when the anti-malware scanners are updated
to be aware of the new rustup release.
Thanks
Thanks again to all the contributors who made this rustup release possible!
The web should be a place where people can choose how they connect, which tools they use, and who they trust. At Mozilla, we live these values, prioritizing products that ensure users can control their experience and that the web remains a global public resource.
Challengers across the tech ecosystem provide these competitive opportunities, but they contend with structural barriers imposed by tech giants leveraging market dominance. A healthy internet depends on ensuring that independent companies have a fair opportunity to innovate and compete on merit. That’s why Mozilla and many others support key legislation like AICOA.
So how do we promote proposals like AICOA and ensure that challengers can thrive in markets controlled by powerful gatekeepers? We explored these questions and more at the recent Mozilla Meetup, “How Challengers Thrive: Why Competition Matters for AI, Security, and the Open Internet.” Across panel events, a lightning discussion, and a networking happy hour, we discussed promoting an innovative, secure internet.
Partnering with Internet Works, Mozilla invited leading minds in tech policy to explore the importance of Middle Tech, AI’s impact on security and competition, and new research on deceptive design practices. Below are some highlights.
On today’s competition landscape, and Middle Tech as a user-first alternative:
Peter Chandler, Executive Director, Internet Works:
“Less competition equals less innovation equals less choices for consumers. It’s that simple.”
Charlotte Slaiman, Principal, Charlotte Slaiman Impact Advising:
“There are all sorts of reasons that competition is not just a click away. There are lock-in effects. There is gatekeeper power. Those things are protecting incumbents and making it much harder for consumers to switch to an alternative.”
On the impact of deceptive design tactics:
Gemma Petrie, Principal Researcher, Competition & Regulation, Mozilla:
“For independent browsers like Firefox, dominant operating systems are both the gateway to consumers and the direct competitor. When these platforms use harmful design to undermine free choice, this is not simply inconvenient. It can create consumer harm by overriding informed choice, social harm by eroding public trust in technology, and market harm by undermining competition and innovation.”
On the role of AI in competition and security:
Helen Toner, Executive Director, Georgetown’s Center for Security and Emerging Technology (CSET):
“It is really notable that in open source software, if you have more eyes on software and you can identify vulnerabilities, that makes it easier and quicker to patch those vulnerabilities to solve the problem. With AI, often we actually don’t have very good solutions when we identify problems, when we identify security risks, and so I think that can change some of the dynamics.”
Chris Lewis, President & CEO, Public Knowledge:
“We have an opportunity. It’s not too late in the AI era to not only design for competition through open technology, open source AI, model weights, some of the things we heard in the introduction, but also to set policies that promote competition.”
Avery Gardiner, Director of Global Competition Policy, Spotify:
“A big part of what I’m thinking about with AI is how quickly it allows us to innovate as an app developer, right, and how quickly we can speed up our coding, bring more features to consumers, bring more things to market, and be better at innovating for the consumer. And all of our competitors can do the same thing. So there’s this remarkable thing where the AI opportunities, the AI services, are getting better every passing day.”
There’s a reason we convene this community. As the web becomes both more complex and even more integral to our lives, competition offers people the ability to make meaningful choices about privacy, security, and control. Competition fosters innovation and spurs better products and services. Now is a particularly important moment to advance these priorities.
Hello everyone! It’s Jamie. My internship at Mozilla is quite unfortunately coming to an end, after which I will be heading back to study at the University of Toronto. In this post, I want to share a rundown of my story working on the Localization (L10N) team, break down the projects I built, and reflect on what made this experience so special.
The First Day
Before joining Mozilla I was quite a bit nervous, as I had never worked at such a large organization before. The first day shattered this perception, as getting an office tour and having a live Q&A with VPs of Engineering really set the expectations of what working at Mozilla would be like.
The Toronto office became the go-to place for connecting with passionate, mission-oriented people across different teams. After getting my computer set up, I immediately got to work on Pontoon, Mozilla’s Translation Management System (TMS). Since Pontoon’s codebase relies on React and Django — frameworks I’ve worked with before — I was able to set up my local environment running smoothly and ship code early on. Over time, I had the opportunity to meet my fellow interns, each on their own teams, and we had chances to bond over our shared experiences and different problems.
Spending my break time in the lounge with my fellow interns.
Since Mozilla is a remote-first company, the L10N team is distributed across Europe and North America. Working with them was an absolute highlight. To put it simply, they are a brilliant group of people of engineers, project managers and open-source contributors who keep Mozilla, and by extension, the wider web open and accessible.
Group photo with the L10N team! Taken August 2026
So, what was working at Mozilla like?
Working at Mozilla, I had the opportunity to contribute to a variety of features involving Pontoon, associated localization workflows and other cool projects. During the duration of my internship, a great deal of localization related work was centralized and continues to be that way, which significantly influenced the projects that I worked on, and more generally, how the L10N team will continue to operate when I am gone.
This work unfolded against the backdrop of an ever changing technological landscape, particularly involving industry adoption of AI tools for code generation. In 2025 and 2026, agentic coding assistants like Claude Code and Cursor began to achieve mass adoption in software development. At Mozilla, I was introduced to Claude Code as a tool later in my internship, which was excellent, as it allowed me to gain a broad understanding of how the codebase worked without the use of AI. After the introduction of Claude Code to my workflow, I was able to push code and conduct code reviews on a much greater scale. I appreciate that Mozilla does not shy away from the practical uses of AI, especially in the realm of improving engineer and localizer workflows, and importantly, making it a choice.
The Work
Here is a shortlist of the varying projects I had the opportunity to work on at my time with the L10N team.
The first task I was assigned to primarily revolved around the deprecation of Pontoon’s public-facing GraphQL API endpoints in favor of a Django REST Framework implementation. The motivations for this project included a preference for simplicity, desire for faster API response times and consistency with existing vanilla Django REST endpoints. The new public facing API lives here.
The next project I was given was to devise a new personal access token (PAT) implementation in Pontoon in order to gate permissions to the newly created REST API endpoints. I was inspired by the way that GitHub did their Classic personal access tokens so I tried to model my design around their implementation as much as possible.
The next project I took up was to reduce the feature gap between Pontoon and Transvision. For context, Transvision was and is used for searching available translations of strings across certain Mozilla products. It uses GitHub as its primary source, which is why it is limited only to the big projects. Thus the motivation was to create a similar service directly on Pontoon that has the most up to date strings with all Mozilla products, with data manipulation and access being a non-issue due to existing on Pontoon directly. Translation Search lives here.
Pontoon’s Translation Search, which searches for strings across Mozilla’s localized projects.
The Pontoon Add-on was a community maintained browser extension that enabled localizers to keep track of their locale’s progress and receive any notifications from Pontoon directly in the browser. As part of the Pontoon API rework mentioned earlier, we needed to refactor the add-on code in order to maintain functionality. The main contributor had limited availability to continue maintaining the add-on anymore, so Mozilla assumed ownership of the extension, and we managed to clean up some of the backlog and redeploy.
For years, Firefox Desktop and Firefox for Android used to operate under different localization workflows. Firefox for Android’s workflow was written such that Android developers needed to maintain deprecated strings to prevent previous versions of localizations of Firefox for Android breaking. Firefox Desktop does not have this issue due to different logic, so I rewrote the whole Firefox for Android workflow to be closer in substance to Firefox Desktop’s localization process. This subsequently deprecated the need for Android engineers to maintain the string deprecation process needed, which was great.
The last main feature set I worked on was the Insights dashboard and accompanying alert system. For context, the Project Managers on the L10N team needed to calculate a score assigned to locales each month for community health analysis purposes using a mish mash of spreadsheets and Python scripts. This project automated the capture and calculation of these statistics to the first of each month and displayed them on a dashboard along with other useful information. The alert system was also implemented which notifies admins of significant changes of scores for specific locales, so certain locales can get increased focus.
Insights dashboard, which enables our Project Managers to track locale health over time.
Final Thoughts
Working at Mozilla has undoubtedly been an enriching experience. I have met a great number of incredible people who have guided me, encouraged me and shaped me into a better engineer and a better person. It has certainly widened my perspective on localization as a global effort, where peoples across different languages, cultures and creeds can work together to build a better web. I leave with sharper technical skills, amazing memories, and zero regrets, only immense gratitude for the opportunity to contribute to software that empowers millions. 🙂
Acknowledgements
To Matjaž (engineer and mentor): Your presence has been invaluable, both as a mentor and a friend. Thank you for your patience with my 10 PM deployment requests, endless questions, and edge-case bugs.
To Flod (manager): You are as always the backbone of the team, and have certainly taught me many lessons regarding leadership, professionalism and dependability. Thank you for reminding me about my deadlines and being the go-to for questions and feedback.
To Eemeli (engineer): Your Zoom call escapades have always been inspiring to me, from burning detritus, cooking random stuff, remote data lag spikes and such much more. I truly wish to become like you with such a vast and bottomless knowledge for so many facets of software engineering, before AI completely rots my brain.
To Ayush (fellow intern): I hope my mentorship was as helpful to you as your camaraderie was to me. You are going to accomplish great things, my friend.
To Eric (engineer): I very much enjoyed your unique German humor, your kindness and passion for building cool technologies.
To Camila (PM): Your personality is incredibly energetic, and I’m sure you will continue to bring so much positive energy to the team. I hope that you continue to be ambitious in everything that you do.
To Eda (PM): I really hope you enjoy working as part of the L10N team. I hope that you continue to make an excellent contribution to Mozilla!
Thank you for reading about my time at Mozilla! If you would like to learn more or wish to connect, feel free to contact me on LinkedIn.
Servo 0.5.0 contains all of the changes we landed in July, which came out to 488 commits, and we now publish binaries for Linux aarch64 (@mukilan, #46760)!
If you’re working on a pull request that you think might be interesting for the next monthly update, even if you’re not 100% sure, tell us about it by following the steps below:
You add the monthly update label to your pull request, or comment @servo-highfive monthly update
Highfive posts a comment asking you some questions
You answer those questions in a comment containing @servo-highfive monthly update answer
Most of Gumroad (gumroad.com), except for the landing page, did not render at all in v0.4.0, but as of v0.5.0, pages like the Discover page or this product page render almost perfectly.
The upgrade to Stylo 2026-07-01 brings several changes to built-in CSS functions (@Loirooriol, #46129):
‘alpha()’ is now supported, under --pref layout_css_alpha_color_function_enabled
‘progress()’ is now supported, under --pref layout_css_progress_function_enabled
‘ellipse()’ values ‘closest-corner’ and ‘farthest-corner’ are no longer stable due to spec uncertainty, but they are still experimental, under --pref layout_css_ellipse_corners_enabled
‘attr()’ is more conformant, under --pref layout_css_attr_enabled
WebGPU content can now enjoy better conformance and use GPUExternalTexture and importExternalTexture() on GPUDevice, under --pref dom_webgpu_enabled (@sagudev, #45873, #46178, #46286).
IndexedDB content can now use the name property on IDBIndex, under --pref dom_indexeddb_enabled (@skyz1, #45512).
document.fonts now includes a FontFace for each valid ‘@font-face’, under --pref dom_fontface_enabled (@simonwuelker, #46509, #46537).
All of the features above are enabled in servoshell’s experimental mode.
We’ve started implementing WebVTT for native subtitles and captions, enabled by default (no --pref).
While they don’t render just yet, we can now fetch each <track src>, parse the WebVTT, and expose cues via the track property on HTMLTrackElement (@TimvdLippe, #46289, #46383).
July was a big month for accessibility in Servo, under --pref accessibility_enabled.
The focus for this month has been on performance, with the accessibility tree now supporting incremental updates (@alice, @delan, #45578, #45971, #46589, #46691, #46385), requiring fewer HashMap lookups and tree walks (@alice, @delan, #45798, #46740, #46348), and allowing for faster DOM mutations (@alice, #46348, #46530).
We’ve also started working on the File and Directory Entries API, to allow users to select and upload entire directories via <input type=file> and drag-and-drop.
To that end, we now have webkitGetAsEntry() on DataTransferItem, plus minimal support for FileSystemEntry, FileSystemDirectoryEntry, and FileSystemFileEntry, under --pref dom_entries_api_enabled (@yezhizhen, #46456, #46879, #46832).
servoshell for Android now runs on Android 10+ (91% market share), not just Android 13+ (68% market share), improving adaptability and reducing waste (@jschwe, #46142, #46308).
We’ve also fixed a problem with building for Android on macOS (@jschwe, #46128).
servoshell for Windows is now better behaved when run in a console window, making the command prompt wait until servoshell exits (@yezhizhen, #43010).
When using the Firefox DevTools, the Console tab now supports some basic autocomplete (@freyacodes, #46382).
Inline SVG can now use web fonts defined in the containing page (@yodalee, #45979).
We’re also implementing the SVG DOM, starting with stub interfaces for SVGElement, SVGCircleElement, SVGDefsElement, SVGEllipseElement, SVGLineElement, SVGLinearGradientElement, SVGPathElement, SVGPolygonElement, SVGPolylineElement, SVGRadialGradientElement, SVGStopElement, SVGRectElement, SVGSymbolElement, and SVGUseElement (@mu-mostafa98, #46558).
2D canvas rendering is now multithreaded, improving frame rates by up to 55% and power consumption per frame by up to 42% (@yezhizhen, #46410), and should use a lot less memory too (@jschwe, @sagudev, #46786).
Text rendering is up to 10x faster for cases with the same text and different ‘font-size’ (@Loirooriol, #46129).
Flex layout benchmarks are up to 3% faster, and an improvement to getElementsByClassName() has made some websites up to 1% faster (@Narfinger, @jdm, #46563, #46595, #46594).
Interested in helping build a web browser?
Take a look at our curated list of issues that are good for new contributors!
Donations
Thanks again for your generous support!
We are now receiving 7824 USD/month (+1.8% from June) in recurring donations.
This helps us cover the cost of our speedyCIandbenchmarkingservers, one of our latest Outreachy interns, and funding maintainer work that helps more people contribute to Servo.
Servo is also on thanks.dev, and already 35 GitHub users (same as June) that depend on Servo are sponsoring us there.
If you use Servo libraries like url, html5ever, selectors, or cssparser, signing up for thanks.dev could be a good way for you (or your employer) to give back to the community.
We now have sponsorship tiers that allow you or your organisation to donate to the Servo project with public acknowlegement of your support.
If you’re interested in this kind of sponsorship, please contact us at join@servo.org.
Unified builds (also know as Jumbo Builds) is a build techniques that aims at
improving build time through the concatenation of several sources as a single
unified source before compilation.
The goal is obtained through implicit caching of header instantiation, although it
implies a trade-off with parallelism.
Let's illustrate this behavior through a simple example, two codes that implement variation of the same approach:
/* algo0.cpp */#include<iostream>#include<string>#include<vector>voidtranslate(std::vector<std::string>&w,void(&t)(std::string&));voidtranslate(std::vector<std::string>&w_out,std::vector<std::string>const&w_in,void(&t)(std::string&)){std::cout<<"[log] through transform\n";w_out=w_in;translate(w_out,t);}/* algo1.cpp */#include<algorithm>#include<iostream>#include<string>#include<vector>voidtranslate(std::vector<std::string>&w,void(&t)(std::string&)){std::cout<<"[log] through for_each\n";std::for_each(w.begin(),w.end(),[&t](std::string&s){t(s);});}
Compiling individual files take the following times:
In that simple case, the weight of headers with respect to actual user code is such that
compilation of the unified file takes almost the same time as the max compilation time among each individual file. That's roughly a 1.97x speedup on compilation time.
That's the promise given by unified builds. And it's a promise held.
Now let's have a look at the consequences of that deal.
Beforehand, we still need to introduce another parameter tied to unified builds: the
unification parameter, say P. That parameter bounds the number of files
that are unified together. Let's imagine we have a hundred of individual source
files compiled with exactly the same compilation flags. Setting P to 5
leads to the generation of 20 unified sources compiled independently.
Remember the parameter P.
Quality of the Generated Code
Let's create a shared object from algo{0,1}.o (this implies a recompilation with -fPIC of the sources):
After stripping, comparing the size of the binaries yield a difference of a few bytes. After disassembling, it turns out the compiler decides to inline the call to void translate(std::vector<std::string>& w, void (&t)(std::string&)) from algo0.cpp when compiling the unified source, something the compiler cannot do when doing split compilation, as it does not know anything about the implementation of that function.
Interestingly, compiling with -flto=thin still lead the compiler instantiation through different optimization path.
Falling back to -flto=full finally yields to the same shared object, which makes sense because Full LTO is very close to performing source unification at the bytecode level and our sources are very simple. It's not a given though because the actual optimisation pipeline is still different in the two scenario.
Why does it matter? Depending on the value of P, the compiler will see
different sets of files per unified file, which will result in different binary
code. It's actually even worse: depending on the way we fill those unification
sets, event with the same parameter P, we end up with different binaries.
Let's call that the reunifying problem.
Even if we have an algorithm that seems to guarantee reproducibility, for
instance working on a sorted list of files with a fixed P, variation can
arise: the introduction of a new source file can lead to changes in every
unified file (e.g. if the split is done by chunks and the new file ends up at
the beginning of the file list).
So unified builds tend to improve performance, but they do not interact in a gentle way with performance reproducibility.
Recompilation Times
Let's denote S as the number of sources and C as the number of CPUs.
Intuitively, setting P=1 yields to the faster recompilation time when a
single file is touched---a usual scenario when developing a new feature.
On the opposite, setting P=S yields to the slower recompilation time (if S >>
C!) under the same scenario as all sources are recompiled under that
scenario.
The form of the curve between those two extreme varies depending on the nature
of the files, and the amount of header sharing between individual sources.
Caching tools like sccache is impacted by the same mechanism: as P gets
greater, more cache misses are hit and more recompilation are done.
Marginally, introducing a new source also pollutes the cache or triggers
recompilation for the unified source it gets added to, and eventually for all
the unified sources derived from the associated file list. The reunifying problem strikes again.
So unified build make compilation faster, but recompilation slower. Setting
P to an acceptable value is important depending on the usage scenario.
Correctness
Unified build changing the compilation unit frontier, which in turns modifies
the semantic of the program. This change can be straight-forward or complex to
debug, and even remain silent. I've listed a few instances of the two first
categories below, and a crafted one for the latter category.
Macro / Symbol Redefinition
This one is trivial to spot (a preprocessor-warning is issued for the macro,
and a compiler error is issued for the symbol redefinition):
/* pi0.cpp */#define PI 3.141593constexprdoublepi(){return3.141593;}/* pi1.cpp */#define PI 3.14159265constexprdoublepi(){return3.14159265;}
The solution usually lies in moving the definition in a shared header, moving the declaration in a shared header and the definition in a single file, or renaming identifiers to avoid the name conflict. Note that depending on the solution we may change the visibility of the symbols, or impact code readability (assuming the identifier name was perfectly chosen in the first place).
Overload Conflicts
This one is also trivial to spot and may hint toward debatable design. But it exists and may be more complex to understand than the above:
The fix is generally to provide a perfect match for the overload, change the call site to avoid the ambiguity, or rename the functions/change their namespace to make the call site explicit.
Using Namespace Confusion
This one tends to creep a lot in codebase where using namespace is used. It generates ambiguity among potential symbols.
A caricatured situation is exhibited with the following situation:
The problem with that category is that the fix is quite unsatisfying: there is no way to limit the scope of a using directive, removing using directive can lead to very verbose codebase, renaming symbols to avoid conflicts goes against the very purpose of namespaces...
Delicatessen
I spent a lot of time nailing that one down, so I wrote a small reproducer to illustrate the problem.
Let me comment that layout a bit: We basically have two different classes named Lock: one lives in the mozilla::dom namespace, and one lives at top-level. In header1.h, although we include the definition of mozilla::dom::Lock, we also get the definition of ::Lock, so a straight reference to Lock is not ambiguous.
Concerning source files, src0.cpp, src1.cpp and src3.cpp just include headers while src2.cpp contains the infamous using namespace modilla::dom; statement.
Let's now consider various partition of the file list src0.cpp, src1.cpp, src2.cpp, src3.cpp:
Isn't that amazing? Some intermediate unification, namely 0,1;2,3 and 0;1,2,3 fail, but other unifications, namely 0,1,2,3 and 0;1,2,3 fail. Did you notice that both non-unified and full unified build succeeds, while some intermediate unification fail? What a disaster. This basically mean that given a set of sources, and without putting restriction on the language (like banning using statement), the only way to be sure that a unified build always succeeds whatever the chosen partition is to test every partition. Not very satisfying.
As a side effect, we can also deduce that adding a new source file to a set of files to be unified can break compilation in files that used to compile fine. That's another instance of the reunifying problem.
Changing Semantic
It is quite easy to derive from the above an example whose semantic change once unified. Let's slightly change the overload conflict example from above:
When compiled independently, this results in a binary that prints a 0 and a 1 on the screen. But when compiled as a unified source, we only get a pair of 0.
Concluding Words
Remember that discussion between Luke and Yoda?
LUKE
Vader. Is the dark side stronger?
YODA
No… no… no. Quicker, easier, more seductive.
That's exactly my thoughts on unified builds: they give you quick wins in
term of cold build speed and give faster builds. That's very good
properties, and you rip the benefit of them very quickly. Then you realize
that you're tied to a monster in terms of maintainability and developer
experience, but you're already addict to the speed it gave you.
The first effort was to use platform-specific profilers to generate profiles in CI of browsers running the Speedometer 3 benchmark, the industry-leading benchmark for browser performance. These ‘native’ profiles provide rich, system-wide insight into how browsers handle Speedometer 3, helping developers analyze and diagnose behaviour. They also provide us with profiles we can use to generate comparison reports for patches. We needed Raptor to generate native profiles for all of our platforms, namely Windows, macOS, Linux, and Android.
At a high level, the pipeline to generate native profiles is as follows:
Start the system profiler.
Run Speedometer 3 on Firefox or Chromium as Release using Raptor and Browsertime.
Stop the system profiler.
Symbolicate the profiles using samply and the corresponding build symbols.
Post-process the symbolicated profiles using profiler-edit (formerly symbolicator-cli) and create compact and labelled variants of the profiles.
Upload the processed profiles as artifacts.
To run tests with native profiling, you can use ./mach try fuzzy --full or ./mach try perf --full and run any test that has the -native-profiling suffix.
On Windows, we produced profiles using xperf, a tracer that uses the Event Tracing for Windows framework (ETW) to capture system-level data on applications running on Windows. To use xperf with our CI machines, scheduled tasks to run the tracer were configured in Puppet (see our ronin_puppet repository).
After adding support to Raptor to trigger these xperf tasks, we can start a trace and run the Speedometer 3 benchmark on Firefox or Chromium as Release (our custom Chromium build configured with release flags) using Browsertime. The Speedometer 3 benchmark runs 20 times, with each run in a separate browser cycle, to ensure we collect enough samples before stopping the trace.
Once completed, xperf provides a user trace and a kernel trace, which are combined into a full trace. We can then use samply to convert and symbolicate these traces into Firefox Profiler profiles, complete with markers and JIT information (Figure 1 and Figure 2).
Figure 1: Native profile of Speedometer 3 running on Firefox on Windows
Figure 2: Native profile of Speedometer 3 running on Chromium as Release on Windows
On macOS, we took a similar approach. We used samply to collect and symbolicate profiles. After implementing a workaround to allow samply to profile across multiple browser cycles and sorting out permission issues in CI, samply could profile Speedometer 3 on Firefox with minimal CI configuration and symbolicate the profiles afterwards.
On Linux, we ran perf with elevated privileges to collect profiling data system-wide before using samply to symbolicate and convert the data into a Firefox Profiler profile. Other than enabling our CI machines to run sudo perf, no additional machine configuration or workarounds were needed.
For Android, we took a slightly different approach. We used simpleperf to collect profiles on our mobile devices in CI (Samsung A55, Google Pixel 6, and Samsung S24) and samply to symbolicate them.
Initially, we wanted to profile 20 Speedometer 3 runs in a single simpleperf session, matching our desktop profiling workflow, but this proved unreliable during testing, as the on-device profiling appeared to be resource-intensive and would intermittently fail or crash.
We decided to use our simpleperf support introduced in Browsertime in Part 1 to profile the 20 individual test suites that make up a single Speedometer 3 run separately, which proved to be more stable (Figure 3). In the long term, we plan to support profiling complete Speedometer 3 runs with simpleperf on Android, bringing the workflow closer to what we currently use for desktop profiling (Bug 2032007). We will introduce native profiles for Chromium as Release (mobile) on Android in Bug 2067157.
Figure 3: Native profile of the TodoMVC-Vue Speedometer 3 test running on Fenix (Firefox for Android)
To make our Speedometer 3 profiles clearer and more helpful, we post-process them with profiler-edit, which adds labels (groupings of JS frames) to the profile (Figure 5) and also provides a more compact version (Figure 4) where all runs are placed on the same process track.
Figure 4: Compact Speedometer 3 native profile
Figure 5: Labelled Speedometer 3 native profile
In CI, we routinely generate Firefox profiles on autoland (Figure 6) and Chromium as Release profiles on mozilla-central. These native profiles have already been used to produce Speedometer 3 comparison reports (Figure 7) and investigate incidents in CI. Currently, profiles for Chromium as Release on macOS and Linux are works in progress (see Bug 2050869 and Bug 2065970, respectively).
Figure 6: Native profiles running routinely on autoland
Figure 7: Comparison reports using native profiles (preview courtesy of Markus Stange)
The second effort was to fully modernize symbolication in mozgeckoprofiler, the module responsible for symbolication across four performance testing frameworks: Raptor, Talos, XPCShell, and Mochitest. This mainly involved phasing out Eliot, an older symbolication API service scheduled to sunset in the near future, and fully transitioning the module’s symbolication workflow to use samply and profiler-edit.
In Part 1, we added support that allowed Raptor and Talos to symbolicate their profiles using our new approach. This left two main cases that were still handled by Eliot: XPCShell and Mochitest symbolication, and local profile symbolication.
Implementing XPCShell and Mochitest profile symbolication (Bug 1998767) was relatively straightforward. We followed the same approach used for Talos and Raptor by adding our new symbolication dependencies to XPCShell and Mochitest taskgraph configurations. Since these tests and their profiles (Figure 8) can be generated in parallel, we made sure to perform symbolication only after all profiles had been generated. You can try these jobs by running ./mach try fuzzy --profiler and selecting any XPCShell and/or Mochitest job (Figure 9).
Figure 8: Symbolicated Mochitest profile
Figure 9: Mochitest tests running in CI produce symbolicated profiles
Originally, when generating profiles locally from one of our performance frameworks, Eliot was used to symbolicate those profiles. To replace it with our new approach, we needed to bootstrap samply and profiler-edit onto local developer machines. Now, when you run ./mach bootstrap, the latest builds of samply and profiler-edit available in CI for your platform are automatically installed under the local .mozbuild/ directory. With this change, the use of Eliot in PerfTest has been completely replaced by our new symbolication approach, and Eliot can safely be retired from mozgeckoprofiler!
What’s Next
These patches are part of an ongoing effort to make performance profiling easier, more standardized, and more useful for Firefox developers. Here are a few related bugs to keep an eye on:
In Bug 2050869, Bug 2065970, and Bug 2067157, we’ll add Chromium-as-Release profiling support for macOS, Linux, and Android, respectively.
In Bug 2066906, we’ll officially remove Eliot as mozgeckoprofiler’s fallback symbolication service.
In Bug 2032007, we’ll add support for profiling full Speedometer 3 runs with simpleperf, rather than producing a profile for each test suite.
In Bug 2036104, we’ll continue developing reports that compare native profiles across patches, making it easier for developers to investigate performance differences and regressions.
Hello and welcome to another issue of This Week in Rust!
Rust is a programming language empowering everyone to build reliable and efficient software.
This is a weekly summary of its progress and community.
Want something mentioned? Tag us at
@thisweekinrust.bsky.social on Bluesky or
@ThisWeekinRust on mastodon.social, or
send us a pull request.
Want to get involved? We love contributions.
An important step for RFC implementation is for people to experiment with the
implementation and give feedback, especially before stabilization.
If you are a feature implementer and would like your RFC to appear in this list, add a
call-for-testing label to your RFC along with a comment providing testing instructions and/or
guidance on which aspect(s) of the feature need testing.
Always wanted to contribute to open-source projects but did not know where to start?
Every week we highlight some tasks from the Rust community for you to pick and get started!
Some of these tasks may also have mentors available, visit the task page for more information.
If you are a Rust project owner and are looking for contributors, please submit tasks here or through a PR to TWiR or by reaching out on Bluesky or Mastodon!
Are you a new or experienced speaker looking for a place to share something cool? This section highlights events that are being planned and are accepting submissions to join their event as a speaker.
If you are an event organizer hoping to expand the reach of your event, please submit a link to the website through a PR to TWiR or by reaching out on Bluesky or Mastodon!
A busy week, with a continued stream of improvements to the next trait solver
and next borrow check implementations. Other than those changes, the week was
pretty quiet for performance.
No Items entered Final Comment Period this week for
Language Team,
Language Reference or
Unsafe Code Guidelines.
Let us know if you would like your PRs, Tracking Issues or RFCs to be tracked as a part of this list.
If you are running a Rust event please add it to the calendar to get
it mentioned here. Please remember to add a link to the event too.
Email the Rust Community Team for access.
I care about this community, including its human and social nature. I want others to appreciate those qualities, and I don't want to see them compromised and replaced by excessive machine-generated content.
We are very happy to announce the Rust Project's first round of Maintainers in Residence:
Gen Li (@rami3l), Chris Denton (@ChrisDenton), Alejandra González (@blyxyas), León Liehr (@fmease), and Maintainer Grant recipients: Jason Newcomb (@Jarcho) and Jonas Böttiger (@joboet). These contributors will be funded for their rust-lang maintenance activities for (at least) the following 12 months!
The funding of the Maintainer in Residence (MiR) and Maintainer Grantee roles is possible thanks to generous donations to the Rust Foundation Maintainers Fund (RFMF) from Google, AWS, OpenAI, the Rust Project Leadership Council and also individual sponsors. We also want to thank the people who advocated for maintainer funding within their companies; Tyler Mandry from Google, Niko Matsakis and Jess Izen from AWS and Predrag Gruevski from OpenAI, and also the whole Rust Leadership Council and our funding advisors. If you would like to help us support even more Rust contributors, consider donating to RFMF.
The Rust Foundation has published a press release and a blog post, where you can learn more about the sponsors and the supported contributors.
Read more below to learn about the MiR program, how we chose the funded contributors, and of course who they are!
Background
The Maintainer in Residence program, established in RFC 3931, is designed to provide stable financial support for Rust contributors, so that they can truly focus on crucial maintenance activities. Currently, there are three categories of support that we offer:
Full-time MiR: funded for 5 days/week of Rust Project work
Half-time MiR: funded for ~2.5 days/week of Rust Project work
Maintainer Grant: funded for ~1 day/week of Rust Project work
Funding for this program comes from the Rust Foundation Maintainers Fund, which was launched recently, and the whole program is managed by the Rust Funding team.
When deciding who to fund, we took a systematic approach. First, we looked at Rust teams to understand their maintenance baseline (the smallest number of maintainers they need to ensure a healthy long-term status of the given project or repository), and how far they currently are from that baseline. From there, we identified and prioritized Rust teams who were both critically underfunded, and have a high impact on the language and its users. These teams (in no particular order) were rustdoc, rustup, cargo, compiler, libs, clippy, rustfmt, rust analyzer and mods.
The next step was pairing these teams with maintainers looking for funding. And it turns out that finding such maintainers for some teams turned out to be much more difficult than we originally assumed! For example, some maintainers are already employed, some do not want to be funded, and while we did our best to promote our funding efforts, not everyone looking for funding actually asked us for it. We also realized that some teams on our list have essentially no active members, which makes it tricky to onboard new contributors, even if they would like to help out.
In the end, we decided to start by supporting six contributors, who will help maintain several critical Rust projects and teams and who could start immediately. However, we are not stopping there. Our funding efforts are ongoing, so stay tuned for more MiR announcements in the near future! If you would like to learn more about our process, check out our recent post.
And now, without further ado, let's meet our newly funded maintainers!
Gen Li (@rami3l)
Gen Li (@rami3l) is a full-time MiR focusing on Rustup.
He has been a Rustup team member since 2023 and its lead since 2025. He deeply cares about the facets of Rust that many might have taken for granted, and embodies all attributes we were looking for in a MiR: he wants to take on complex issues, continue mentoring, and work on important Rustup features, among many other things.
Turning volunteering into an actual job has really been an empowering experience so far! I finally have the bandwidth to take a careful look at my inbox and can actually read each message without the fear of missing crucial details while rushing prompt replies, which has really helped me retain the essential compassion as a maintainer. I also get to interact with regular contributors a lot more often. Finally, I can't wait to see what I can come up with in terms of Project Goals :)
Chris Denton (@ChrisDenton)
Chris Denton (@ChrisDenton) is a half-time MiR focusing on the standard library, compiler, Rustup and anything Windows-related.
For the past five years Chris has been bringing his deep knowledge of Windows to help Rust sustain and improve its great cross-platform support. He will be unblocking other contributors in various Windows use cases, performing refactoring and code reviews and implementing new features across several areas of the Project.
Even though it is still early days, I'm feeling pretty optimistic about the health of the Rust Project going forward, thanks to the recent funding efforts.
Alejandra González (@blyxyas)
Alejandra González (@blyxyas) is a half-time MiR focusing on Clippy.
She is a Clippy team member always keen on improving performance and helping new contributors. She will focus on making Clippy faster and also reviewing its pull requests, to help get the ~300 pull request backlog down. Additionally, she is excited to mentor people from the Rust for Linux project to work on Clippy, and fine tune the open peer review system that Clippy started using earlier this year.
Funding is the system that helps me pour my heart into a project without worrying about making ends meet. Having those needs met is a game-changer and boosts my productivity. One of the areas where I want to focus my efforts is mentoring new contributors. If new people coming is the lifeblood of a project, I want to be the cardiologist!
León Liehr (@fmease)
León Liehr (@fmease) is a half-time MiR focusing on rustdoc and the compiler.
He is a member of the rustdoc and compiler teams, who is usually working on the Rust type system or issues related to parsing. He will continue working on complex features that he started a few years ago, and also focus on general maintenance, code reviews, refactoring and mentoring.
Being funded to work on Rust means I can sustainably focus my time and energy on a project I call a passion of mine.
Jonas Böttiger (@joboet)
Jonas Böttiger (@joboet) is a maintainer grantee focusing on the standard library.
He is a musicology student from Germany. When he is not playing the Cello or reading about Fanny Hensel, he applies his research skills to ensure that programs written in Rust run quickly and soundly on all platforms, no matter how quirky the operating system may be. He loves helping contributors write excellent code that they can be proud of; and considers it to be just as much fun as writing it himself.
Getting funding for my work is a dream come true. It will allow me to continue doing the thing I love instead of worrying about whether I should rather invest all that time in a money-earning job with much less positive impact on the world around me.
Jason Newcomb (@Jarcho)
Jason Newcomb (@Jarcho) is a maintainer grantee focusing on Clippy.
He is primarily working on fixing bugs and making it easier to develop and contribute to Clippy. He is also focusing on making the review process as smooth as possible.
Being funded allows me to work on something I care about and want to work on instead of what will get me paid. I'm looking forward to seeing how this will impact Clippy and the Rust project in general.
Conclusion
The contributors presented above will be funded for the next 12 months, though of course we hope that we will be able to extend their support going further, as this program is designed to be for long-term stable maintenance funding. We are very excited about them; each one of them has been with the Project for years, and we are very glad that we can support their maintenance work! All of them have already signed their contracts, so they are already being funded as we speak.
While there are many other Rust contributors who are doing awesome work, and who would also deserve to get proper funding for it, we think that this is a great start. We hope that the awesome work done by the funded maintainers will allow us to promote this program, so that we can fund even more Rust contributors!
We would like to once again sincerely thank everyone who made this possible, especially our sponsors. If you would like to help us fund more maintainers, consider donating to RFMF. You can also sponsor individual Rust contributors directly.
Starting in Firefox 154, we’ve added a new capability for changing the default browser icon for Windows (Windows-only, for now, and not MSIX / Store installs) in about:settings#appearance!
Added moz-promo cards to the about:addons extensions list recommendations footer and empty state, and updated the openAmoInTab helper to support a custom UTM content value – Bug 2043615 / Bug 2050880
Introduced the building blocks for the Nova Themes Picker in about:addons: a shared Firefox Themes list source of truth, a light/dark/device theme-mode switcher, a reusable theme-preview webcomponent, and Nova-styled theme previews – Bug 2051554 / Bug 2051559 / Bug 2051564 / Bug 2051573
Updated the Extensions panel empty state illustration and toolbar item icon for Project Nova – Bug 2030715
Thanks to Michael Hynson for driving this.
Removed the legacy AddonManager Glean metrics used for mirroring legacy telemetry events, along with the corresponding legacy telemetry test checks – Bug 1923949 / Bug 1981822
Thanks to Chris H-C for collaborating with us on this.
Fixed themes installed through the distribution mechanism not fetching their AMO metadata, which was resulting in distribution installed themes left without a preview image in about:addons – Bug 1917279
Thanks to Mike Kaply for the fix to the distribution themes metadata handling.
Fixed amContentHandler to verify that a system triggeringPrincipal genuinely originated from the parent process, a regression introduced in Firefox 153 and fixed in Firefox 154 (with a beta 153 uplift requested) – Bug 2048964
WebExtensions Framework
Fixed a startup performance regression by avoiding an NSS-initializing crypto.getRandomValues() call during extension startup, a regression introduced in Firefox 153 and fixed in Firefox 154 (with a beta 153 uplift requested) – Bug 2050882
Enabled tier 3 TypeScript typecheck linting for the extensions framework code – Bug 2050124
Implemented the WebExtensions manifest sandbox key, letting extensions keep using string-based code execution in unprivileged sandboxed extension documents – Bug 1685123
Thanks to Robin for the implementation of the manifest sandbox support.
WebExtension APIs
Enabled storage.local database auto-reset on detected corrupted IndexedDB storage on all channels, starting in Firefox 154 – Bug 1992973
Simplified registerTraceableChannel to make it synchronous again, removing the delay before blocking webRequest listeners can register a traceable channel – Bug 2044518
Restored the contextualIdentities iconUrl container icons to their intrinsic 32×32 size, fixing a regression introduced earlier in the Firefox 154 cycle – Bug 2048599
Thanks to Andrea Marchesini for the fix to the contextualIdentities container icons.
Fixed the MV2 userScripts API failing with an Xrays TypedArray access error due to a missing isWebExtensionContentScript flag – Bug 2054083
Thanks to erosman for the fix to the MV2 userScripts API.
Nicolas Chevobbe about:debugging is now using moz-page-nav for its left sidebar (#2048544), thanks to Mark making it possible to disable collapsing that occurs on narrow screen (#2050907)
(not all items were migrated to moz-page-nav-button though, see #2050746 for remaining work)
Alexandre Poirot made it possible to control the request and response body size limit from the Settings panel (#2040892)
That’s a wrap for the World Cup! We’re powering down the Sports widget today.
Some folks might see a survey about the Sports widget, to get feedback from the wild on whether or not it provided any user value (Telemetry points to “yes”, but it’s good to get qual data too)
We’re replacing it with some new widgets. If you’re in an English-speaking region, you will probably see it replaced with a Daily Crossword widget. Otherwise, it’ll be replaced with a Picture of the Day widget.
Sections have rolled out to 100% in France! We’re now doing 10% Sections experiments in Spain, Italy, Austria, Switzerland and Belgium.
Joel added WebNotifications to the newtab state, allowing New Tab widgets to observe and reflect WebNotification events (affects the notification-driven widget lifecycle and UI state updates).
Reem Hamoui adjusted the New-Tab Widgets 3-dot menu layout to vertically center menu entries inside the hover-granted colorful stripe, removing visual misalignment and small hit-area offsets on touch and pointer inputs.
Scott Downe fixed New Tab Page drag-and-drop so widgets no longer jump or keep moving during drags (2049472).
Reem Hamoui rendered the Daily Crossword in a sandboxed iframe to isolate its scripts/CSP on the New Tab Page (2049489).
Reem Hamoui added the Crossword option to about:preferences and wired the New Tab Page crossword widget into prefs (2050340), so users can enable or disable the crossword via the standard Preferences UI rather than about:config.
Dre set up the Picture of the Day boilerplate, including prefs and basic New Tab UI components (2050969), which exposes a configurable PoD surface for users to opt into and customize.
Dre added a dismiss control and persisted dismissal state to the daily photo UI (2050972), allowing users to remove the current picture from their New Tab and avoid immediate reappearance.
Dre added a “set as wallpaper” action and hooked it into New Tab wallpaper storage/prefs (2050973), enabling users to promote a PoD image to their custom New Tab wallpaper persistently.
Dre connected the Picture of the day widget to the Merino endpoint to set the background of the widget to the current picture (2050976). He also added telemetry for the Picture of the day widget on the New Tab Page to capture impressions and clicks for usage analysis (2050977).
Nina Pypchenko [:nina-py] added a small size variant for the Focus Timer widget in Nova so the timer can render compactly in narrow/new tab layouts and reduce vertical space usage (2051179).
Dre introduced two variants of the World Cup widget survey message, changing the copy delivered in the widget to support an A/B/message-variant experiment and altering what users see when the World Cup widget surfaces survey prompts on their New Tab Page.
Nina Pypchenko [:nina-py] added an error state to the Stocks widget on the New Tab Page to show an explicit failure UI when quote fetches or network requests fail, reducing user confusion.
Irene Ni fixed the New Tab add-pin flow that was creating extra rows when grouped pins was off by changing the insertion logic to append into the existing grid, which eliminates unexpected row creation and layout shifts for users managing many pins (2053251).
Scott Downe updated New Tab section rendering to hide cards that don’t fill their row by adjusting layout logic/CSS, removing orphaned placeholders and reducing blank space on narrow viewports or low-item sections for a cleaner grid appearance (2053264).
Reem Hamoui added a context menu to the Crossword widget using a postMessage integration between the iframe and parent page, enabling right-click actions (copy/hint/theme) and making the embedded crossword more interactive and accessible to users who rely on context menus (2053311).
Reem Hamoui added a visible “New” badge plus interaction handlers and state tracking to the Crossword widget on the New Tab Page to improve discoverability and make tapping/clicking behave reliably when launching puzzles (2053667).
Irene Ni removed unused Add Shortcut OMC artifacts from the New Tab Page (2053843); this is a cleanup of obsolete assets/templates and has no direct runtime user impact.
Maxx Crawford added author and license attribution to the Picture of the Day widget (2053933); this surfaces photographer credit and license metadata on the New Tab Page for users who want provenance information.
Maxx Crawford applied UX refinements to the Picture of the Day widget (2054109); users will see improved layout, spacing, and touch targets in the POTD area for clearer interactions.
Maxx Crawford added a pref and trainhopConfig gate to toggle the POTD “Set as wallpaper” feature (2054111); rollout and availability of the wallpaper action are now controllable via pref and remote trainhopConfig.
Maxx Crawford added a dedicated trainhopConfig.widgetPictureOfTheDay payload for POTD feature config (bug 2054112) so the New Tab Page train-hop widget can be controlled server-side — this delivers image URLs, attribution and display params remotely which lets us enable/disable POTD per cohort without ship-side changes and reduces rollout latency for users who see the Picture‑of‑the‑Day widget.
Irene Ni updated the Shortcuts Add/Edit dialog for Nova (bug 2054175) to improve the add/edit UX on the New Tab Shortcuts surface — the patch adjusts dialog layout and controls, tightens validation and accessibility labels, and reduces accidental duplicate/invalid shortcut creation so users editing shortcuts have a more reliable, faster flow.
Maxx Crawford fixed Related articles not opening on click by repairing the related-articles component’s click handling and event delegation (anchor href/target behavior and JS listener) on the New Tab Page so article tiles now reliably open on click for users.
Irene Ni migrated the New Tab Widgets expand button to moz-button which standardizes the expand/collapse control on the New Tab Page widgets area, fixing inconsistent styling and keyboard/click handling so users now get consistent visuals and improved accessibility across platforms.
Maxx Crawford added per-widget feature toggles and pref reset buttons to Discovery Stream Admin, enabling admins to toggle individual widgets and reset prefs without code deploys — changes here can alter what users see when toggled.
It isn’t often that new image formats land in browsers. In the early 2000s we had JPEG, GIF, and PNG. The 2010s gave us WebP, which was a modest step up from JPEG. But the 2020s have given us two new image formats that are a big step up from previous formats: AVIF and JPEG XL.
We shipped AVIF back in 2021, and today we posted our intent to ship JPEG XL. Chrome are also intending to ship, and given there’s already a partial implementation in Safari, the format will be supported across browsers before the end of the year.
Shipping JPEG XL securely
We added experimental support for JPEG XL behind a flag back in 2021. But, at 100,000 lines of multithreaded C++, we were concerned about the attack surface this added to Firefox.
So, we laid down a challenge to the JPEG XL team at Google Research: Build a safe, performant, compact, and compatible JPEG XL decoder in Rust, and we’ll ship it. That challenge was met; Google Research built jxl-rs, and it’s the core of our JPEG XL support in Firefox.
Although Safari shipped JPEG XL in 2023, their implementation lacked some key features of JPEG XL – our favourite is progressive rendering, which is something we pushed for in the Rust implementation.
Progressive rendering means the image can render as it’s downloading.
Although the full image is 135 kB, with only a few kB downloaded the user can determine the subject of the image. Try the above demo image in a browser that supports JPEG XL & progressive rendering, like Firefox Nightly – move the slider to see how the image displays with just a portion downloaded.
JPEG XL vs AVIF
Browsers will now have two modern image formats for developers to choose from. Which you choose depends on your use-case.
JPEG XL: Excels at lossless imagery, progressive rendering, and further compressing JPEGs without quality loss.
AVIF: Excels at web-quality photographic images, and images that have a mix of sharp edges and flat surfaces.
For example:
The image above is a 116 kB AVIF with a quality score (SSIMULACRA 2) of 62.8, meaning medium-high quality. To get the same quality, the JPEG XL image would be 134 kB.
At a SSIMULACRA 2 score of 80 (very high quality), the AVIF is 227 kB, and the JPEG XL is 264 kB.
But at lossless, the AVIF is 1.76 MB, and the JPEG XL is 1.45 MB. A lossless WebP is 1.55 MB.
Another example is a screenshot of the Interop 2025 scores:
At a SSIMULACRA 2 score of 78 (very high quality), the AVIF is 11.6 kB, and the JPEG XL is 23.8 kB.
But at lossless, the AVIF is 164 kB, and the JPEG XL is 92 kB. A lossless WebP is 96 kB.
Although AVIF tends to produce smaller files at web-quality than JPEG XL, AVIF only has basic progressive rendering support. So, for very large images, it may be worth taking the filesize hit with JPEG XL.
The key is to test with a representative set of images for your site, at a quality that works best for your users, and remember to optimise for high density.
While using guest wifi during travels, I was trying to fetch some changes from a github remote and my git fetch is over SSH which happens over port 22. Most (TCP?) ports are blocked on public or hotel wifi, so with some help1 I learnt that Github serves SSH over 443 too.
While working on Writing the Docs: 2026 Edition,
I experimented a bit with updating the Glean Dictionary to
incorporate some of the ideas in the essay, in particular those around reference documentation.
As a sort of demonstration that documentation about an application can be
treated as a data product in and of itself, I hacked up a quick ETL pipeline to dump the JSON output of the Glean Dictionary into a DuckDB database that can be queried standalone.
Since the Glean Dictionary is just a static Netlify site, the DuckDB database can simply
be published alongside as a standard file.
This allows you to do fun things from the DuckDB console like:
From there, you could either build an interface like the Glean Dictionary itself (much easier to do from
a database than the somewhat harebrained dataclass soup I originally came up with) or any number
of other data products or analyses. Here's an example marimo notebook that tracks the metrics added
to each product over time:
As you can see, the number of metrics did a big jump in 2024 (I imagine they finally moved Firefox Desktop over to Glean) with slower and steadier growth since.
After nearly 4 years of active development, the next-generation trait solver is close to stabilization. We are enabling it by default on nightly to surface any remaining issues and plan to stabilize it in the next months. This is the largest single change to the Rust compiler since its initial release. It completely replaces how we prove where-clauses, normalize associated types, and much more. Please try out the latest nightly and open an issue if you encounter any bugs or regressions.
Even so, this already fixes a huge number of issues. As an underapproximation, we currently know of more than 200 issues on GitHub fixed by this change. This also has a significant impact on compile times; more on that later. When developing on nightly, you may accidentally rely on behavior only supported by the new trait solver.
This is an incredibly big change which results in a non-trivial amount of breakage. Most of these changes are intended improvements to type inference or the removal of undesirable behavior. We are tracking the known issues and breakage in a pinned GitHub issue.
What can I do?
Please update to the latest nightly version by using rustup update nightly and use it to test your existing projects and libraries.
Please tell us if you encounter any breakage, compile-time performance regression, or bad diagnostics. We have not yet spent too much time on error messages for the next-generation trait solver, so we would also appreciate you using this nightly for development to find poor diagnostics and other bugs in our error handling.
If you encounter any issue, take a quick look at the pinned GitHub issue to see if the affected crate is already listed, and if not, please open a new issue! To disable the next-generation trait solver on nightly, you can pass -Znext-solver=coherence to rustc, use RUSTFLAGS=-Znext-solver=coherence, or change your project's .cargo/config.toml configuration file:
[build]rustflags = ["-Znext-solver=coherence"]
What exactly does this mean?
We will go into more detail about the next-generation trait solver, how we got here, and what it changes when fully stabilizing it. This is a quick summary of its main impact.
impl Trait handling
The way opaque types — return-position impl Trait (RPIT), but also the unstable Type Alias Impl Trait (TAIT) and Return Type Notation (RTN) — are handled in the type system has nearly completely changed. This fixes a lot of bugs and edge cases with them and should make their behavior a lot more consistent in general. This change is why the next-generation trait solver is necessary to stabilize TAIT and RTN.
The implementation change mostly does not matter for RPIT as we special-cased impl Trait from the method signature when type checking the method body. This means the only way to observe the old behavior is via recursive function calls. The following snippet errors with the existing implementation, but compiles with -Znext-solver enabled: godbolt
fn foo(b: bool) -> impl Sized { if b { // The old implementation errored here. foo(false) + 1 } else { 0 }}
Associated types in higher-ranked types
The most impactful change is way we handle associated types referencing bound variables, i.e., lifetimes from a for<'a> binder, for example, the type for<'a> fn(<T as Trait>::Assoc<'a>). While most users don't encounter such types directly, there are widely used crates which do. This change impacts existing code by removing incorrect type inference, such as in bevy and minijinja.
It also fixes a bunch of unnecessary errors like in the following example: godbolt
trait OtherTrait { type Assoc<'a>;}impl OtherTrait for u32 { type Assoc<'a> = &'a u32;}trait Trait {}impl<T: OtherTrait> Trait for (T, for<'a> fn(<T as OtherTrait>::Assoc<'a>)) {}fn impls<T: Trait>() {}fn main() { // The old implementation failed to prove // the where-bound of `impls`. impls::<(u32, for<'a> fn(&'a u32))>();}
We've spent a lot of time on the compile-time performance of the next-generation trait solver. There have been many cases where it performed quadratically or even exponentially slower than the old solver.
Especially the last few weeks were mainly spent on improving performance. This work was shared by many people, with major contributions by Nick Nethercote, jana, Rémy Rakic, and mira.
As part of this effort, Rémy Rakic compared the performance of both implementations for the top 20,000 crates on crates.io. Below you is a visualization of the performance changes over the last two months.
On the left and the right, the major outliers can be found. Note that the sample of crates here is biased towards such crates, because those are more interesting to us. Nearly all crates we tested in the top 20k had effectively the same performance with both implementations.
This graph shows that we've mainly focused our efforts on the negative outliers and made significant progress there. While many of the crates that previously took more than twice as long to compile with the new solver are still slightly slower, our work has made a few of them actually compile faster than with the old solver.
We will continue to improve its performance over the coming months, and there are still a lot of optimization opportunities compared to the existing implementation. My expectation is that, in the long term, nearly all crates will benefit from the next-generation trait solver. I am especially excited about the huge performance benefits for some trait-heavy crates.
As an example, a Chess implementation in Rust's type system hangs with the old implementation while taking a minute with the new one. There are also more practical crates with huge performance benefits, e.g., the datafusion crate compiles more than 8x faster now. For more details about the recent performance work, see this blog post by jana.
There's a popular post going around about Alibaba doing WebAudio fingerprinting and in the process, mucking around with the author's Bluetooth headphones. Here's the tl;dr: browser fingerprinting is a far-too-pervasive method of tracking users across the web, but at least for WebAudio specifically, it's not very effective. Firefox has largely eliminated this fingerprinting vector.
I work on Firefox. Chrome, Brave, Safari probably have defenses against this. I'm pretty sure Chrome's WebAudio code was made approximately constant (like ours) many years ago. It probably still leaks CPU architecture though.
If you want to test Alibaba's WebAudio fingerprint, I had claude extract it into a standalone page. My value is sha256:9a388c0dd04cfdc54314f9d961c7e2d247b972067e28d1cea76bd6060cf1392e, and the other value we saw in an internal survey was sha256:16d3191880ce01f726015ec6a1f9a072a81ebd04bf489098d4685d1d1c0b2711.
99.24% of users belong to one of three values, and .76% of users had that data collection point fail (a value of zero.) So virtually all users have one of these three values but why are there three values??? Why isn't there one?? Well this is why we collected this telemetry - to ensure we really had made things constant the way we thought we had, and if we hadn't, figure out why and fix it.
The improvements we put into 118 eliminated a lot of differences and I wish I had a graph I could show you of what it looked like before (but I don't.) But what about these remaining three buckets? We were able to figure out that the differences between these are CPU-level differences, which is not surprising given the math operations of audio processing. Specifically one value comes from (all) x86 CPUs and x64 CPUs that lack fused multiply-add instructions, one value from x64 with FMA, and one value from CPUs with the NEON instruction set (ARM).
We followed up on that effort to collapse these buckets into one another. Bug 2036977 collapses the x64 (with FMA3) into the x86/x64 (without FMA3) bucket. Bug 2040494 is on file to collapse the remaining bucket into the NEON bucket but I haven't worked on it in a while because it's just not as high a priority as larger improvements we can make like Sanitizing the WebGL Renderer and Vendor (something I talked a bit about a few months ago).
Because if you've read this far you surely care about the rest of the graph also. There is also the long-tail of 23 other values belonging to 48 other users. This is very unfortunate, as it makes these users completely unique, but it is also not terribly unusual - computers are weird and these results could have been caused by bad RAM, a CPU bug, or possibly some crazy architecture (LoongArch??).
But at the end of the day, WebAudio fingerprinting is nearly useless. I don't expect browser fingerprinting to disappear from websites entirely (unless some regulatory action occurs, fingers crossed) - it's still going to be effective against a majority of users on the web, but at least for privacy focused browsers, it should be wildly less effective.
Open or closed AI isn’t a fringe question anymore; it’s a live policy debate, with real consequences for who gets to build, audit, and compete in the AI ecosystem. But as that debate plays out in Washington, Brussels, and beyond, the harder questions are still very much up for discussion. What does meaningful openness actually require? Where should the guardrails sit? And who gets a say in setting them?
That’s exactly the gap a group of us set out to close two years ago.
Back in 2024, Mozilla and the Columbia Institute of Global Politics brought together more than 40 researchers, builders, and policy experts for the Columbia Convening on Openness and AI. The goal was simple to state, but hard to do: figure out what “open” actually means once you’re talking about foundational models rather than traditional software, and build a shared vocabulary that researchers, developers, policymakers, and civil society could all work from.
The convening was the start of a years-long effort to turn a room full of perspectives on openness into something durable and useful for developers, builders, and policymakers alike. Recently, that effort reached a new milestone: Communications of the ACM published “Unpacking Open Source AI: Toward a Framework for Openness in Foundation Models,” which I co-authored alongside a host of other allies spanning academia, industry, and civil society.
The paper outlines a framework that does something the open source AI debate badly needs. It stops treating “open” as a single switch you flip on or off. Instead, it breaks the AI stack down into its component parts – data, code, model weights, documentation, and more – and looks at how openness at each layer shapes who actually gets to inspect, use, and build on a system. That kind of specificity matters. A lot of the current policy debate treats open source AI as a monolith, when in reality the details of what gets shared (and how) are what determine whether openness delivers on its promise of safety, competition, and accountability.
A few of the framework’s ideas are worth pulling out. First, it treats openness as a gradient rather than a binary. A system can be open on weights while remaining closed on training data, or open on code while offering little documentation on how it was evaluated. The framework offers language to describe that mix precisely, instead of lumping it under one vague label. Second, it argues that safety can’t be assessed at the model level alone: what matters just as much is the surrounding system – the deployment environment, the safeguards, the moderation layers, and governance structures. That’s because a model’s real-world risk profile is shaped by all of it together, not by the weights in isolation. Critically, the framework deliberately stops short of prescribing one “correct” level of openness for every system. Instead, it gives developers, researchers, and regulators a common vocabulary to make and evaluate those tradeoffs on a case-by-case basis.
It’s worth pausing on who’s behind this work. Scroll through the author list, and you’ll find a genuine cross-section of the individuals and organizations contributing to moving the development of open systems forward. It’s a collection of people who’ve spent years arguing, in good faith and often across real disagreements, that open approaches can be a foundation for safer, more democratic, more accountable AI. That’s the same spirit that drove the original convening, and it’s what makes this paper a genuinely important milestone for our mission to make AI systems accessible to the many, rather than the few.
You’ve probably heard about “ad blockers,” “tab managers,” “anti-trackers” or any number of browser customization tools commonly known as extensions. And maybe you’re intrigued to try one, but you’ve never installed an extension before and the whole notion just seems a bit vague.
Let’s demystify extensions.
An extension is simply an app that runs on a browser like Firefox. From serious productivity and privacy enhancing features to fun stuff like changing the way the web looks and feels, extensions give you the power to completely personalize your browsing experience.
Addons.mozilla.org (AMO) is a discovery site that hosts thousands of independently developed Firefox extensions. It’s a vast and eclectic ecosystem of features, so we’ve hand-picked a small collection of great extensions to get you started…
I’ve always wanted an ad blocker!
uBlock Origin
Works beautifully “right out of the box.” Just add it to Firefox and uBlock Origin will automatically start blocking all types of advertising — display ads, banners, video pre-rolls, pop-ups — you name it.
Of course, if you prefer deeper content blocking customization, uBlock Origin allows for fine control as well, like the ability to import your own custom block filters or access a data display that shows how much of a web page was blocked by the extension. More than just an ad blocker, uBlock Origin also effectively thwarts some websites that may be infected with malware.
I’m concerned about my privacy and tracking around the web
Privacy Badger
The flagship anti-tracking extension from privacy proponents at the Electronic Frontier Foundation, Privacy Badger is programmed to look for tracking heuristics (i.e. specific actions that indicate someone is trying to track you).
Zero set up required. Just install Privacy Badger and it will automatically search for third-party cookies, HTML5 local storage “supercookies,” canvas fingerprinting, and other sneaky tracking methods.
Consent-O-Matic
Not only will Consent-O-Matic automatically handle pop-up data consent forms (per GDPR regulations), but it’s brilliantly designed to interpret the often intentionally confusing language of consent pop-ups trying to trick you into agreeing to invasive tracking.
Developed by internet privacy researchers at Aarhus University in Denmark who grew sick of seeing so many deceptive consent pop-ups, Consent-O-Matic’s decision-making logic is built upon studying hundreds of pop-ups and identifying duplicitous patterns. So using this extension not only gives you a great ally in the fight against intrusive tracking, but you’re spared the annoyance of constantly clicking consent forms all over the internet.
I need an easier way to translate languages
Simple Translate
Do you do a lot of language translations on the web? If so, it’s a hassle always copying text and navigating away from the page you’re on just to translate a word or phrase. Simple Translate solves this problem by giving you the power to perform translations right there on the page.
Just highlight the text you want translated and right-click to get instant translations in a handy pop-up display, so you never have to leave the page again.
YouTube your way
Enhancer for YouTube
Despite offering dozens of creative customization features, Enhancer for YouTube is easy to grasp and gives you a variety of ways to radically alter YouTube functionality.
Once the extension is installed you’ll find an additional set of controls just beneath YouTube’s video player (you can even select the extension features you want to appear in the control bar).
Key features include…
Customize video player size
Change YouTube’s look with a dark theme
Volume boost
Ad blocking (with ability to allow ads from channels you choose to support)
One-click screenshots
Change playback speed
High-def default video quality
I’m drowning in browser tabs! Send help!
OneTab
You’ve got an overwhelming number of open tabs. You can’t close them. You need them. But you can’t organize them all right now either. You’re too busy. What to do?!
If you have OneTab on Firefox you just click the toolbar button and suddenly all those open tabs become a clean list of text links listed on a single page. Ahhh serenity.
Not only will you create browser breathing room for yourself, but with all those previously open tabs now closed and converted to text links, you’ve also freed up a bunch of CPU and memory, which should improve browser speed and performance.
If you’ve never installed a browser extension before, we hope you found something here that piques your interest to try. To continue exploring ways to personalize Firefox through the power of extensions, please see our collection of 100+ Recommended Extensions.
YouTube wants you to experience YouTube in prescribed ways. But with the right browser extension, you’re free to alter YouTube to taste. Change the way the site looks, behaves, and delivers your favorite videos.
Enhancer for YouTube
With dozens of customization features, Enhancer for YouTube has the power to dramatically reorient the way you watch videos.
While a bunch of customization options may seem overwhelming, Enhancer for YouTube actually makes it very simple to navigate settings and select just your favorite features. You can even choose which of your preferred features will display in the extension’s easy access interface that appears just beneath the video player.
Key features…
Customize video player size
Change YouTube’s look with a dark theme
Volume booster
Ad blocking (with ability to whitelist channels you OK for ads)
Take quick screenshots of videos
Change playback speed
Set default video quality from low to high def
Shortcut configuration
Enhancer for YouTube provides feature controls just beneath the video player.
Return YouTube Dislike
Do you like the Dislike? YouTube removed the display that reveals the number of thumbs-down Dislikes a video has, but with Return YouTube Dislike you can bring back the brutal truth.
“Does exactly what the name suggests. Can’t see myself without this extension. Seriously, bad move on YouTube for removing such a vital tool.”
Though its primary function is to automatically play all YouTube videos in their highest possible resolution, YouTube High Definition has a few other fine features to offer.
In addition to automatic HD, YouTube High Definition can…
Customize video player size
HD support for clips embedded on external sites
Specify your ideal resolution (4k – 144p)
Set a preferred volume level
Also automatically plays the highest quality audio
YouTube NonStop
So simple. So awesome. YouTube NonStop remedies the headache of interrupting your music with that awful “Video paused. Continue watching?” message.
Works on YouTube and YouTube Music. Now you’re free to navigate away from the YouTube tab for as long as you like and never worry about music interruption again.
YouTube Screenshot Button
If you take a lot of screenshots on YouTube, then the aptly titled YouTube Screenshot Button is worth your time.
You’ll find a “Screenshot” button conveniently located on the control panel of videos, or at the top of the screen on Shorts (or you can use custom keystrokes), so it’s always easy to snap a quick shot. Set preferences to automatically download screenshots as JPEG or PNG files.
Instant serenity for YouTube! Unhook strips away unwanted distractions like the promotional sidebar, end-screen suggestions, trending tab, and much more.
More than two dozen customization options make this an essential extension for anyone seeking escape from YouTube rabbit holes. You can even hide notifications and live chat boxes.
“This is the best extension to control YouTube usage, and not let YouTube control you.”
If you subscribe to a lot of YouTube channels PocketTube is a fantastic way to organize all your subscriptions by themed collections.
Group your channel collections by subject, like “Sports,” “Cooking,” “Cat videos,” etc. Other key features include…
Add custom icons to easily identify channel collections
Customize your feed so you just see videos you haven’t watched yet and prioritize videos from certain channels
Integrates seamlessly with YouTube homepage
Sync collections across Firefox/Android/iOS using Google Drive and Chrome Profiler
PocketTube keeps your channel collections neatly tucked away to the side.
AdBlocker for YouTube
It’s not just you who’s noticed a lot more ads lately. Regain control with AdBlocker for YouTube.
The extension very simply and effectively removes both video and display ads from YouTube. Period. Enjoy a faster, more focused YouTube.
SponsorBlock
It’s a terrible experience when you’re enjoying a video or music on YouTube and you’re suddenly interrupted by a blaring ad. SponsorBlock solves this problem in a highly effective and original way.
Leveraging the power of crowd sourced information to locate where — precisely — interruptive sponsored segments appear in videos, SponsorBlock learns where to automatically skip sponsored segments with its ever growing database of videos. You can also participate in the project by reporting sponsored segments whenever you encounter them (it’s easy to report right there on the video page with the extension).
SponsorBlock can also learn to skip non-music portions of music videos and intros/outros, as well. If you’d like a deeper dive of SponsorBlock we profiled its developer and open source project on Mozilla Distilled.
We hope one of these extensions enhances the way you enjoy YouTube. Feel free to explore more great media extensions on addons.mozilla.org.
On 2026-08-20 at 7:15 UTC we got a report that the proc-macro1 crate was malicious.
The Rust Security Response Team verified this to be the case: the crate had a build script that was downloading a malicious payload.
This crate proc-macro1 and others like it (proc-macro-en, aovine, arone, aronenao, tinymember) have been deleted.
Furthermore, we discovered that the popular arrayref crate had recently been republished and made to depend on this crate, with the most recent versions yanked. We have removed the malicious version and unyanked the maliciously-yanked versions. Other crates by that author (internment, append-only-vec) were also affected so we have done the same for those, and locked the account as a precaution. We do not believe the author of arrayref to be acting maliciously, but their computer or credentials are likely compromised, and we are attempting to contact them.
What you need to do
We recommend you check your local dependencies to ensure these crates were not pulled in.
Here are the malicious versions that we deleted from crates.io:
append-only-vec@0.1.9: published at 2026-08-20T07:37:49Z, deleted at 2026-08-20T09:25:24Z. Online for 107 minutes.
arrayref@0.3.10: published at 2026-08-20T07:15:00Z, deleted at 2026-08-20T08:41:40Z. Online for 86 minutes.
internment@0.8.7: published at 2026-08-20T07:34:07Z, deleted at 2026-08-20T09:04:11Z. Online for 90 minutes.
We'd like to thank the Research Team at Nextron Systems GmbH for initially discovering this and reporting it to us. We'd also like to thank Emily Albini, Manish Goregaokar, Marco Ieni, Tobias Bieniek, Ubiratan Soares, and Walter Pearce for participating in the response here.
The Rust team is happy to announce a new version of Rust, 1.98.0. Rust is a programming language empowering everyone to build reliable and efficient software.
If you have a previous version of Rust installed via rustup, you can get 1.98.0 with:
If you'd like to help us out by testing future releases, you might consider updating locally to use the beta channel (rustup default beta) or the nightly channel (rustup default nightly). Please report any bugs you might come across!
What's in 1.98.0 stable
Algebraic floating-point methods
The floating-point types f32 and f64 now have "algebraic" methods for addition, subtraction, multiplication, division, and remainder. These allow optimizations on these operations using the algebraic properties of real numbers, even though these properties do not hold with the limitations of floating-point representations. The exact set of optimizations is not specified, but may be similar to the kind of optimization you would see with the -ffast-math option in other languages.
For example, floating-point addition is not associative, so a sum like a + b + c + d must be evaluated in the left-associative order in which it is parsed, like ((a + b) + c) + d. If you write the same sum as a chain of algebraic_add calls, then the compiler is free to reorder it, perhaps like (a + b) + (c + d) to evaluate the partial sums simultaneously. Broader loop-vectorization is often enabled by using these algebraic methods as well.
These methods are non-deterministic, since the compiler is free to choose different optimizations, but they never cause undefined behavior. See the library documentation and the original API change proposal for more details.
Buffered integer formatting
All of the primitive integer types now have a format_into method that takes a &mut NumBuffer<Self> parameter, which is a buffer that is large enough to hold the decimal format of any value of that type. The buffer itself is opaque, but the method returns the formatted &str with a lifetime borrowed from that buffer.
This method also bypasses much of the dynamic dispatch that you would get with buffered write! formatting, which can be a boon to performance. The itoa-benchmark repo now shows that format_into performs similarly to itoa itself, so this could serve as a standard replacement for that dependency and others like it.
Fix interaction between ManuallyDrop and Box
Prior to Rust 1.96.0, there was a bug in the Rust compiler, which made the following code undefined behavior:
let mut x = ManuallyDrop::new(Box::new(1));unsafe { ManuallyDrop::drop(&mut x) };let x = x; // UB!
This is because the compiler considers it undefined behavior to move a Box that has been dropped (deallocated), and ManuallyDrop used to propagate that, such that moving ManuallyDrop<Box<_>> where the box has been dropped would also be considered UB.
In Rust 1.96.0 we fixed this, so this code was no longer UB. In this release we have updated the ManuallyDrop documentation, providing a stable guarantee that this code will continue to not be UB in the future. See ManuallyDrop docs and the related RFC 3336 for more information.
Some of you may have heard about this change from the announcement the team shared in early July, but Firefox is moving to a two-week release cycle. The first release on the new cadence is Firefox 155 on September 1, 2026, two weeks earlier than the originally planned September 15 release.
Why this is happening
If you’ve been following recent Firefox releases, you may have noticed that we’ve shipped multiple dot releases for several versions (up to six for Firefox 152). This new release cadence is designed to get bug fixes and completed features into users’ hands sooner, while making the release process more predictable.
It’s important to note that this doesn’t mean Firefox will ship twice as many features. Instead, we’ll be releasing updates more frequently, using a two-week rhythm instead of the current four-week cadence. For contributors, the biggest benefit is predictability: rather than waiting for an unpredictable series of dot releases, we’ll have a more consistent release schedule to plan around.
That said, it doesn’t mean dot releases will disappear entirely. They may still happen when needed, albeit not as often.
Here’s what to expect, how we’re preparing, and how you can help.
What it means for SUMO
Community Forum
On a typical Firefox release, we see an average of 30% increase in incoming support questions during the first 10 days. Under the new two-week release cadence, we expect these waves of questions will arrive more frequently.
The good news is that we’ve observed a consistent pattern after each release. Most questions fall into a handful of common categories, including UI changes (“Where did this go?”), lost data after updating, and crashes. We expect to see the same types of questions, just on a more frequent schedule, which gives us an opportunity to prepare ahead of each release.
Knowledge Base & Localization
A faster release cadence also means a faster content cycle. We expect that content requests will arrive on a more distributed timeline instead of every 4 weeks. But of course, this will also have a downstream impact on localization, as new and updated KB articles become available for translation more frequently. We recognize the additional pressure this could put on localization communities, and we’ll be monitoring the transition closely to make sure we’re mindful of contributor capacity.
Release preparation
We’ll be preparing a release wiki page every two weeks instead of every four. For now, our monthly Community Call will remain on its existing monthly schedule, though we’ll revisit that if the new release cadence creates a need for more frequent community updates.
How we’re preparing and how you can help
Here’s what we’re doing:
Community Forum: We’ll be adding and updating canned responses related to the most common post-release questions, including UI changes, lost data after updating, crashes, and other recurring issues. We’ll also continue to prepare the release wiki before each Firefox release so you’ll know what’s changing and what to expect.
Knowledge Base: The CX team is updating the Bugzilla content request template and collaborating with the product folks to make it easier for them to submit content requests and provide the information needed to create the content. We’ve also introduced a sumo-contributors keyword in Bugzilla to categorize requests that are open for contributors, making them easier to find and track.
Localization: We know the SUMO localization dashboard doesn’t currently have a priority indicator, so please use the release wiki as a guide to identify which content may need attention first. We’ll also explore ways to provide better visibility into upcoming content changes, giving localization communities more time to plan their work around the new release cadence.
Here’s how you can help:
Be extra active during the first 10 days after each release. That’s when we see the biggest wave of support questions, and your contributions have the greatest impact.
Use our common forum responses. They’ll help you reply more quickly and consistently. If you spot opportunities for improvement, please let us know in this thread! Your feedback will help make them even better for future releases.
Get involved in the KB content request process. With content requests arriving more frequently, we’ll need more contributor participation to help create, update, and review support content. Keep an eye on Bugzilla requests tagged with sumo-contributors for opportunities to get involved.
Keep an eye on the release calendar for localization work. Localization work will likely arrive on a more distributed schedule rather than being concentrated every four weeks. Following the release calendar can help you anticipate when new or updated content may be ready for localization. But of course, be sure to contribute at a pace that works for you.
Looking after each other
We also want to acknowledge that contributor burnout is a real risk when the quieter periods between releases become shorter. We’ll be monitoring the transition closely and adjusting as we learn. Most importantly, you should never feel like you have to be “on” all the time. Every contribution, no matter how big or small, makes a difference.
The first major test of this new cadence will likely come with Firefox 157, when Project Nova is expected to roll out more broadly. We’ll treat that release as an opportunity to learn what works, identify where we need to improve, and fine-tune our approach together.
Thank you for everything you do to support Firefox users. This transition is only possible because of our contributor community. If you have any questions, concerns, or ideas, we’d love to hear them. Join our Community Call where we’ll also discuss more about this change.
A concorrência é o ponto forte da internet. Com a possibilidade de as pessoas escolherem navegadores, mecanismos de pesquisa e aplicativos livremente, a concorrência entre das empresas se baseia no mérito. No entanto, os mercados digitais estão concentrados em “guardiões” que controlam a descoberta, dificultando o alcance de usuários por desenvolvedores independentes. A fiscalização tradicional acabou se tornando ineficaz, normalmente sendo muito tardia. Agora, governos do mundo todo estão adotando novas ferramentas para garantir um mercado aberto e contestável.
O projeto de lei (PL) 4675/2025 é um passo importante nessa direção. Baseando-se na DMA (Digital Markets Act) da União Europeia e na DMCCA (Digital Markets, Competition and Consumers Act) do Reino Unido, esse projeto de lei aborda questões de concorrência sistêmica voltadas à realidade do mercado brasileiro. A Mozilla é a favor dessa legislação, que visa criar uma estrutura segmentada de concorrência para os mercados digitais brasileiros.
A concorrência possibilita produtos melhores e liberdade de escolha
Há vinte anos, a Mozilla desenvolve o Firefox como um navegador independente, priorizando a privacidade, a segurança e a escolha. Operamos no Gecko, um dos três mecanismos de navegador existentes no mundo. A independência é essencial para evitar dominância no mercado e garantir que os usuários tenham liberdade de escolha. A inovação não é suficiente. Os produtos precisam de oportunidades justas de concorrência sem barreiras de pré-instalação ou interoperabilidade.
O PL 4675/2025 trata dessa questão por meio de uma estrutura ex ante, permitindo que a autoridade relevante mitigue os riscos antes de se tornarem irreversíveis. O anteprojeto mais recente contém melhorias importantes dessa estrutura. Ele determina as obrigações de acordo com produtos ou serviços específicos, em vez de aplicá-las automaticamente a todo um grupo corporativo; define proteções processuais durante todo o processo de designação; e traça limites mais claros sobre a capacidade da autoridade de fazer algo as obrigações além daquelas estabelecidas na legislação. De forma mais notável, ele determina uma arquitetura de escolha “isonômica e não discriminatória”, incluindo telas de opções para selecionar, instalar ou definir produtos de terceiros como padrão.
A experiência da Mozilla com telas de escolha de navegador, em conformidade com a DMA da União Europeia, mostra que essas disposições funcionam. O Firefox foi o navegador de escolha mais de seis milhões de vezes. A probabilidade de as pessoas que escolheram o Firefox nessas telas continuarem usando o navegador é cinco vezes maior. Ao tornar a estrutura segmentada e previsível, o PL 4675/2025 estabelece a base para um ecossistema de concorrência em que a inovação impulsiona o sucesso.
Qual é o benefício da concorrência para as pessoas
A política de concorrência defende as pessoas. Mercados abertos permitem a liberdade de escolha e o sucesso de empresas menores. Críticos argumentam que essas propostas prejudicam a inovação, mas nossa experiência sugere o contrário. O Gecko, mecanismo de navegador do Firefox, continua sendo o maior mecanismo não controlado por uma operadora dominante de sistema operacional. Essa independência nos permite priorizar inovações voltadas aos usuários, como proteções avançadas de privacidade e segurança.
Decisões de design, como padrões pré-instalados e barreiras de interoperabilidade, moldam significativamente a experiência de usuários. A pesquisa Over the Edge 2.0 da Mozilla destaca como essas práticas afetam a liberdade de escolha. Startups também se beneficiam, pois podem alcançar usuários e concorrer com base no mérito, em vez de depender de decisões de plataformas dominantes. O projeto de lei brasileiro promove essas condições ao proporcionar ao Cade (Conselho Administrativo de Defesa Econômica) as ferramentas para tratar de práticas anticoncorrenciais, garantindo que a concorrência de plataformas dominantes ocorra por meio de melhoria da qualidade do produto, não por controle da infraestrutura.
De olho no futuro
Os mercados digitais evoluem, mas os princípios de concorrência justa (abertura, liberdade de escolha, interoperabilidade e transparência) continuam iguais. O PL 4675/2025 transforma esses princípios em normas aplicáveis. Seu modelo ex ante segmentado e suas proteções processuais posicionam o Brasil entre os países que visam restaurar o equilíbrio do mercado. Por fim, o sucesso da estrutura será medido por sua capacidade de proporcionar uma mudança significativa para os usuários.
A Mozilla é a favor desse projeto de lei e se dispõe a colaborar com o poder legislativo, o Cade e todas as partes interessadas. Com alterações segmentadas, o PL 4675/2025 pode se tornar uma estrutura duradoura a favor da concorrência, da inovação e da liberdade de escolha.
Competition is a strength of the internet. When people freely choose among browsers, search engines, and apps, companies compete on merit. However, digital markets have concentrated around ‘gatekeepers’ that control discovery, making it harder for independent developers to reach users. Traditional enforcement has proven ineffective, often arriving too late. Governments worldwide are now adopting new tools to ensure open, contestable markets.
Brazil’s Bill 4,675/2025 is a critical step in this direction. Drawing lessons from the EU’s Digital Markets Act and the UK’s Digital Markets, Competition and Consumers regime, the bill addresses structural competition concerns with an approach calibrated to Brazil’s market realities. Mozilla strongly supports this legislation, which aims to establish a tailored competition framework for Brazil’s digital markets.
Competition unlocks better products and meaningful choice
For over twenty years, Mozilla has built Firefox as an independent browser prioritizing privacy, security, and choice. We operate on Gecko, one of only three browser engines worldwide. Maintaining independence is critical to preventing market dominance and ensuring users have genuine choices. Innovation alone isn’t enough; products need fair opportunities to compete without being hindered by preinstallation or interoperability barriers.
Bill 4,675 addresses this via an ex ante framework, allowing Brazil’s competition authority to mitigate risks before they become irreversible. The latest draft improves this framework in several important ways. It tailors obligations to specific products and services rather than automatically applying them across an entire corporate group, strengthens procedural safeguards throughout the designation process, and places clearer limits on the authority’s ability to expand obligations beyond those established in legislation. Most notably, it requires “neutral and non-discriminatory” choice architecture, including choice screens, for selecting, installing, or setting third-party products as defaults.
Mozilla’s experience with browser choice screens under the EU Digital Markets Act proves these provisions work. Firefox has been selected more than six million times, and users who select Firefox through these screens are five times more likely to continue using it. By making the framework targeted and predictable, Bill 4,675 establishes a foundation for a competitive ecosystem where innovation drives success.
How competition delivers for people
Competition policy is about people. Open markets provide genuine choice and allow smaller players to thrive. Critics argue these proposals harm innovation, but our experience suggests the opposite. Gecko, Firefox’s browser engine, remains the only major engine not controlled by a dominant OS operator. This independence enables us to prioritize user-focused innovations like advanced privacy and security protections.
Design decisions, like preinstalled defaults and interoperability barriers, significantly shape the user experience. Mozilla’s Over the Edge 2.0 research highlights how these practices undermine choice. Startups similarly benefit when they can reach users and compete on merit rather than relying on dominant platform decisions. Brazil’s bill can foster these conditions by providing CADE with tools to address anti-competitive practices, ensuring dominant platforms compete by improving product quality rather than leveraging infrastructure control.
Looking ahead
Digital markets evolve, but healthy competition principles (openness, choice, interoperability, and transparency) remain constant. Bill 4,675 translates these into enforceable rules. Its tailored ex ante model and procedural safeguards position Brazil among jurisdictions restoring market balance. Ultimately, the framework’s success will be measured by its ability to deliver meaningful change for users.
Mozilla supports this bill and looks forward to collaborating with lawmakers, CADE, and stakeholders. With targeted refinements, Bill 4,675 can become a durable framework that promotes competition, supports innovation, and empowers people with greater choice.
Gamers have asked for GeForce NOW support for years. Today, NVIDIA made it official, opening up GeForce RTX-powered play to Firefox on Windows.
Firefox users can now stream more than 2,000 PC games from virtually anywhere, no downloads, installs, or hardware upgrades required, just a Windows PC and a browser.
Gaming: one of the web’s toughest tests
Cloud gaming pushes a browser in ways most websites never do. Every click and frame matters. Behind today’s announcement is months of collaboration and engineering between Mozilla and NVIDIA to deliver GeForce NOW on Firefox for Windows.
Now, players can jump into high-performance PC gaming directly from Firefox, no waiting on lengthy game downloads, installs, or updates. The experience delivers GeForce RTX-powered performance at up to 1440p and up to 120 frames per second for GeForce NOW Ultimate members.
“Firefox earned its place on our list of supported browsers by delivering the first-class experience GeForce NOW players expect. We set a high bar for browser support, and we’re excited to welcome Firefox — giving millions of Firefox fans a new way to stream the games they love,” said Andrew Fear, Director of NVIDIA GeForce NOW.
Versatility and customization baked into your gaming rig
Gamers put real effort into making their rigs their own, and Firefox gets that. Users can choose themes, custom colors, and tab settings to customize their setup, instead of sitting there like just another window.
We also know online gaming doesn’t happen in just one window. It’s social and sometimes spontaneous. With Firefox, you can have a Discord call running in Split View, a guide open in another tab, or Reddit pulled up between matches. Then go full screen when you’re ready to play, no need to switch browsers to stream games.
“Teaming up with NVIDIA to bring GeForce NOW to Firefox is a milestone moment — one of the world’s leading cloud gaming services, now running on a browser built for privacy, control and flexibility. This is a big win for the Firefox community and for NVIDIA’s gaming community — and a sign of even bigger things ahead,” said Ajit Varma, Head of Firefox.
If Firefox is already your browser of choice, online gaming and your PC game library can join the party. Whether your library lives on Steam, Epic Games Store, GOG, Xbox PC Game Pass, or Ubisoft Connect, you can sign in, open your library, and start streaming the games you already own. For all the gamers returning to Night City in Cyberpunk 2077, jumping into Halo: Campaign Evolved, or dropping in for a quick round of Fortnite, Firefox users can now play where you want.
Try it today
Update to the latest version of Firefox, go to play.geforcenow.com, and sign in with your GeForce NOW account.
Join us August 25 as NVIDIA heads to Gamescom, where we’ll have more to share about what this partnership means for gamers.
Firefox users were choosing Startpage long before today — to the tune of more than a billion searches a year, every one of them required some assembly: an extension, a manual setting, a workaround.
Today, starting with Firefox 154, that choice becomes as easy as head to the drop-down menu, hit ‘select,’ and start searching. Startpage is now a built-in search option for Firefox users on desktop in Germany, France, Austria, Switzerland, and the Netherlands. Android and iOS are coming soon. Whether you want to search with Startpage, or another preferred search engine, it’s as easy as opening your search settings, picking a default, and done.
And if you’re happy with your current search engine, nothing about your setup changes.
Why Europe first
This launch starts in Startpage’s home markets: a Netherlands-based search engine, now built into the browser for some of the most privacy-conscious users in the world. At a moment when so much of the web experience is decided by a handful of very large companies, a search option that’s private by design and European by origin isn’t a small thing.
What Startpage delivers
Startpage delivers full, high-quality search results without the privacy trade off. Queries aren’t stored or linked to you, and there are no AI answers pushed above your search results. In fact, there’s no AI at all. Based in the Netherlands, Startpage built its product around a simple idea: great search and personal privacy can go hand in hand.
“So much of your web experience is prescribed before you ever open a browser. We’d rather you decide how you want to search. Adding Startpage puts a genuinely private search engine option — real results, zero profiling, AI-free — one click away for millions of people in Europe,” said Ajit Varma, Head of Firefox.
Users asked with one billion searches
Startpage ranks among the most-requested search engines in the Firefox community. When demand is this clear, our job is to remove the friction.
“More and more of what people use online comes from a handful of very large companies, and search is where that concentration gets felt most directly. Firefox has always been the browser for people who want to make their own decisions about the web, which makes it a natural home for private search. Firefox users already run over a billion Startpage searches a year. Now Startpage is built in for everyone in these markets,” said Stewart Marlborough, President of Startpage.
That’s the pattern we want: people who use Firefox every day tell us what they need, and we ship it.
Search is a choice. Firefox treats it like one.
Most browsers have already decided how you’re going to search. Firefox hasn’t. Pick your search engine, control what happens to your queries, decide who sees data about you, even turn AI on or off. It should always be your call. Not everyone wants the same thing from search, and a browser shouldn’t pretend they do.
Try it out
If you’re in Germany, France, Austria, Switzerland, or the Netherlands, update to Firefox 154 and you’ll find Startpage in your search settings.
Update on September 16, 2026: Smart Window is now rolling out in France, marking its first expansion beyond North America. People in France will be able to download and try the Smart Window beta in French. Download Smart Window here and share your feedback with us on Mozilla Connect.
Original post from August 2026:
Browsers make it easy to start things, but picking them back up is another story.
We start planning a trip or researching a purchase, and before long we’re comparing options and chasing ideas across dozens of tabs. That work rarely happens in one sitting. When we come back after an interruption, we have to figure out where we were, what we’d already found, and what we were trying to do in the first place.
Smart Window is Firefox’s privacy-first, AI-powered browsing experience designed to help people finish what they start online. It works with the context you choose to share, such as your open tabs and relevant browsing history, so you can get back to what you were doing without retracing your steps.
We’ve spent the last several months building and testing Smart Window in beta with our community. Today, we’re adding new capabilities that help you check answers without losing your place, make sense of open tabs and get back to things you’ve seen before. Together, they help keep a task moving across tabs, searches, and time.
“The browser already has much of the context around what you’re trying to do — the research in your tabs, the pages you’ve visited, the things you’ve found along the way,” said Ajit Varma, Head of Firefox. “With Smart Window, we’re exploring how to make more of that context useful while keeping you in control.”
What’s new in Smart Window
Check answers without losing your place
When you have a question in the middle of a task, getting an answer shouldn’t take you out of your flow or require you to track down the sources separately.
Through our new partnership with Exa, Smart Window can now retrieve current web information and show the sources behind its response without taking you to a separate search results page. Learn more about why we chose Exa and what the partnership means for Firefox in our companion post.
Group tabs that belong together
It doesn’t take long for a quick search to turn into a browser full of tabs. Once they pile up, keeping track of everything becomes even more work.
Smart Window can now suggest groups for related tabs, making it easier to organize what you have open and return to it later. It can also spot duplicate tabs and close them with a click.
Find your spot again
Sometimes you remember what was on a page better than you remember what it was called or how you got there. Smart Window can now show visual previews of pages in your browsing history, making it easier to spot the page you’re looking for among similar results without opening each one to figure out which is which.
Behind the evolution
Last November, we shared an early concept called “AI Window,” exploring what it could look like to give people a user-controlled space where they could chat with an AI assistant to get help while browsing. We shared it early because we wanted our community to help shape where it went next.
Over the months that followed, we watched how people used the experience, listened to feedback, and tested new ideas. A consistent theme emerged: people were increasingly using it as part of their everyday browsing — searching, navigating, and working through the things they’d come online to do. The value of the AI assistant came through in how it helped them make progress on those tasks.
We saw the same idea in feedback from beta users. One described using Smart Window to keep track of their “train of thought.” Another used it to find something they’d looked at before without remembering exactly where they’d seen it.
Those learnings helped us shape Smart Window into a broader browsing experience that helps people make progress on what they came online to do.
While the product is evolving, the principles we started with remain the same: choice, privacy, and transparency. Smart Window is optional. You choose when to use it, what browsing context it can use to help with a task, and which AI model you want to use. Firefox’s AI Controls gives you one place to manage Smart Window, including turning it off entirely, so you can easily choose the browsing experience you want.
What’s next
We’re continuing to explore ways Smart Window can help carry a task forward, especially when you leave it and come back later.
Soon, Smart Window will be able to surface recent browsing journeys and pull together related tabs and history, giving you a starting point when you return to something you were working on. We’re also working on ways for Smart Window to use relevant information to help fill out online forms, so you don’t have to re-enter the same details again and again. You’ll stay in control of what Smart Window can access, including which tabs you choose to share with it.
Smart Window remains in beta, and we’ll keep learning from our community as these experiences develop. It’s currently available in English to people in the U.S. and Canada. If it’s not available where you are yet, you can sign up to be notified when it is.
AI has changed how we browse. Full stop. The real question is whether AI leads to one browser experience for everyone, or gives people more ways to make the browser work for them.
Firefox was always built to give users an alternative to the status quo, and our approach with AI is no different. Much of the industry is going in another direction: Company A builds the browser → and the search engine → and the AI model → and all the surrounding services. The seduction lies in how effortless every layer feels, but it also means one company has total influence over what tech you can use and what AI delivers.
We aim to deliver users a different model: one where AI makes your browser empowering and helpful, with visible citations and with a zero-data-retention commitment, all powered by an independent browser engine. To get there, we’re partnering with people who align with the same open, choice-first thinking that’s shaped Firefox from day one.
Today, that starts with Exa.ai, a search and retrieval company built for the AI era.
Going forward, Exa will help power Smart Window on desktop and Quick Answers on iOS, giving people a way to get current, source-backed answers without leaving the page. More on our related Smart Window announcement here.
But our Exa news isn’t about one feature or product. It’s about model choice and how people find things online.
An independent AI model
Mozilla has always believed the web is strongest when it encourages technology competition and variety, and we think the same principle should apply to AI. We want to create an AI ecosystem that is open, diverse, and grounded in the same values we champion for the web. So, instead of building our own closed AI stack, Firefox is investing in partnerships with companies like Exa.ai to bring deep expertise in specific areas while sharing our commitment to user choice, privacy, and transparency.
As Ajit Varma, Head of Firefox, puts it, “Firefox’s philosophy is straightforward: the open internet is a critical resource and people should be able to shape it to their needs and preferences — even as new entry points like AI emerge. AI should be responsible. It should stay transparent and under your control. AI shouldn’t be an-all-or nothing offering, but rather built so users can pick and choose the model or system that works for them.”
The idea is simple: Mozilla builds the browser people trust, and partners like Exa.ai bring the specialized pieces that make it better. That lets us move faster without asking people to give up what made Firefox different in the first place.
Adds Will Bryk, Co-founder and CEO of Exa.ai, “Search built for the AI era doesn’t work if it’s locked inside one company’s stack. Firefox is one of the last browsers that isn’t trying to own the model, the search, and the browser all at once. That’s why this partnership makes sense to us. We’re building the information layer for an agentic web, where trust and transparency are paramount. We share those values with Firefox, making this partnership a very easy call.”
AI should make the web more useful, not replace it
AI is only as useful as your ability to check its work.
That’s the point of building Exa’s retrieval into Firefox: when you get an answer, you can see the source it came from. Nothing is buried in a ‘citations’ menu, but sitting right there so a two-second glance tells you whether to trust it or read more. We’re not forcing you ‘just trust us’ that it’s right.
It’s a small design choice, but it matters. It’s the difference between an AI that tells you things and one that shows you where to look. It also means the people who actually wrote that content don’t disappear from the picture, the way they often do when AI summarizes and moves on.
Looking ahead
This won’t be the last partnership like it. We’re picking partners for the same reason each time: people who think AI in a browser should work for you, not the other way around.
WebDriver is a remote control interface that enables introspection and control of user agents. As such, it can help developers to verify that their websites are working and performing well with all major browsers. The protocol is standardized by the W3C and consists of two separate specifications: WebDriver classic (HTTP) and the new WebDriver BiDi (Bi-Directional).
This newsletter gives an overview of the work we’ve done as part of the Firefox 154 release cycle.
Contributions
Firefox is an open source project, and we are always happy to receive external code contributions to our WebDriver implementation. We want to give special thanks to everyone who filed issues, bugs, and submitted patches.
Firefox 154, one WebDriver bug was fixed by a contributor:
A bug comes in, or someone shows me a page doing something surprising, and the question is always the same one. Is that what the spec says? Not what we all assume it says, and not what Gecko happens to do, but what the algorithm actually does when you follow it step by step. So I open html.spec.whatwg.org, find the entry point, and start reading. Twenty tabs later I have usually lost the thread.
This isn’t an occasional chore. I do it when I’m implementing something new, when I’m working out whether a Gecko bug is a bug in Gecko or a bug in the spec, when I’m reviewing a spec change someone else has proposed, and when I’m trying to design something that has to fit alongside everything that already exists. Four fairly different jobs, and every one of them comes down to the same mechanical work. Start at an algorithm, follow the calls, keep track of where you’ve been.
The specs are built for exactly this, in principle. Every step that invokes another algorithm is a hyperlink, and the whole thing is one large call graph spread across HTML, DOM, Fetch, URL and Infra. The trouble is that walking that graph by hand is slow, and it’s the kind of slow a machine should be doing on your behalf.
Two tools have changed how I do this. One answers questions about the graph, and the other helps me walk it. If you’d rather install them first and read afterwards, they’re both at the end.
webspec-index trace
webspec-index is Jan Jaeschke’s tool for querying web specifications from the command line. It indexes the specs, on demand as it needs them, and lets you ask about definitions, references and IDL. In August it gained a trace subcommand, and that’s the one I keep reaching for.
You give it two anchors and it finds the routes between them. It answers in JSON by default, which is the right choice for feeding it into something else but not for reading, so add --format markdown when the audience is you. Say I want to know how a navigation can end up firing navigateerror:
# trace: `HTML#navigate` -> `HTML#event-navigateerror`
Max depth 6, kind `step`. Found 11 trace(s).
## Trace 1 (5 hop(s))
1) [`HTML#navigate` step 20](…#beginning-navigation:set-the-ongoing-navigation)
calls `HTML#set-the-ongoing-navigation`
> Set the ongoing navigation for navigable to navigationId.
2) [`HTML#set-the-ongoing-navigation` step 2](…#aborting-navigation:inform-the-…)
calls `HTML#inform-the-navigation-api-about-aborting-navigation`
> Inform the navigation API about aborting navigation given navigable.
3) [`HTML#inform-the-navigation-api-…` step 3.1](…#ongoing-navigation-tracking:…)
calls `HTML#abort-the-ongoing-navigation`
- under: While navigation's ongoing navigate event is not null:
> Abort the ongoing navigation given navigation.
4) [`HTML#abort-the-ongoing-navigation` step 7](…#ongoing-navigation-tracking:…)
calls `HTML#abort-a-navigateevent`
> Abort event given error.
5) `HTML#abort-a-navigateevent` step 6 calls `HTML#event-navigateerror`
> Fire an event named navigateerror at navigation using ErrorEvent, with
additional attributes initialized according to errorInfo.
I’ve wrapped those lines and shortened the URLs to fit; in the real output each hop is one long line and every link is a full deep link to that exact call site.
Every hop names the exact step number, quotes the step text, and tells you the condition it sits under. That last part matters more than it looks. Step 3.1 only runs while the ongoing navigate event is non-null, and knowing that is the difference between a path that exists on paper and a path your case actually took.
Eleven routes, though1. Reading eleven of these back to back is not much better than the twenty tabs.
Three zoom levels
This is where webspec-index trace gets genuinely nice, and it’s the part I want to draw attention to, because it’s easy to miss in the help text. The --detail flag changes how much of each route you get, and the three levels turn out to be three different ways of working rather than just three verbosity settings.
Ask the same question again with --detail edges and the prose falls away, leaving the skeleton:
Now you can read all eleven at once, and a shape appears that I could not see in the verbose output at all. There are five places inside navigate where a route starts:
There are exactly two ways into that step, from HTML#abort-the-ongoing-navigation step 7 and from HTML#process-navigate-event-handler-failure step 5. Eleven routes exist because three of the five entry points re-enter the same navigate event firing machinery from different directions, not because there are eleven genuinely different things going on.
That’s a useful thing to know before you start debugging. If a navigation is firing navigateerror and you want to find out why, you don’t instrument eleven places. You instrument the one step they all pass through and work backwards from there.
So the way I use it now is to start at --detail edges to find the shape, then drop back to the default once I know which route I care about and want to read the reasoning. The third level, --detail compact, drops the prose but keeps every anchor as a deep link to the exact call site, which is the form you want when you’re pasting a route into a bug report for someone else to follow.
WebSpec Tracer
webspec-index trace answers a specific kind of question, and it’s worth being precise about which kind. You have to know both ends. That’s fine when you’re asking whether one thing can reach another, but a lot of the time I only know where I’m standing. I have a starting point, a bug in front of me, and no idea yet where the algorithm goes.
There’s also something webspec-index trace can’t do for you in principle. It finds routes through the spec text, statically. It doesn’t know which branch your case took, because that depends on what actually happened at runtime, and only you have that information.
So I wrote WebSpec Tracer, a Firefox extension that walks the specs with you rather than ahead of you. You give it a starting anchor and it shows you that algorithm with every linked term highlighted. Click one and it becomes the next hop in the trace, and the panel moves you into it. Click the wrong one and Back undoes it.
The screenshot is a walk that started at location.assign and has arrived inside navigate. Step 15 is the interesting one. It runs only if four things are all true, that there’s no document resource, no response, the URL matches the current entry’s URL ignoring fragments, and the fragment is non-null. If all four hold, it navigates to a fragment and returns. Otherwise the algorithm keeps going into the full navigation path below.
No tool can decide that for me. Whether my bug went left or right at step 15 depends on the page and on what the user did. But the extension puts the decision in front of me with the alternatives visible, which is precisely what I was failing to do for myself with twenty tabs open.
The trace builds up in the panel underneath as markdown, with every anchor pointing at the exact call site. That box is a display rather than a text field, so there are buttons for getting the trace out of it. Copy does what you’d expect. Insert is the one I actually use, and it’s the reason the extension lives in the sidebar: it writes the markdown straight into whichever field you have focused on the page, so you can have a spec issue open next to the panel and drop the trace into it without going near the clipboard. Reset clears everything and starts over.
Switch the issue over to Preview and there are the same two hops, rendered, each one a link into the spec. That’s most of the reason I built the thing. Explaining a route through an algorithm in prose is miserable, and the version you retype by hand is always slightly wrong. This way what I hand over is exactly what I walked.
One more thing worth knowing, about the anchors themselves. The starting one has to say which spec it’s in, so HTML#dom-location-assign rather than just dom-location-assign, but after that the extension works it out as it goes. Anything that turns up in the trace without a prefix is in the spec you started from, and a prefix appears when the trace crosses a boundary:
That’s the same walk carried a few hops further. Hop 3 is that step 15 decision, taken, and the last line is WEBIDL#wait-for-all. Somewhere in the navigate event firing the trace left HTML entirely, and the prefix is the only thing that tells me so. The panel on the left has stopped showing me HTML too, and is now sitting in WebIDL. That’s easy to lose track of when you’re clicking through by hand, and it’s usually the moment a question stops being about HTML and starts being about something else.
When one call happens twelve times
Sometimes an algorithm invokes another one from many different places, and a trace has to say something sensible about that. This was in the design from the start, and the answer it arrived at is to do what the spec already does. Start at HTML#update-the-image-data and follow it to HTML#abort-the-image-request:
HTML#abort-the-image-request is invoked from twelve separate places inside HTML#update-the-image-data. The extension doesn’t make me choose one, and it doesn’t flatten them into a single link either. It records the hop once and hangs all twelve call sites off it as numbered links, so the line reads #update-the-image-data calls #abort-the-image-request, [2], [3] and onwards to [12], each number pointing at its own anchor.
The numbering isn’t invented. It’s the spec’s own scheme for repeated references: the anchors run #abort-the-image-request, then -2, -3, and so on up to -12. All the trace does is carry that through, so a hop in the output identifies call sites the same way the spec identifies them, and the numbers mean the same thing in both places.
That also keeps the trace honest. The hop happened, and that’s true whichever of the twelve fired, but the fact that there are twelve is worth knowing on its own, and anyone reading can go and check any one of them. Writing this out by hand you would link the first and lose the other eleven without ever noticing. The same thing is visible in the previous screenshot, where hop 3 reads #navigate calls #navigate-fragid, [2], [3].
webspec-index trace deals with the same situation the other way round. Ask it the same question and you get twelve separate one hop traces, each naming its own step number, step 2, then 7.4.2, then 11.1, and so on down the algorithm. Neither is wrong. The command line is telling you which steps, and the extension is keeping your trace to one line while preserving every place it could have come from.
Which one, when
They divide up cleanly enough that I don’t think about it much any more. If I know both ends and want to know what’s between them, or how many different routes there are, that’s webspec-index trace. If I know where I’m starting and want to find out where it goes, that’s the extension.
The one I underused at first was --detail edges. Asking a broad question and then zooming out far enough to see the answer’s shape is a different move from following a single path carefully, and it’s the one that has surprised me most often, usually by showing me that several things I thought were separate all funnel through the same step.
Getting them
webspec-index is on crates.io:
cargo binstall webspec-index
It builds its index as it goes, so the first trace into a corner you haven’t visited before pauses briefly to fetch and index the specs the route touches. After that it’s fast.
WebSpec Tracer is on addons.mozilla.org, and the source is on GitHub. It lives in the sidebar, toggled with Ctrl+Shift+U, so you can keep it open next to whatever you’re reading.
Both are worth a try if you spend any time at all reading specs, whether you’re implementing them, arguing with them, or just trying to find out whether the browser is wrong or you are.
Notes
Eleven is what you get at the default maximum depth of six hops. Raise it and there are more. ↩
Planet Mozilla
Collected here are the most recent blog posts from all over the Mozilla community.
The content here is unfiltered and uncensored, and represents the views of individual community members.
Individual posts are owned by their authors -- see original source for licensing information.