diff --git a/text/0000-deprecate-readonly-helper.md b/text/0000-deprecate-readonly-helper.md new file mode 100644 index 0000000000..8c5f1e8093 --- /dev/null +++ b/text/0000-deprecate-readonly-helper.md @@ -0,0 +1,153 @@ +--- +stage: accepted +start-date: 2026-10-02T00:00:00.000Z +release-date: +release-versions: +teams: # delete teams that aren't relevant + - framework + - learning +prs: + accepted: # update this to the PR that you propose your RFC in +project-link: +--- + + + +# Deprecate the `readonly` template helper + +## Summary + +Deprecate the `{{readonly}}` template keyword. It has been marked `@private` in the API docs since 2016, but it was never deprecated and still works, which makes it intimate API. This RFC deprecates it so it can be removed after the next LTS. + +## Motivation + +`readonly` exists to opt out of two-way bindings when passing a value into a classic component (`import Component from '@ember/component'`): + +```hbs +{{my-child count=(readonly this.total)}} + +``` + +Without `readonly`, a classic component that calls `this.set('count', ...)` writes the new value back up to the caller. With it, the write stays local to the child. + +That is the only thing `readonly` does, and it only matters for classic components: + +- Glimmer components (`@glimmer/component`) and template-only components cannot set their arguments, so `readonly` is a no-op for them. +- Plain functions used as helpers, and any other helper result, are already read-only references. +- [RFC #1216](https://github.com/emberjs/rfcs/pull/1216) deprecates the classic component class, which is the last thing in the framework that supports two-way bindings. + +Meanwhile `readonly` still costs something: + +- It is one of the few built-in keywords still recognized in strict mode (`STRICT_MODE_KEYWORDS` in `ember-template-compiler`), alongside `mut` and `unbound`. +- It sits in an odd state: hidden from the API docs since 2016 ([emberjs/ember.js#21549](https://github.com/emberjs/ember.js/issues/21549)), yet working, untaught, and still showing up in older apps and addons. Developers who find it in a codebase have no documentation and no guidance on whether to keep it. + +Deprecating it resolves that state and lets the keyword be removed along with the rest of the two-way binding machinery. + +## Transition Path + +### What is deprecated + +Any use of the `readonly` keyword in a template, in both loose mode (`.hbs`) and strict mode (`