Skip to content

Drop isInteractive and hasDOM; remove FastBoot codepaths#21347

Closed
NullVoxPopuli-ai-agent wants to merge 2 commits into
emberjs:nvp/environment-collapsefrom
NullVoxPopuli-ai-agent:nvp/drop-isinteractive
Closed

Drop isInteractive and hasDOM; remove FastBoot codepaths#21347
NullVoxPopuli-ai-agent wants to merge 2 commits into
emberjs:nvp/environment-collapsefrom
NullVoxPopuli-ai-agent:nvp/drop-isinteractive

Conversation

@NullVoxPopuli-ai-agent
Copy link
Copy Markdown
Contributor

Stacked on top of #21346.

Since we always have a DOM and modifiers always run, the entire isInteractive/hasDOM split is dead weight.

Summary

  • Glimmer-vm: drop isInteractive from EnvironmentImpl/EnvironmentDelegate/Environment. scheduleInstallModifier, scheduleUpdateModifier, VM_MODIFIER_OP, and VM_DYNAMIC_MODIFIER_OP always run.
  • Curly + root managers: lifecycle hooks (willRender, willInsertElement, didInsertElement, willUpdate, didUpdate, didRender, willDestroyElement, willClearRender) always fire.
  • Renderer: drop isInteractive/hasDOM from boot options; getElement always returns the element; remove(view) always triggers didDestroyElement.
  • App/engine boot: drop BootOptions.isInteractive and BootOptions.isBrowser. setupEventDispatcher always runs. EventDispatcher.setup no longer asserts against fastboot mode. EngineInstance always registers event_dispatcher:main.
  • @ember/-internals/browser-environment deleted entirely. The only remaining consumers were isChrome/isFirefox in @ember/debug — inlined with typeof window !== 'undefined' guards. self/location/history/window re-exports are gone.
  • <Input> initializes its probe element lazily so build tools that import the package in Node (without a DOM in scope) still load. DOM is required at render time, which is the contract.
  • Component: _dispatcher always looks up event_dispatcher:main. appendTo always uses document.querySelector for string selectors. matches() drops its fastboot guard.

Tests dropped

  • non-interactive variants of the lifecycle, custom-modifier, and on-modifier integration tests
  • visit_test for "doesn't set up event_dispatcher:main if isInteractive is false"
  • The 4 FastBoot smoke tests in smoke-tests/node-template/tests/node/ (app-boot, component-rendering, fastboot-sandbox, visit) and their SimpleDOM-based helpers

44 files changed, +163 / -1746.

Verified

  • `pnpm type-check`
  • `pnpm lint:eslint`
  • `pnpm build:js` (rollup)
  • `pnpm vite build`
  • `pnpm test` — 9187 pass / 0 fail / 17 skip
  • All 4 smoke scenarios pass

🤖 Generated with Claude Code

Since we always have a DOM and modifiers always run, the entire
isInteractive/hasDOM split is dead weight. Tear it out.

Glimmer-vm:
- @glimmer/runtime/lib/environment.ts: drop the isInteractive field on
  EnvironmentImpl and EnvironmentDelegate. scheduleInstallModifier and
  scheduleUpdateModifier always schedule.
- @glimmer/runtime/lib/compiled/opcodes/dom.ts: drop the early-returns
  in VM_MODIFIER_OP and VM_DYNAMIC_MODIFIER_OP. Modifiers always run.
- @glimmer/interfaces: drop isInteractive from the Environment interface.

Ember component layer:
- curly + root component managers: lifecycle hooks (willRender,
  willInsertElement, didInsertElement, willUpdate, didUpdate, didRender,
  willDestroyElement, willClearRender) always fire.
- ComponentStateBucket no longer carries isInteractive.
- BootEnvironment loses both fields.

Renderer:
- BaseRenderer / Renderer / renderComponent no longer take an env config.
  isInteractive and hasDOM options are gone.
- Renderer.getElement always returns the element (no more "not allowed in
  non-interactive environments" throw).
- Renderer.remove always triggers didDestroyElement.
- Drop the _isInteractive getter and the debug.isInteractive field.
- EmberEnvironmentDelegate has no constructor args.

Application/engine boot:
- BootOptions drops isInteractive and isBrowser.
- _BootOptions no longer threads isInteractive through isBrowser /
  shouldRender / option override; just _renderMode, location,
  shouldRender, document, rootElement.
- ApplicationInstance always calls setupEventDispatcher.
- EngineInstance's singleton list always includes event_dispatcher:main.
- EventDispatcher.setup drops the "should never be setup in fastboot"
  assertion.
- @ember/-internals/views/lib/system/event_dispatcher.ts no longer
  imports from @ember/-internals/glimmer.

Component:
- The DEBUG tagless event-handler check no longer needs renderer._isInteractive.
- _dispatcher always looks up event_dispatcher:main.
- appendTo always uses document.querySelector for string selectors;
  the "no DOM" branch is gone. matches() drops its fastboot guard.

Browser-environment package: deleted entirely.
- isChrome/isFirefox were the only remaining consumers (in @ember/debug);
  inlined there with `typeof window !== 'undefined'` guards.
- self/location/history/window references were the only hasDOM users.
- Removed from @ember/-internals package exports, root package.json
  embedded-package map, types/stable manifest, and lib/index.js
  implicit-modules list.
- Test files that imported `window`/`isChrome`/`isFirefox` from
  browser-environment now use globals directly.

Inputs lazily initialize INPUT_ELEMENT (instead of at module-load time)
so node-side build tooling that imports the package without a DOM in
scope still loads. The DOM is required at render time, which is the
contract.

Tests:
- Drop the non-interactive variants of the lifecycle, custom-modifier,
  and on-modifier integration tests. Drop the lifecycle test's
  isInteractive/nonInteractive split — assertHooks always uses the
  interactive expectations.
- Drop the visit_test that checked event_dispatcher:main wasn't created
  for isInteractive: false.
- OutletView render-queue test now appends to a real DOM element rather
  than a CSS-selector string (since selector resolution is no longer
  short-circuited).
- type-tests for BootOptions no longer mention isBrowser.

Smoke tests:
- Delete app-boot, component-rendering, fastboot-sandbox, and visit
  tests in node-template, plus their setup-app/setup-component/build-owner/
  assert-html-matches helpers. They were FastBoot-only — every one of
  them used SimpleDOM as a stand-in for `document`.

Cumulative diff vs nvp/environment-collapse: 44 files, +163 / -1746.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@NullVoxPopuli
Copy link
Copy Markdown
Contributor

Prompter's note:

  • the limitations fastboot placed on us for SSR are no longer needed, and since fastboot was never formally supported, I think we can drop this stuff in a non-major release
  • vite-ember-ssr proves that we can not only render in interactive mode, but we can await settled() if we want until rendering is finished, which gives us a lot of flexibility, and frees us from having to maintain all this cruft

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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