Skip to content

refactor: retire @action and get() from @ember/object - #613

Open
josemarluedke wants to merge 4 commits into
mainfrom
claude/ember-deprecations-review-033e20
Open

josemarluedke wants to merge 4 commits into
mainfrom
claude/ember-deprecations-review-033e20

Conversation

@josemarluedke

@josemarluedke josemarluedke commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

Retires the two @ember/object APIs Frontile still uses, following two open Ember RFCs:

  • RFC 1045 (Exploring) stops teaching @action and teaches arrow-function class fields instead. It does not deprecate @action.
  • RFC 1234 (Proposed) deprecates EmberObject and its object model. Its table does not name the standalone get() function, but get() reads through that object model, so it is the likeliest next target.

Frontile uses nothing else on RFC 1234's list. Glimmer components define their own willDestroy / isDestroying / isDestroyed, which the RFC does not touch and @glimmer/component's docs still teach, so those are left alone. The same goes for guidFor and the Application.create() boot calls.

Commits

  1. Replace get() with getPath (plus a follow-up commit from /simplify).
    • getConfigOption keys are flat, so it now uses plain property access.
    • Field#fieldValue needs dotted paths, so it uses a new getPath in utils/nested-data.ts. That puts it next to flattenData / unflattenData, and it is exported with them. It is a small public API addition.
    • It reads accessors, so @tracked fields and getters on class-instance formData work as they did with get().
    • It refuses __proto__ / constructor / prototype segments, including an own __proto__ key like the one JSON.parse produces. Field names can come from untrusted schemas, and Ember's get() would follow those segments to Object.prototype.
    • The tests were written first, and each guard was checked by removing it and watching the tests fail.
  2. @action → arrow fields in packages/*/src, including the co-located component .md files. Docfy renders those as live demos, and they are what consumers copy.
  3. The same in docs/, site/app, and test-app.

Review notes

  • One exception. site/app/routes/application.ts didTransition keeps @action. It is a router event, looked up in the route's actions hash, and an arrow field is not in that hash.
  • Mechanical conversion. The conversion was scripted. Aside from the removed decorators and imports, it only rewrites method headers (name = [async] (params): Ret => {) and turns closing } into };. Added and removed lines match one for one.
  • Initialization order. Class fields initialize in declaration order, so a field initializer that reads an action declared below it would get undefined. I checked every this.<action> that appears above its declaration, and all of them are inside methods, callbacks, or templates.
  • Overrides. Nothing calls an action through super. changeset-form's validate overrides still work because the base class and its subclasses are all fields.

Verification

  • pnpm build
  • test-app: 2202 tests, 0 failures (3 skipped)
  • site suite: 26/26
  • lint:types is clean for frontile, changeset-form, and forms-legacy.
  • eslint is clean on the changed files.
  • The template-lint errors in field.gts / form.gts / native-select.gts and the site/test-app type errors all exist on main and are on lines this PR does not change.

🤖 Generated with Claude Code

josemarluedke and others added 3 commits September 25, 2026 10:59
RFC 1234 deprecates the EmberObject object model. The standalone get()
function is not in its table, but it is the likeliest next target.

- getConfigOption: keys are flat, so plain property access is enough.
- Field#fieldValue: needs dotted paths, so it now uses a small getPath
  helper that reads own properties only and refuses __proto__,
  constructor and prototype segments, since field names can come from
  untrusted schemas. The unsafe-key list moves to -private/unsafe-keys
  so nested-data and getPath share it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Follows RFC 1045, which stops teaching @action in favour of arrow
functions assigned to class fields. The co-located component docs are
converted too, because Docfy renders their code fences as live demos and
they are what consumers copy.

No action is overridden through super, and no class-field initializer
reads an action declared below it, so the conversion is behaviour-
preserving; changeset-form's validate overrides stay working because
base and subclasses are both fields.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ite and test-app

Same conversion as the packages, per RFC 1045. The guide docs' code
fences are live Docfy demos, so they now teach the arrow form.

The application route's didTransition keeps @action: it is a router
event, looked up in the route's actions hash, which an arrow field is
not part of.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@netlify

netlify Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for frontile-next ready!

Name Link
🔨 Latest commit 40a0f04
🔍 Latest deploy log https://app.netlify.com/projects/frontile-next/deploys/6ab6be53bd664c0008f78c5b
😎 Deploy Preview https://deploy-preview-613--frontile-next.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

getPath is the read-side partner of flattenData/unflattenData, so it now
lives beside them and reuses the module's own isUnsafeKey. That removes
the separate get-path and -private/unsafe-keys modules, and puts the
prototype-pollution rationale back next to the walk it describes. It is
exported alongside the other nested-data helpers.

It also stops requiring own properties. @Tracked fields and getters are
accessors on the prototype, so a class-instance formData rendered empty
fields; Ember's get() read them. Unsafe segments are still refused,
including an own __proto__ key such as JSON.parse produces.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant