Skip to content

Don't run @ember/owner polyfill on ember-source itself#324

Merged
NullVoxPopuli merged 1 commit intoember-cli:nvp/its-vite-timefrom
NullVoxPopuli-ai-agent:fix/ember-owner-polyfill-skip-ember-source
Apr 19, 2026
Merged

Don't run @ember/owner polyfill on ember-source itself#324
NullVoxPopuli merged 1 commit intoember-cli:nvp/its-vite-timefrom
NullVoxPopuli-ai-agent:fix/ember-owner-polyfill-skip-ember-source

Conversation

@NullVoxPopuli-ai-agent
Copy link
Copy Markdown

Summary

Fixes the regression on ember-lts-4.12 introduced by #323:

Uncaught ReferenceError: Cannot access 'getOwner' before initialization
at http://localhost:.../assets/app-*.js, line N

Root cause

ember-source >= 4.12's @ember/application/index.js re-exports getOwner/setOwner from @ember/owner under aliases, then reassigns them as consts:

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 (added in #323) rewrote the from '@ember/owner' at the top of that file to from '@ember/application' — the module's own specifier — so rollup bundled it as a self-import. The const getOwner = actualGetOwner line then becomes (effectively) const getOwner = getOwner, which trips TDZ at load time.

The plugin already tries to skip ember-source files with this guard:

if (state.filename?.includes('/ember-source/')) {
  if (!state.filename.includes('/.embroider/')) {
    return;
  }
}

But in a vite compat build ember-source lives at node_modules/.embroider/rewritten-packages/ember-source.*/node_modules/ember-source/..., so the path contains both /ember-source/ and /.embroider/ — the guard falls through and rewrites the file. min-supported didn't hit this on Ember 4.2 because that version's @ember/application doesn't import from @ember/owner in the first place.

Fix

Move the polyfill plugin out of the main plugins list into babel.overrides, with a test filter that skips anything whose filename contains /ember-source/:

     ...macros.babelMacros,
     ...(isCompatBuild
       ? [
           [
             'babel-plugin-debug-macros',
             {
               flags: [{ source: '@glimmer/env', flags: { DEBUG: true } }],
             },
           ],
-          'babel-plugin-ember-polyfill-get-and-set-owner-from-ember-owner',
         ]
       : []),
   ],

+  overrides: isCompatBuild
+    ? [
+        {
+          test: (filename) =>
+            filename !== undefined && !filename.includes('/ember-source/'),
+          plugins: [
+            'babel-plugin-ember-polyfill-get-and-set-owner-from-ember-owner',
+          ],
+        },
+      ]
+    : [],

This keeps the rewrite running where it's actually needed (@glimmer/[email protected]'s import { setOwner } from '@ember/owner', which is what #323 was targeting), and leaves ember-source alone.

A proper fix probably belongs upstream in the plugin (the existing filename guard likely intended to skip ember-source unconditionally), but this unblocks CI without needing a plugin release.

Test plan

  • ember-lts-4.12 locally → 31 pass, 0 fail
  • min-supported locally → 31 pass, 0 fail (polyfill still runs on @glimmer/component)
  • Default non-compat → 31 pass, 0 fail (override block is empty)
  • ember-lts-4.12 and min-supported jobs on CI go green
  • Other try scenarios and the regular Tests/Floating jobs remain green

🤖 Generated with Claude Code

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/[email protected]`'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) <[email protected]>
@NullVoxPopuli NullVoxPopuli merged commit 2ca69f6 into ember-cli:nvp/its-vite-time Apr 19, 2026
20 checks passed
@github-actions github-actions Bot mentioned this pull request Apr 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants