Deprecation staging config, deprecation shaking, and classic object model deprecations (wave 1) - #21505
Draft
wagenet wants to merge 15 commits into
Draft
Deprecation staging config, deprecation shaking, and classic object model deprecations (wave 1)#21505wagenet wants to merge 15 commits into
wagenet wants to merge 15 commits into
Conversation
wagenet
force-pushed
the
classic-object-model-deprecations
branch
from
July 17, 2026 03:11
9f0e401 to
240cfdb
Compare
Contributor
|
how would a consuming project configure their build tool to not include deprecations? the changes I see are on the ember-publishing side, and I think the deprecation staging stuff we talked about all that time ago was user-configurable? |
wagenet
force-pushed
the
classic-object-model-deprecations
branch
from
July 17, 2026 19:25
240cfdb to
7173c1c
Compare
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Apps can enable individual available-stage deprecations early (enable), declare compliance so migrated-away deprecations throw instead of warn (compliance/assert/except), and test harnesses can swap config at runtime via setDeprecationStagesConfig. DEPRECATIONS registry entries now compute test/isEnabled/isRemoved lazily so config changes are reflected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Revives @ember/deprecated-features as the per-deprecation flag source: one boolean const per shakable deprecation, named after its DEPRECATIONS registry key. deprecation() takes the flag as a second argument; a false flag makes the entry report isRemoved so unguarded reaches throw. The Comparable mixin body and the deprecated service inject body are guarded following the convention. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The standard dist externalizes @ember/deprecated-features to a package
self-reference so the flags stay live for app-side shaking, emits the
flags module and dist/deprecation-flags.json. EMBER_DEPRECATION_FLAGS
builds dist/deprecation-custom/{dev,prod} with the flags compile-time
folded and guarded code eliminated. bin/assert-deprecations-shaken.mjs
verifies both directions; a new CI job runs it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A vite/rollup plugin that replaces the externalized flags module in ember-source's dist based on app config (compliantThrough, strip, keep): shaken deprecations lose their implementation to DCE and throw the removal error if reached. The smoke scenario builds a real Embroider vite app both ways and verifies bundle contents and runtime behavior. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
setDeprecationStagesConfig stays private with a follow-up-RFC path; dynamic-id deprecation families take one flag, with the past-until import-from-ember family deliberately unflagged. The compliance-scope and shaken-undefined questions stay open with stated defaults. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The deprecation-shaking plugin matches module ids with POSIX separators (vite normalizes ids on every platform; the node:path sep never matched on Windows). The manifest metadata (id/since/until) is now pinned to the DEPRECATIONS registry by a conformance test, and the scan script's marker guidance describes what actually survives prod builds. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
generateBundle runs before rollup writes output, so on a fresh checkout the directory does not exist yet and every from-scratch build failed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Under _OVERRIDE_DEPRECATION_VERSION simulation an unshaken deprecation legitimately reports removed; the assertion tested version logic, not shaking. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
except now means "treat this id as unconfigured": exempt from compliance/assert throwing and excluded from enable, including enable: true. EXCEPT_DEPRECATIONS threads through testem/index.html so CI variants can blanket-enable available deprecations minus a known-noisy list. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
except now also excludes an id from the version-based removal
computation, so _OVERRIDE_DEPRECATION_VERSION can simulate a future
version with known-noisy ids excluded, the same way enable: true
coexists with them. It never shields a false shaking flag: that code is
actually gone.
setDeprecationStagesConfig(null) now restores the boot (EmberENV)
config instead of clearing it, so test teardowns no longer wipe the
harness variant's config for the rest of the suite. {} is an explicitly
empty config.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The stage configuration functions are no-op stubs in production builds, so the tests that exercise them move to a development-only module. The isRemoved compliance test starts from an explicitly empty config — the compliance CI variant's boot config now survives teardown (null restores it) and would otherwise make its enabled-stage deprecation throw. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Both are already deprecated (RFC 1112) and nothing in ember-source uses them, so their implementations can leave a shaken build. PromiseProxyMixin takes the value shape, like Comparable: a shaken build exports undefined. A cast keeps its published type, since TypeScript does not narrow a const-true flag in a conditional. ObjectProxy takes the entrypoint shape: the class survives as a stub whose init throws the removal error, and ProxyMixin, which holds the forwarding behavior and has no other consumer, is shaken away. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
wagenet
force-pushed
the
classic-object-model-deprecations
branch
from
September 18, 2026 19:13
7173c1c to
dded12f
Compare
This branch has not been deployed
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.
Draft for CI signal — not ready for review yet, and the design needs an RFC before any of it can merge. An RFC draft covering the full design lives in this PR at
internal-docs/rfcs/deprecation-early-enablement-and-shaking.md.This is two stacked pieces of work in one PR so CI covers the whole stack; it will be split for review:
1. Deprecation tooling (branch
deprecation-stages-and-shaking)EmberENV.DEPRECATION_STAGES: per-id early enablement of available-stage deprecations (enable), and compliance declarations that turn migrated-away deprecations into errors (compliance/assert/except). Builds on the staging metadata from RFC 0649.@ember/deprecated-featuresflags stay live in the published dist (externalized as a package self-reference), and apps can strip deprecated code paths with theember-source/deprecation-shakingvite plugin or anEMBER_DEPRECATION_FLAGSsource build. A false flag also makes the deprecation report itself as removed at runtime, so shaking is a size optimization on top of correct semantics.deprecation-shaken-distjob with a dist scan, smoke-test scenario building an app both shaken and unshaken.2. Classic object model deprecations, wave 1 (branch
classic-object-model-deprecations)Available-stage deprecations (
since: 7.3.0,until: 8.0.0, silent unless opted into) for:.extend(),.reopen()/.reopenClass(),Mixin.create,computed()and the@ember/object/computedmacros,observer()/addObserver/removeObserver,A(),ObjectProxy,ArrayProxy.Ember's own framework definitions route through internal non-deprecating entry points (
internalExtend,createMixin, …), including the runtime paths (autoboot Router re-extend,Router.map, engine initializers), so framework operation is never blamed on apps. The blanket and removal-simulation CI variants carry these ids inexcept, which now shields an id fromenable: trueand from_OVERRIDE_DEPRECATION_VERSION.Verified locally: full suite under the standard, all-deprecations-enabled, and deprecations-as-errors variants; smoke scenarios standard and under removal simulation; published types across TS 5.2–7.0.
This PR was written by Claude (I reviewed and directed the work).
🤖 Generated with Claude Code