Polyfill @ember/owner imports for min-supported scenario#323
Merged
NullVoxPopuli merged 2 commits intoember-cli:nvp/its-vite-timefrom Apr 19, 2026
Conversation
Two stacked runtime issues were blocking ember-lts-4.12 once the `require` import issue from ember-cli#321 cleared. Both only affect the compat path (ENABLE_COMPAT_BUILD=true, ember4 deps overrides) and are hidden for ember-source >= 6 because the upstream code was rewritten. 1. "Cannot read properties of undefined (reading 'has')" at `makeComputedDecorator` → `COMPUTED_GETTERS.has(...)`. ember-source <= 5.x's `@ember/-internals/metal` has `let COMPUTED_GETTERS; if (DEBUG) { COMPUTED_GETTERS = new WeakSet(); }` paired with `assert(..., !COMPUTED_GETTERS.has(...))`. `DEBUG` comes from `@glimmer/env`, whose published default is `DEBUG = false`. Without something resolving `DEBUG` at compile time, rollup tree-shakes the init but the `assert` predicate still runs eagerly, so `COMPUTED_GETTERS` is undefined at runtime. Conditionally add `babel-plugin-debug-macros` (only when ENABLE_COMPAT_BUILD is set) with `flags: [{ source: '@glimmer/env', flags: { DEBUG: true } }]` so the plugin inlines `DEBUG = true` in ember-source. The init and the use stay consistent. Non-compat scenarios don't need the plugin — modern ember-source uses `isDevelopingApp()` from `@embroider/macros`, which `buildMacros()` already handles. 2. ember-qunit@8 + @ember/test-helpers@4 rely on classic-Ember globals that don't exist in a vite build: `start()` auto-calls `loadTests()` which iterates `requirejs.entries`, and `visit` reads `global.EmberENV._APPLICATION_TEMPLATE_WRAPPER`. Both were removed in ember-qunit@9 and @ember/test-helpers@5 respectively. Bump those two pins in the ember4 deps stanza so the scenario exercises the same surface modern scenarios do: ember-qunit: ^8.0.0 -> ^9.0.0 @ember/test-helpers: ^4.0.0 -> ^5.0.0 Both peer `ember-source >= 4.0.0`, so Ember 4.12 is still within the supported range. ember-qunit@9 peers `@ember/test-helpers >=3.0.3`, so the test-helpers bump stays within bounds. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`min-supported` installs `ember-source: ~4.2.0` but the test-app's
default `@glimmer/component@2.1.1` has `import { setOwner } from
'@ember/owner'`. `@ember/owner` didn't ship as a module path until
ember-source 4.10, so rollup fails with:
[vite]: Rollup failed to resolve import "@ember/owner" from
".../@glimmer/component@2.1.1/node_modules/@glimmer/component/dist/index.js"
Use `babel-plugin-ember-polyfill-get-and-set-owner-from-ember-owner` to
rewrite those imports back to `@ember/application` (which had `getOwner`
/`setOwner` in every 4.x release). The plugin only runs when
`ENABLE_COMPAT_BUILD` is set, next to babel-plugin-debug-macros. It's a
no-op for scenarios that still resolve `@ember/owner` natively
(ember-lts-5.12 and later) because `@ember/application` re-exports the
same symbols there.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
62fbb6c
into
ember-cli:nvp/its-vite-time
19 of 20 checks passed
NullVoxPopuli-ai-agent
pushed a commit
to NullVoxPopuli-ai-agent/ember-page-title
that referenced
this pull request
Apr 19, 2026
With ember-cli#323 landed, `ember-lts-4.12` flips to: Uncaught ReferenceError: Cannot access 'getOwner' before initialization at app-*.js line N ember-source >= 4.12's `@ember/application/index.js` re-exports the real implementations from `@ember/owner` as aliases: import { getOwner as actualGetOwner, setOwner as actualSetOwner } from '@ember/owner'; export const getOwner = actualGetOwner; export const setOwner = actualSetOwner; `babel-plugin-ember-polyfill-get-and-set-owner-from-ember-owner` rewrote the source of that import to `@ember/application` — turning the module into a self-import that rollup then collapses into `const getOwner = getOwner` (TDZ). The plugin already tries to skip ember-source paths, but the guard only short-circuits when the file is outside `.embroider/`; in a vite compat build ember-source lives at `node_modules/.embroider/rewritten-packages/ember-source.*/` so it fell through and got rewritten. Gate the plugin through babel `overrides` with a `test` filter that excludes any path containing `/ember-source/`. The polyfill still runs where it needs to (e.g. `@glimmer/component@2.1.1`'s `import { setOwner } from '@ember/owner'`, which is how min-supported started passing in ember-cli#323). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Unblocks the
min-supportedtry-scenario. With thebabel-plugin-debug-macrosfix from #322 in place,min-supported(ember-source~4.2.0) now fails at:@glimmer/component@2.1.1hasimport { setOwner } from '@ember/owner';.@ember/owneras an importable module path didn't exist until ember-source 4.10 (per the@ember/application→@ember/ownersplit deprecation), so there's no resolution on Ember 4.2. Per the upstream polyfill README: "not needed if you are on ember-source 4.12 or newer."Fix: add
babel-plugin-ember-polyfill-get-and-set-owner-from-ember-owner(by NullVoxPopuli) tobabel.config.mjs, next tobabel-plugin-debug-macrosand under the sameENABLE_COMPAT_BUILDgate. It rewrites:import { getOwner } from '@ember/owner'→import { getOwner } from '@ember/application'import { setOwner } from '@ember/owner'→import { setOwner } from '@ember/application'@ember/applicationexports both symbols in every 4.x release, so the rewrite works on Ember 4.2 and remains a semantic no-op on 4.12+ (where@ember/applicationre-exports from@ember/owner)....(isCompatBuild ? [ [ 'babel-plugin-debug-macros', { flags: [{ source: '@glimmer/env', flags: { DEBUG: true } }], }, ], + 'babel-plugin-ember-polyfill-get-and-set-owner-from-ember-owner', ] : []),Test plan
min-supported(ember-source~4.2.0) locally → 31 pass, 0 failENABLE_COMPAT_BUILD)min-supportedjob on CI goes greenember-lts-4.12,ember-lts-5.12,ember-lts-6.4,ember-latest,ember-beta,ember-alpharemain green —setOwnerresolution is unchanged for them; the rewrite targets@ember/applicationwhich re-exports from@ember/ownerin those Ember versions🤖 Generated with Claude Code