Deprecation staging config, deprecation shaking, and classic object model deprecations (wave 1)#21505
Draft
wagenet wants to merge 24 commits into
Draft
Deprecation staging config, deprecation shaking, and classic object model deprecations (wave 1)#21505wagenet wants to merge 24 commits into
wagenet wants to merge 24 commits into
Conversation
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>
wagenet
force-pushed
the
classic-object-model-deprecations
branch
from
July 17, 2026 03:11
9f0e401 to
240cfdb
Compare
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>
…iases internalExtend/internalReopen/internalReopenClass (@ember/object/core) and createMixin (@ember/object/mixin) are the entry points for ember-source's own framework definitions; the public statics delegate to them. This includes the runtime sites (autoboot Router extend, Router.map's reopenClass, engine initializer buckets) and the PrototypeMixin/willReopen machinery, so upcoming definition-time deprecations on the public statics never fire from framework internals. No behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…age) deprecate-ember-object-extend, deprecate-ember-object-reopen, and deprecate-ember-mixins fire from the public statics only; framework internals go through the internal aliases. Available-stage: silent unless opted into via DEPRECATION_STAGES. The blanket CI variant rows move from _ALL_DEPRECATIONS_ENABLED to ENABLED_DEPRECATIONS=true with these ids excepted, since ember's own suite still exercises the classic APIs pervasively. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
deprecate-computed-properties fires from the public computed() wrapper and once at module eval of the @ember/object/computed macros barrel; deprecate-observers fires from observer() and the public addObserver/removeObserver. Framework internals use the metal modules directly (the two remaining public-barrel imports in the routing services moved to the deep path) and stay silent. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
deprecate-ember-array fires from the public A(); internals use the new internalA (data-adapter, reduce_computed_macros, route/router QP handling). The EmberArray/MutableArray/NativeArray mixins ride the extend/mixins deprecations when applied externally. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fires at init, deduped by a WeakSet on the constructor so high-volume proxy creation warns once per class. Internals never instantiate these. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
RFC appendix covering the wave-1 ids, the internal-alias approach, why these entries have no shaking flags, and the blanket-CI except-list rationale; registry doc comment gains the internal-alias convention. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Consumer bundlers treat @ember/object/computed as side-effect-free (the package-level sideEffects declaration) and drop top-level statements when only re-exports are used, so the module-eval deprecation never fired in bundled apps. Each macro export is now a call-time deprecating wrapper; internals keep using the underlying lib modules directly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The proxy dedupe sets only record classes while their deprecation is enabled, so enabling later still warns; expandProperties gets an accurate message; createMixin notes its intentional divergence from the this-based static. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
OVERRIDE_DEPRECATION_VERSION=15 made every wave-1 deprecation (until
8.0.0) throw the removal error across the suite and the smoke apps —
ember's tests and the app-testing ecosystem still use the classic APIs.
except now also excludes an id from the version-based removal
computation (never from a false shaking flag: that code is actually
gone), and the Deprecations-as-errors CI rows plus the
deprecations-removed smoke job carry the classic except list, threaded
into the app templates via EXCEPT_DEPRECATIONS.
setDeprecationStagesConfig(null) now restores the boot (EmberENV)
config instead of clearing it — test teardowns were wiping the
harness variant's config for the rest of the suite. {} is an
explicitly empty config. Warn-expecting deprecation tests skip under
removal simulation via testUnless, the standard pattern for removed
deprecations.
Co-Authored-By: Claude Opus 4.8 (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>
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? |
Module-scope calls to the imported internalReopen/internalReopenClass helpers made six modules permanently side-effectful (caught by the tree-shakability snapshot): rollup cannot scope an imported helper call, but it can scope a static method call to its class. The non-deprecating internal entry points for reopen/reopenClass are now reopenInternal/reopenClassInternal statics on CoreObject; the module functions remain as their implementation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
wagenet
force-pushed
the
classic-object-model-deprecations
branch
from
July 17, 2026 19:25
240cfdb to
7173c1c
Compare
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