Issue #3618644: Declare Drupal 12 support, and run the whole suite against it
Every extension declares ^11.3 || ^12, and a phpunit (next major) lane runs the whole suite against core dev-main, so support for Drupal 12 is measured rather than asserted.
What core 12 required
- Return types. Core 12 declares native return types on methods this module overrides:
toUrl(),label(),buildEntityQuery(),create(),createInstance(),applyDefaultValue()and the channel cache context now state theirs.validateForm()is the one that cannot carry one, because core 12 declares the entity where core 11 returns nothing and a nullable type would widen both, so it carries an explicit@returninstead. - An explicit commit on every transaction. A
Transactiondestroyed without one commits today, and that is deprecated in 11.5 for removal in 13. Every scope now ends incommitOrRelease(). Behavior is unchanged on both cores; what changes is that it is stated. - PHPUnit 12 leaves no mock without an expectation, so stubs that only stand in are built with
createStub(), and$this->any(), deprecated there, gives way toatLeastOnce(). $argvexists only whereregister_argc_argvis on, so the load scripts read$_SERVER['argv'].
The two lanes cannot share their test-type names
Core 11.4 accepts run-tests.sh's legacy PHPUnit-Kernel spelling; core 12 dropped the map and wants the names from phpunit.xml. No single spelling runs on both, so the next-major lane overrides the matrix with kernel and functional,functional-javascript,unit,unit-component,build.
The performance budgets, and the difference that was not a regression
The two performance tests hold exact budgets, and reconciling them across cores turned up three things:
- The three extra queries on core 12 were a missing module. The testing profile brings
dynamic_page_cachealong on core 11 and does not on core 12, so the page was rebuilt per request and the availability recomputed. Both tests now name it among their modules, and the same figures hold on both cores. - The asset counts genuinely differ. Core 12 groups its aggregates by library set and by category rather than into one bundle, and serves
once.min.json its own, so the same page arrives as four scripts and two stylesheets where core 11 sent one of each. Both figures are measured and both are asserted, per core, so a page that grows an aggregate still fails on the core it grew on. The byte counts differ by well under the toleranceassertMetrics()already allows for them, so one figure covers both. - The click that puts a place in the basket costs one query fewer on core 12. Stated per core, not tolerated.
A ceiling loose enough to pass on either core would have been the same as not asserting the counts at all, which is why each core is held to what it actually does.
Dependencies
webform has no core 12 release, and its handler manager is not compatible with core 12's CategorizingPluginManagerInterface, so the six tests that need it skip on core 12 and say why. domain asks for ^3.0 || ^4.0.