Follow-up to #2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList, which provides new extension listing classes ExtensionList, ProfileExtensionList, ModuleExtensionList.
Problem/Motivation
Due to the size of the theme list refactoring scope, we need a separate issue.
Proposed resolution
Create new ThemeExtensionList and ThemeEngineExtensionList classes, refactor theme discovery functionality into this class.
Remaining tasks
Patch
Reviews
Commit
User interface changes
None
API changes
ThemeHandler constructor has new argument $theme_list of type ThemeExtensionList but is an optional argument. Service signature not changed in core.services.yml.
ThemeInstaller constructor has new argument $theme_list of type ThemeExtensionList but is an optional argument. Service signature not changed in core.services.yml.
- New
ThemeExtensionList class and extension.list.theme service. Class marked internal.
- New
ThemeEngineExtensionList class and extension.list.theme_engine service. Class marked internal.
- The
ModuleExtensionList and ProfileExtensionList classes also marked internal.
- The protected
$defaultFeatures class property removed from ThemeHandler
- The protected
$extensionDiscovery class property removed from ThemeHandler
Data model changes
None.
Release notes snippet
Theme extension listing moved to ThemeExtensionList class and brought into line with module listing making a complex part of core more consistent. In the future this will allow us to remove unnecessary code from the system module.
Comments
Comment #2
almaudoh commentedFirst trial patch rolled on top of the patch at #2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList. CNR for testbot.
Comment #4
almaudoh commentedRerolled to HEAD
Comment #6
almaudoh commentedComment #8
almaudoh commentedI was very sleepy when I posted the last two patches :P
Comment #9
dawehnerIn general this looks pretty good already. Didn't had a deep look into it yet, but I totally agree that the theme extension list part should be extracted
from the theme handler. Great work!
Comment #11
almaudoh commentedSo, do we still need the
system_listcache?Comment #12
dawehnerI guess no?
Comment #13
jibranShould we move all the drupal_get_profile() calls to wrapper function?
Comment #14
berdirNice.
We should deprecate those functions and mark for removal in 9.x
Wondering if the changes in here could be considered a BC break in some way...
Should we have a way to get enabled themes only? a method for this?
The extension list is different for themes than for modules, as it also knows about enabled or not.
is this a fallback when the extension isn't injected yet?
can we inject this?
Comment #17
dawehnerLet's postpone it for now
Comment #20
almaudoh commentedSince #2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList is RTBC, I thought I should re-roll this patch and bring it back. So here's a re-roll of the -do-not-test.patch in #11
It still needs to be applied to the RTBC patch in #2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList
Comment #21
dawehnerThank you for your reroll @almaudoh!
What about just do a return
$extension->status?Let's still mark this internal? Let's also add some documentation :)
This methods could be made easier to rad by splitting it up into two bits:
$themes = readThemeInfoFiles($themes)and$themes = $this->fillInSubThemes($themes). Maybe we could do that in another issueI fear we would need to create a new follow up, given that this is extension part 3 :)
I see, this is public due to BC reasons. We should clearly communicate that with another @internal statement + an explanation.
👍 Doing less magic on theme installation is an obvious improvement
We need to add back test coverage for those ...
Comment #23
jibran#2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList is in.
Comment #24
dsnopekChange parent to the right META issue - this is really a sibling, not a child, of #2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList
Comment #25
jofitzRe-roll.
Comment #27
dsnopekI haven't done a detailed read of the patch, I just peeked in, but I saw something right away at the top:
Shouldn't these services be named 'extension.list.theme' and 'extension.list.theme_engine' to match the extension list services for modules and profiles?
This code will depend on that!
Comment #28
dsnopekThis fixes the review from #27 - hopefully, this one will test a little better
Comment #30
dsnopekAh, apparently what is breaking the tests is:
Comment #31
almaudoh commentedTrying to fix the test fails first. Interdiff is against #25 and contains changes mentioned in #28.
Comment #32
almaudoh commentedOk. Here's the actual patch.
Comment #35
almaudoh commentedAddressed some of the review comments here:
#14:
1. :)
2. If so, then the removal of
$extensionDiscoveryfromThemeHandlerwould also be a BC break. Not so sure.3. I thought about this too, just like
ModuleHandler::getModuleList(), but I'm wondering if the module/theme handler is the right place for that information or would it rather be in the module/theme installer. Also, as it is now, both modules and themes have the same 'installed' status, no more enabled status.4. Yes, because to maintain BC, the
ThemeHandlerconstructor had to have an optional parameter for theThemeExtensionList5. I guess we can. It would be the same pattern as in 4. I guess.
#21:
1. Done
2. I'm just wondering why these two would be marked @internal while the
ModuleExtensionListis not. Should we make all three internal.3. It seemed like it would be too complicated splitting out to two methods (because of the
$sub_themesvariable), so I went halfway and broke out$this->fillInSubThemeData()to a separate method.4. I'm wondering if we still really need to do that. I think we should just remove the @todo.
5. IMO this should be the public interface while the
ThemeHandlerInterface::getBaseThemes()should be deprecated. What do you think?6. Yes! Less magic.
7. Will do this in the next patch.
Comment #37
jofitzA minor improvement and a correction ($theme->status is normally 0 or 1 so we don't want === TRUE).
Comment #39
jofitzFixed the coding standards errors.
But the Functional test failures are beyond me, on this occasion.
Comment #41
dawehnerOh yeah totally, till we are sure these services are stable.
Comment #42
dawehnerAssigning to myself to fix the failure
Comment #43
dawehnerComment #45
almaudoh commentedThis doesn't work because we always want to get the freshest list of themes (rather than the cached list) when building the theme listing (for instance where a theme was just installed or uninstalled).
Comment #46
dawehner@almaudoh Ah interesting. Do you mind on your next patch iteration make a comment why we are doing something this specific way? Thank you!
Comment #47
almaudoh commentedSo correcting per #45, let's see if tests all pass...
Comment #48
jibranIt's green! Nice work!
#2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList is fixed. Can we remove this now?
Can we inject this if not then can we add a comment here?
Are we going to deprecate these? If yes then can we have a change notice?
Comment #49
almaudoh commentedIn this patch, the test coverage that was removed for
::rebuildThemeData()and::getBaseThemes()has been reinstated in a newThemeExtensionListTestclass.Other comments have also been addressed:
1.
ModuleExtensionList,ProfileExtensionList,ThemeExtensionListandThemeEngineExtensionListhave all been marked@internal2. The @todo referencing #2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList has been removed
3. The 'extension.list.theme' service is now injected into
ThemeInstallerservice class.#48:
1. This most definitely would need profiling :)
2. Removed
3. Injected
4. I think deprecations should be in a follow-up issue so as not to delay this one. There are already a bunch of deprecation issues scattered around, I'll just make a meta issue to capture all of them.
Comment #50
almaudoh commentedComment #51
almaudoh commentedComment #52
almaudoh commentedCreated a meta issue to track all the deprecations from this issue and the
ModuleExtensionListone: #2940190: [meta] Deprecations of old functions in Extension systemComment #53
jibranWe should also add information about
ThemeExtensionListandThemeEngineExtensionListin _system_rebuild_module_data() and co. are replaced by services to give you all available modules.Comment #54
markhalliwellRe #41:
I'm really not a huge fan of flagging these as
@internal.However, if these are only being temporarily flagged as such for "stability" reasons, then a comment and @todo linking to an issue that removes this state once the criteria deeming them as "stable" has been met should also be added.
Otherwise, we risk leaving them this way and I know for a fact that I have plans on extending some of these classes in the future since they're now proper services that can easily be extended or replaced entirely by contrib.
Comment #55
almaudoh commentedRerolled after #2939904: Fix system_get_info() for non-installed modules got committed. NW to test.
Comment #56
almaudoh commentedHiding the wrong patch.
Comment #57
almaudoh commentedHead was moving too fast on the previous reroll.
Comment #59
markhalliwellPlease see #54.
I would even suggest that all these issues for extension listings get backported to 8.5.x so we can actually start using them and then before 8.6.0 is released, these
@internaltags are removed because we'll have fixed any major bugs that may have crept up.Comment #60
dawehnerI opened up #2940481: Road to stabilize ExtensionList services. To be honest I'm a huge fan of adding an interface on the longrun, but let's discuss that over there.
Comment #61
almaudoh commentedAdded some explanation for making the classes
@internal.Comment #62
almaudoh commentedAlso made
ExtensionList@internaland slightly improved the formatting of the message.Comment #63
markhalliwellThis feels like the extension list should already support returning a filtered list based on status.
Perhaps a parameter could be added to
->getList(), e.g.$enabled = NULL?NULL- return all regardless of statusTRUE- return all enabledFALSE- return all disabledThis can't be the only place where having native support for this kind of filter would be necessary.
Again, this shouldn't be a static list. It should actually return the installed theme engine names.
Ah, here is another place that could benefit from an already filtered list as mentioned above.
It could probably even be reduced to a one-liner for that matter:
Comment #64
almaudoh commented#63:
1. This is something I thought we would need also, but I felt it was out of scope. Decided it's cleaner to introduce new methods
::getInstalledand::getUninstalled(), while::getList()will still return all extensions. I've also added test coverage for the new methods.2. So far I've not found where the theme-engine list is stored - it's not in the
core.extensionconfiguration storage. I've not seen any code that actually installs theme engines and saves the list somewhere. Will have to create a follow-up for this.3. Great idea. Did that.
I've also updated the change record. https://www.drupal.org/node/2709919
Comment #66
almaudoh commentedAdded more test coverage that helped me identify the bug. Fixed it.
Comment #67
almaudoh commentedMissed one test :).
Comment #68
dawehnerWhy do you need this use statement?
What happened with the
system_registercall?This reads quite nice now.
👍 This makes this easy to understand what is going on.
What means installed/uninstalled in the context of profiles/theme engines?
Can't you have multiple theme engines? There is probably not a single person using one, but this would break this, wouldn't it?
❓Why do we need both?
Should we mark the interface method deprecated?
👍 Nice!
Comment #69
almaudoh commented#68:
1. Removed unused use. This was left over from earlier version of the patch.
2. The only purpose of this section of code is to statically cache the theme .info.yml file paths for faster lookup.
system_register()callsdrupal_get_filename()with the theme name and file path (as mentioned by the comment above that code block). Since the new implementation already has the filepaths from ExtensionDiscovery, and is cached internally by ExtensionList, this bit of code is no more needed. The other thingsystem_register()does is to register the theme in the PSR4 classloader. I don't think this is needed either since all modules and themes are already registered on installation.3. :)
4. Yes!
5. Well, in the context of install profiles / theme engines, we may consider the possibility of installing / uninstalling them in future. We should leave that possibility open.
6. This would mean creating a new config storage entry for the list of installed theme engines. Will try that out in the next patch.
7. Since it's an optional argument, we have to cover for where it is not provided. I didn't want to break the constructor signature. But leaving it in makes it easier to enforce the dependency injection when we can break BC.
8. My thoughts too. I have marked the interface
@deprecated, even though I didn't implement@trigger_errorto avoid test fails. I tried that but the patch got too big. I'll open up a separate issue for that.9. :)
Comment #70
markhalliwellWhere are they registered on installation? I cannot find this in any of the
*Installerclasses.I'm very worried/cautious about this change. Themes like https://www.drupal.org/project/bootstrap rely heavily on PSR autoloading and, from what I have always been able to determine, this was where theme namespaces were registered. There's even a "fix" for this in the base theme:
https://drupal-bootstrap.org/api/bootstrap/autoload-fix.php/8#source.16
It purposefully invokes
\Drupal::service('theme_handler')->listInfo();to trigger this registration because, during certain circumstances (e.g. AJAX requests), theme namespaces haven't yet been registered (regardless if they were installed).From past conversations (#2002606: Allow themes to provide services.yml and other IRC/slack convos), I've been told this is primarily due to which theme is "active".
That being said, this has always registered all "installed" themes... not just the "active" ones... so.... idk.
I'm almost tempted to say that theme namespaces are a very vital aspect of this issue and need to be flushed out more first. AFAIK, there are no [extensive] theme namespace tests, so... the current "passing" may be a false positive as it's likely to break contrib.
Comment #71
markhalliwellI think maybe you're confusing "registered on installation" with DrupalKernel::compileContainer. This automatically registers module namespaces, because they can provide services (not themes):
http://cgit.drupalcode.org/drupal/tree/core/lib/Drupal/Core/DrupalKernel...
Comment #72
markhalliwellShould probably be postponed on this, but leaving status to CNW for now. If you agree, you can change.
Comment #73
almaudoh commentedGood observation, @markcarver, I actually haven't encountered this issue of theme class namespacing before. It does tell me that we need to add test coverage for theme classes. Maybe this will provide an opportunity to fix the Bootstrap hack here.
Yes. This is what I thought.
I will take some time to study the issues referenced for some insights. Maybe others can chime in here as well.
Comment #74
almaudoh commentedI'm thinking maybe would be better to re-instate the
system_register()calls and then fix the whole theme namespacing thing in #2941757: Extension System, Part IV: Properly register all installed extensions/namespaces during container generation. That way we can keep this issue focused, while the other issue will have the extension system in a saner form to work with.Comment #75
markhalliwellSure, I'm OK with doing that as a follow-up.
Comment #76
markhalliwellFTR, I think just reinstating
drupal_classloader_register()will be enough.Comment #77
dawehnerI think this should not be a follow up. Instead we should do two things:
Maybe this should be done before this issue, but I think we should avoid temporary regressions.
Comment #78
almaudoh commentedIt wouldn't be a regression if we re-instated the call to
system_register()or just directly calleddrupal_classloader_register().I'm seeing the theme namespace issue as really out of scope. But, well, we could still add it.
Doing that before this issue would mean more places where we have to change the old API. We could add the test and make sure it doesn't fail in this issue, while the more elaborate edge cases (e.g. Ajax, multiple themes, admin / default themes, etc.) can be punted to #2941757: Extension System, Part IV: Properly register all installed extensions/namespaces during container generation.
Comment #79
markhalliwellIt's not, but I suppose considering that there has been very little documented "support" for this, I could see how you would say that.
I think that's what @dawehner was suggesting.
That being said, #1538478: Register lib/ directories of themes as PSR-0 roots for Drupal\$theme namespace supposedly already added such a test:
http://cgit.drupalcode.org/drupal/tree/core/modules/system/src/Tests/The...
Which instantiates a
new ThemeClass()object.I think, however, this is still a false positive since it's not actually testing against core's container namespaces using the extension registration/autoloading, but rather it may just be successfully autoloading due to the nature of directly calling the class in the test itself (i.e. using the test namespacing/autoloader, not core's).
A real test would be to load a page where the theme itself can instantiate one of its own classes from within the
*.themefile, like Drupal Bootstrap does. This ensures that the container properly registers the classes within the scope of the request.Comment #80
almaudoh commentedIn this patch I've added a config storage entry for theme engines in
core.extension.yml, with a default to 'twig'. That means a module can easily override the active theme engine by writing to that config storage\Drupal::config('core.extension')->set('theme_engine', 'my_theme_engine');. Also added test coverage for that.Will work on the namespacing issue next.
Comment #81
almaudoh commentedModified
ThemeTestbased on @markcarver's suggestion to get a failing test. I have to go sleep now. Will work on a fix tomorrow.Comment #82
almaudoh commentedAlso added #2942001: Deprecate ThemeHandlerInterface::rebuildThemeData() and use extension.list.theme service instead.
Comment #85
almaudoh commentedFixed the failures in #80 and coding standards. Still a fail patch though per #81. Expecting 3 test fails now.
Comment #87
markhalliwellThis still isn't exactly what I meant.
Themes cannot provide controllers/routes. In addition to the
theme_test.test_theme_classroute in the module, I suggest the content be rendered by the test theme itself. ThenThemeClassshould be invoked inside the.themefile in a preprocess hook or something similar.This would be a "true" baseline test for this IMO because
\Drupal::service('theme_handler')->listInfo()is what used to register installed theme namespaces and they wouldn't necessarily be available in just a normal module callback.Comment #88
almaudoh commentedOk. So a "true" baseline test implemented per #87. The
ThemeClassis invoked in a.themefile in a preprocess hook. A fail patch is attached with the new test in addition to a patch that fixes it based on the existing implementation in HEAD. I moveddrupal_classloader_register()into theThemeExtensionListpost-discovery decorations section with a todo to fix it better in #2941757: Extension System, Part IV: Properly register all installed extensions/namespaces during container generation.Interdiff is against #85. Actual fix is in
fix.txtComment #90
markhalliwellI'd say let's mark this as
@internaland/or@deprecatedsince we know this is likely going away when the other issue is fixed.Other than that... I'd say this looks good!
It's also great to know that the existing test was definitely a false positive :D
Comment #91
almaudoh commentedI actually thought about doing that for a moment, then remembered that the whole class is already marked
@internal, so that should cover the method as well. Right?Yeah. :) Great find there. This will be a good opportunity to fix it for themers.
Comment #92
markhalliwellNo, the class is only temporarily marked as
@internaluntil #2940481: Road to stabilize ExtensionList services; at which point that label will be removed.Ideally, the
registerThemeNamespaces()method will be removed entirely by #2941757: Extension System, Part IV: Properly register all installed extensions/namespaces during container generation. However, in the off chance that it doesn't, I think this should still be marked as such now (since we already have plans for this) with@internaland/or@deprecated. If it doesn't, it can then just stay as an empty method that does nothing (since the other issue would take care of this at the container level).Comment #93
almaudoh commentedOk. Makes sense.
This patch still needs profiling. Anybody up for it ;) ?
Comment #94
markhalliwellThere is no need for a config entry like this. There is no "default" engine per se. The theme engine used is determined by the theme itself, which automatically defaults to "twig" if not defined.
This still isn't right. It's still only returning a single theme engine.
There has always been the ability to have multiple theme engines installed (https://www.drupal.org/project/project_theme_engine).
The one that is actually used is determined by the active theme during rendering.
E.g. the admin theme may use a different engine than the default theme.
edit: I've even seen some cases where certain AJAX requests were rendered using a different theme engine.
One can still even use PHPTemplate (although I don't know why they would): https://cgit.drupalcode.org/phptemplate/tree/phptemplate.engine
This should return a list of all available theme engines (since they don't actually have an "install" state).
ThemeHandler::rebuildThemeDatais where theme engines where originally stored. Since they don't have an "install" state, they're all "available" and were just returned as needed.Comment #95
almaudoh commentedThis config entry is the same convention that has been used for storing installed modules and themes, it would only make sense to use this for theme engines as well.
So the question is, what does the concept of an "installed" theme engine really mean? This is what @dawehner asked in #68.5. So do we want to hold up this patch trying to figure that out?
The
'system.theme_engine.files'state entry is actually already built into the extension list system (whether theme, profile, module or theme engine). So if we're going with this, then we just return the list of all available theme engines.Comment #96
dawehnerI agree with @markcarver, we should not introduce a new concept as part of this issue. I also believe that installing a theme extension doesn't make necessarily even sense, just as pointed out like @markcarver
Comment #97
markhalliwellFor
ThemeEngineExtensionList, it just means that it should return all discovered theme engines. They have no "install" state.That's actually what #1685492: Convert theme engines into services is attempting to solve. Since that issue is likely the "end goal" with theme engines, it would ultimately make
ThemeEngineExtensionListmoot since they would no longer be an "extension" as any module would be able to define a theme engine service.For now, and in anticipation of that issue, I think we should keep
ThemeEngineExtensionListsimply for furture BC reasons.Comment #98
almaudoh commentedIn this patch I've reverted the config entry that was added in #80 for theme engines. Now
ThemeEngineList::getInstalled()will return all discovered theme engines. I have also updated the test coverage for that.Comment #100
almaudoh commentedForgot to revert the
DefaultConfigTest.Comment #101
jibranGlad to see this green. Thanks, for all the work @almaudoh. Hopefully, all the feedback has been addressed. Let's get to some profiling.
Comment #102
markhalliwellI'd do the profiling, but not currently set up to do so (nor very familiar with how to, if I'm being honest).
Comment #103
zviryatko commentedProfiled patch added in #100
tldr: ~2% performance decrease for everything except the memory.
Cold cache:
Time+553 µs (+0.02%)
2.71 s → 2.71 s
I/O Wait+55.5 ms (+3.61%)
1.54 s → 1.6 s
CPU Time-55 ms (-4.7%)
1.17 s → 1.12 s
Memory-109 kB (-0.488%)
22.2 MB → 22.1 MB
SQL Queries+56.9 ms / +13 rq
Blackfire:
- without patch and aggregation:
https://blackfire.io/profiles/c6bfa8c9-8834-41d2-a766-57fc96e646d2/graph
- with patch and without aggregation:
https://blackfire.io/profiles/957ba241-e66b-48d7-a6a9-acf25582763b/graph
- compare:
https://blackfire.io/profiles/compare/d4bea6a7-3035-4ca5-a562-23d568f779...
Warm cache:
Time+4.41 ms (+1.61%)
274 ms → 279 ms
I/O Wait+1.97 ms (+1.98%)
99.5 ms → 101 ms
CPU Time+2.44 ms (+1.39%)
175 ms → 177 ms
Memory-26 kB (-0.229%)
11.5 MB → 11.5 MB
Blackfire:
- without patch and with aggregation:
https://blackfire.io/profiles/607b82b5-f77e-4962-8f00-589cccba95d2/graph
- with patch and aggregation:
https://blackfire.io/profiles/5ecae1a8-f70b-440d-996f-37c5b86e671f/graph
- compare:
https://blackfire.io/profiles/compare/f9b21477-65a5-4fb2-8159-776bcbc650...
Comment #104
jibranThanks, this doesn't look too bad to me. Let's get some opinions from core committers.
Comment #105
dawehner@zviryatko Nice work!
I was looking at https://blackfire.io/profiles/compare/f9b21477-65a5-4fb2-8159-776bcbc650...() and I'm wondering. Have the original request been really warm? state set shouldn't happen on normal requests. Any idea why they are there?
Comment #106
zviryatko commented@dawehner, check
\Drupal\update\UpdateManager::projectStorage()it removes state for listed routes.Update: added list of routes from mentioned function:
Comment #107
markhalliwellWent ahead and re-queued the last patch (just to double check).
Other than that, I'd say that this is RTBC.
Comment #108
markhalliwellOk. I'll do the honors...
Comment #110
markhalliwellRe-roll, but should still probably RTBC
Comment #112
markhalliwellHm... seems I was behind 1 commit from HEAD somehow, whoops.
Comment #113
alexpottI've not done a deep dive review yet just a couple of quick thoughts that jump out.
As per the policy we should not add deprecations unless we also do an @trigger_error() to the code. In this case I would suggest filing followups to cope with each deprecation separately. See https://www.drupal.org/core/deprecation
There also needs to be a change record to detail the introduce of the new extension lists - ThemeExtensionList and ThemeEngineExtensionList
Comment #114
markhalliwellAgreed. I think it can be a single issue though as it should a relatively small patch. I'll fix this shortly.
There is: https://www.drupal.org/node/2709919
Comment #115
markhalliwellI went ahead and created the following issues as well:
#2972152: Deprecate ThemeHandlerInterface::rebuildThemeData and remove usages from core
#2972153: Deprecate ThemeHandlerInterface::getBaseThemes and remove usages from core
Comment #116
markhalliwellI went ahead and updated the CR as well: https://www.drupal.org/node/2709919
Comment #118
daffie commentedBack to RTBC.
Comment #119
larowlanShould we catch when $type yields a 'service not found exception, i.e. is of a type we don't support and trigger and error?
At present it would cause an uncaught exception.
Starting to feel like these might need to be tagged services with a collector to clear them all in one go? That would be the path to deprecating system_list_reset right? Follow up?
what happens if the engine doesn't exist?
Would that be a case to declare this as private and prevent subclassing or calling from children?
Are we sure this would throw an Exception? In PHP 7 it would be an \Error right? In PHP 5 it would be a fatal, not an exception right?
Should we instead be using
class_exists?I know this is test only, but shouldn't this be 5.5.9?
Comment #120
markhalliwelldrupal_get_filename()as well.twig, as per the comment above it:// Defaults to 'twig' (see self::defaults above).@internaland will be removed in #2941757: Extension System, Part IV: Properly register all installed extensions/namespaces during container generation, yes, that makes sense.$variables['message'] = 'Loading ThemeClass was successful.', which only happens after the class is constructed. If it errors, it doesn't get that value and the test would fail, yes?Comment #121
alexpottGiven that we're changing low-level extension system stuff in this issue we should also do some profiling to make sure we're not removing some static that the installer or the cold cache rebuild relies on to be performant.
#103 only does the cold cache. In the previous issue we found profiling the install also important.
Comment #122
alexpottAlso looking at https://blackfire.io/profiles/compare/d4bea6a7-3035-4ca5-a562-23d568f779...() I'm not sure we've profiled what we think we're profiling. Since I would expect some of the new functions to be listed. That said this might be blackfire because on the free version it does not list all methods called. I miss XHProf.
Comment #123
markhalliwellThe only statics we're actually removing are in
system_list()anddrupal_get_filename(). Now that they're using services and once all the extensions are found, it's cached.We could keep the statics in both of these functions for performance/BC reasons if you want? This could help mitigate any currently unforeseen performance impacts until we actually remove usages throughout core, when #2940190: [meta] Deprecations of old functions in Extension system and sub-issues are dealt with.
That being said, I seriously doubt any of this will have any negative impact moving forward.
Also, we could just XHProf PHP 5.6, since PHP 7 is likely to not really be an issue here.
What previous issue? #2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList didn't mention profiling around the installation.
Comment #124
alexpottRe the previous issue and the installer see #2208429-243: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList and onwards.
Comment #125
markhalliwellWell, considering that you already optimized
ExtensionListto take into account of this scenario, which this extends from, I don't think there's much more we can do here (aside from what I mentioned in #123).Comment #126
markhalliwellAdding this tag merely for historical purposes (as this issue is ultimately the first step in this journey).
Comment #127
dawehner+1 for making the errors way more helpful!
As a follow up we could explore to move these to the base class. These seemed to be shared between implementations
Sure, there we go: #2973439: Make extension list services tagged services
Comment #128
markhalliwell@alexpott, could you respond to #125 please? I don't think this needs more profiling for the install scenario you mentioned.
Comment #129
alexpottSo here's a comparison of installing minimal via drush with and without the patch. https://blackfire.io/profiles/compare/1de227a7-af08-4780-a6b3-93a9ea8ca8...
Interestingly it seems we have additional container builds that we did not have before. And we're calling drupal_get_filename more too. And doing more queries. We need to work out why.
We actually shouldn't be using FormattableMarkup in errors. We should be using
sprintf()or just combining the strings. All error messages are escaped anyways. Yep this was already an issue but we're changing it here so let's fix it.Comment #130
alexpottIt got the profile by doing the following:
composer require blackfire/php-sdkso I can add instrumentation to our code.to the top of the
install_drupal()function$profile = $blackfire->endProbe($probe);to the end of the functionComment #131
alexpottThe problem grows are bit with a standard install... https://blackfire.io/profiles/compare/ad7e32c1-41a0-4ffb-81f4-e144f0a968...()
Comment #132
alexpottThe reset() here looks really wrong. We were not doing a system list reset here before. How come this was added?
Comment #133
alexpottSo here's a start on fixing the problem with the increased number of queries and activity during install plus it fixes a couple of coding standards minor things.
We use the same technique as the module list to do static caching during the install process and I've also fixed #132.
Here are the comparisons:
Head to #133 - https://blackfire.io/profiles/compare/11be1ed0-74ea-4227-835e-1d900defcd... - still 52 more queries.
#120 to #133 - https://blackfire.io/profiles/compare/748235c8-3021-4756-a962-2888ab0cbf... - we've lost 139 queries - so we're heading the right way :)
Comment #134
alexpott#133 is going to fail badly. One thing that sticks out now looking at this issue more carefully is what's the point of the ThemeHandler?
Comment #135
alexpottOne reason this change is having an effect on the install is because we do:
in install_begin_request() - we're alway initialising the theme layer during the installer to work around things :(
Comment #137
alexpottRemoving this isn't great - that was added in #2872611: Optimise \Drupal\Core\Extension\ThemeHandler::refreshInfo() for the early installer. We need to ensure we maintain this.
Checking isset() and initialising to an empty array is flawed. And the reason for all the failures in the previous patch.
https://blackfire.io/profiles/compare/455a3ab8-52f1-4c70-9bb7-ed9f142a29... - closing in only 38 more queries than HEAD. Still lots more container work.
Comment #138
alexpottOkay with this patch we're now at less queries than HEAD! https://blackfire.io/profiles/compare/381a44ab-efe2-4dd1-b868-3627879385...
Comment #141
alexpottFixing the last error. This change makes no difference to the callgraph of minimal install.
Comment #142
markhalliwellOh wow! I was just expecting a yes/no :D Glad you took that on though because profiling isn't really my strong suit (especially without XHprof).
I just couldn't see how this could have been further optimized, I was wrong. My apologies.
I've reviewed the interdiffs and gave the overall patch a good once over again. Only thing that really jumpped out at me was:
Setting to CNW to fix this, but other than that I think this could be RTBC! Woo hoo!
@alexpott++
Comment #143
Anonymous (not verified) commentedInterestingly, #141 is 14 minutes slower than #138:
Graph with discrepancy in speed test runs:

Comment #144
alexpott@vaplas we need further samples for that :) so much variation on bot runs. I've kicked off some more test runs.
Comment #145
alexpottFor me there is still quite a bit of work to do here. One of the big things is should the ThemeHandler be the theme extension list service. I'm not sure that the decoupling here is worth it.
Looking at the existing ThemeHandler:
So there does seem to be some differentiation in terms of getDefault / setDefault / hasUi - but everything else is really on the extension list. Having the ThemeHandler and the theme extension list would mean that we can only have one static list cache and not both
\Drupal\Core\Extension\ThemeHandler::$listand\Drupal\Core\Extension\ExtensionList::$extensionswhich is wasteful and too many layers of caching. Also I would argue that things should just read from config to get and set the default theme so those methods and the config factory dependency shouldn't really be on the ThemeHandler.Before I start work on merging here's a patch the properly guts themehandler and calls the theme list were possible.
Comment #146
alexpottSo #145 is doing a bit less container work than #138 but is doing more YAML parsing which is odd. https://blackfire.io/profiles/compare/7abcdc68-2a88-4abd-a4bf-6ec75d9ee7...
Comment #147
markhalliwellI agree that ThemeHandler is basically useless now, just like ThemeManager will be once #2869859: [PP-1] Refactor theme hooks/registry into plugin managers happens.
Both ThemeHandler and ThemeManager will ultimately become artifacts because when they were created it was out of immediate necessity to migrate procedural code into OO code. It really didn't have a lot of architectural thought behind it (like much of the theme system's "OO conversion").
Gutting/deprecating ThemeHandler should probably be a separate follow-up issue IMO.
I'd like to see if we could possibly move the default getter/setter and hasUI methods elsewhere and get rid of the entire class.
At the very least, I think we should probably do it as a follow-up just to make sure we don't step on any toes.
Comment #150
almaudoh commentedAwesome work by @alexpott to profile and improve the patch performance. I always knew the Extension system would bring performance benefits, just didn't know where to optimise.
I'll have to find time and learn a thing or two about profiling with blackfire.io soon.
I don't think
$this->extensionsexists in theThemeHandlerclass. Maybe should be$this->listas it was before.I had these same ideas myself. Maybe we could leave the ThemeHandler in just for BC and then remove it in a follow-up issue.
Comment #151
alexpottFixing the tests and #150 - nice spot @almaudoh. We still need to understand the extra info parsing this patch causes.
Comment #152
alexpottI talked to @dawehner yesterday and he pointed out that sun's original plan had extension discovery and handling as separate things. The current patch makes extension discovery aware of installation status so it's mixing responsibilities. I've rolled a patch locally that combines ThemeHandler and ThemeExtensionList which completes the mixing of responsibilities. Thinking some more I don't think this is a good way to go. I think the ThemeHandler should handle installed themes etc and the ThemeExtensionList should handle the listing.
Comment #153
alexpottSo in light of #152 we already have ModuleHandler and ModuleExtensionList well and truly entangled. And the extension listing stuff already has the concept of installation status :( ho hum but let's try not to make it worse in this issue.
In HEAD this function only works for themes it doesn't work for modules or anything. With this patch we change it to work for every type again. That's not a good idea. We also break it for the
filepathstype. Not that that is documented. Imo we shouldn't change what this method can return.Let's not add these methods we don't need to.
system_list()is dead code and we can do the logic that's need in ThemeHandler.I'm not sure we should call this alter... and then trigger a proper alter next in the code. That's confusing.
Comment #154
alexpottHere's a start on #153.
Comment #155
alexpottHere's a proper deprecation of system_list(). I think because this only lists themes we need to do this here - also we need to ensure we don't change it's behaviour.
Comment #158
markhalliwellI'm confused, you said in #113 that [triggering] deprecations should be done in a follow-up issue (so we can remove code that uses it and not trigger errors). That's why I created the follow-up issues.
Comment #159
alexpottFixing the test.
Re #158 - the only use of system_list() in HEAD is to list themes. This patch makes fundamental changes to it and in earlier version unnecessarily expanded system_lists()'s capabilities. In reviewing all the code it makes it obvious that with this patch core has no reason to call system_list() anymore. Therefore this patch should take care to deprecate it. Especially as this patch extended the public API of the extension listing system to support system_list() - which doesn't make sense to me. It hard to explain to someone the difference between
ExtensionList::getInstalled()andExtensionList::getAllInstalledInfo()but now we don't have to becauseExtensionList::getInstalled()is no longer being added.Comment #160
Anonymous (not verified) commented#144: you are right. The subsidence appears only when all the tests are run. I opened a separate issue for it #2975163: InstallUninstallTest is taking 20 minutes to run.
Comment #161
alexpott@vaplas does this patch make InstallUninstallTest worse?
Comment #162
Anonymous (not verified) commentedTL;DR: Yes, but perhaps it is beyond the scope of the current issue :)
Not (or nit worse), if run only InstallUninstallTest.
Yes if run all tests - yes:
And many other tests run more slowly:
In HEAD only 5 tests run > 300 seconds:
After #141 - 31 tests:
I assume that this is due to the APCu fragmentation,
because it almost does not affect the WTB tests (they works without APCu)(Edit: My bad,WTB::InstallUninstallTestalso much slower, when run all tests). But so far I have not found evidence.Perhaps related issues:
Comment #163
alexpottSome more improvements. We now have less queries and less info parsing. Obviously we still have more container stuff because we have another service - https://blackfire.io/profiles/compare/b19f2764-50c2-4241-9168-0746436d22...
Comment #164
Anonymous (not verified) commented#163 has no problems described in #162 🚀
RTBC++ from this point of view, although I'm not competent in this issue. Are there any unaddressed feedbacks?
Comment #165
Anonymous (not verified) commentedNo objections, so RTBC 💎
Comment #166
almaudoh commentedIt sounded like @alexpott still had some things he wanted to do here. But if not, I'm RTBC+ myself.
Comment #168
markhalliwellComment #169
jofitzRe-rolled.
Comment #170
phenaproximaRe-roll passed Drupal CI, so restoring RTBC.
Comment #171
alexpottThis needs to be done.
Comment #172
jofitzReplaced the @todo.
Comment #173
phenaproximaNice. Restoring RTBC once all backends are green.
Comment #175
jofitzTests are passing again now after a blip over the weekend. Here's a little patch to correct a coding standards error.
Comment #176
jofitzSeeing as this is such a minor tweak I'm going to cheekily return this to RTBC, safe in the knowledge the tests will pass.
Comment #178
daffie commentedBack to RTBC. The testbot fails are not related to this patch.
Comment #180
jibranComment #182
markhalliwellCan we please get this in 8.6.x so contrib code doesn't have to use special use cases for themes when dealing with the extension system. This has been sitting at RTBC for basically a month.
Comment #183
daffie commentedI think that the committers are waiting for 8.7, because it is a large change to a very fundamental part of Drupal's core. If there is some strange side affect as a result of this patch we have 6 months to fix it.
Comment #184
markhalliwellNo. It just got "overlooked/deprioritized" (like most theme related issues) and was automatically "flagged" as such by the system.
The majority of the ExtensionList code/services was introduced in #2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList (which has already been committed and will be in 8.6.0).
This issue split from that one because it was deemed "significantly large" all on its own.
IMO, that was a mistake, but meh... whatever. Baby steps I guess.
Regardless of that fact, I don't believe this issue should be pushed to 8.7.x simply because it "didn't make the cut" for the initial alpha.
This is a task, not a feature (perhaps that's why it wasn't prioritized... idk).
It should be committed so it flushes out the entire ExtensionList code/services API that was introduced in 8.6.x.
Not doing so would be a huge PITA/oversight for contrib upgrading their code.
Comment #185
phenaproximaFor whatever it's worth, I entirely agree with @markcarver. This patch seems to be ready and has been for a while. What do we gain by leaving an incomplete API in core? People will just work around it (we Drupalists are a resourceful bunch), those hacks will ossify over time, and we'll just end up introducing even more complexity around the lumbering beast that is the extension system. Why not just land this in 8.6 for API completeness?
Comment #186
dsnopekI concur that this would be really valuable to get in sooner rather than later. It is just the last finishing touch on a many-years-long effort to refactor the extension system. While it does touch some pretty low-level code, the changes are much smaller than any of the previous already-committed issues in this refactor. Let's finally finish this!
Comment #187
almaudoh commentedIt would be really unfortunate if this didn't get into 8.6 because then we'd be having two different API''s for the module/profile extension system and the theme extension system. That would be a huge WTF with additional tech debt we would have to manage later.
Comment #188
almaudoh commentedComment #190
daffie commentedComment #191
oriol_e9gOK. We want this, go to reroll.
Comment #192
oriol_e9gComment #194
oriol_e9gWe have moved the theme tests recently and we need to test the testClassLoading as a Functional test.
Comment #195
oriol_e9gOnly to clarify.
The old testClassLoading() was in core/modules/system/src/Tests/Theme/ThemeTest.php
Today we splited ThemeTest.php into Kernel and Functional tests, and moved the testClassLoading() as a Kernel test here: #2863429: Theme: Convert system functional tests to phpunit
In this patch we have updated this test code and the new version needs to live as a Functional test. I have not changed any piece of code, only moved code around it.
Comment #196
catchThis doesn't include the calls to setPathname that ModuleExtensionList does, and we don't have a container.themes extension parameter. Is this OK? Where does the theme location actually come from for each request now?
Comment #197
alexpottIn each request when \Drupal\Core\Theme\ThemeManager::getActiveTheme() is called we go through theme initialisation. I.e. we then call \Drupal\Core\Theme\ThemeNegotiator::determineActiveTheme() which ends up calling \Drupal\Core\Extension\ThemeHandler::listInfo() which will call \Drupal\Core\Extension\ThemeHandler::addTheme() for all installed themes. This uses the cached extension info to set up the class loader and populate the theme list with the relevant info which includes the theme's pathname.
Comment #198
catchThanks I think that covers #196 fine. It's still slightly odd the way we handle active vs. installed themes but this patch overall will help clarify some of that.
Comment #200
daffie commentedBack to RTBC.
Comment #202
daffie commentedBack to RTBC.
Comment #204
daffie commentedBack to RTBC again.
Comment #205
alexpottHmmm.... the other rtbc's don't seem to be random failing as much as this one. Maybe this is introducing a random?
Comment #207
markhalliwellOr maybe this issue has just been sitting long enough that it keeps having to get re-rolled/tweaked due to the other commits.
Comment #208
alexpott@markcarver I'm not sure about that. There are issues that have been rtbc for longer... for example https://www.drupal.org/pift-ci-job/1037332
Comment #209
markhalliwellI still think that they're just random test failures due to other code/commits...
I mean from above: https://www.drupal.org/pift-ci-job/1037348
This issue has absolutely nothing to do with that lol
This happens (a lot) in other issues too. Just the nature of the new Drupal CI + new JavaScript testing work that's being done.
Whenever these "failures" are manually re-queued for a re-test, everything passes.
Comment #210
markhalliwellComment #212
phenaproximaThe random failures are happening on this issue so often that I'm starting to wonder if @alexpott hasn't got a point...
Comment #213
oriol_e9gAlways fails randomly functional javascript tests related with Media or Layout Builder.
I don't know how can be related with this issue :(
Comment #214
ndf commentedAll failed tests since #199 do contain a failure in
Drupal\FunctionalJavascriptTests\Ajax\AjaxTest::testInsertAjaxResponseThe test 1034656 (5 Aug 2018 at 15:55 CEST) has additional failures in Media and Layout_builder tests.
All of the failing test are
FunctionalJavascripttests.Failing AjaxTest
Drupal\FunctionalJavascriptTests\Ajax\AjaxTest::testInsertAjaxResponsetests multiple inserts throughDrupal.theme.ajaxWrapperMultipleRootElementsandDrupal.theme.ajaxWrapperNewContentIt fails after
and
Failing media test
failing test: https://www.drupal.org/pift-ci-job/1034656
Drupal\Tests\media\FunctionalJavascript\MediaSourceFileTest::testMediaFileSourcefails when validating$assert_session->waitForElementVisible('css', 'fieldset[data-drupal-selector="edit-source-configuration"]')Failing Layout builder test
failing test: https://www.drupal.org/pift-ci-job/1034656
Drupal\Tests\layout_builder\FunctionalJavascript\AjaxBlockTest::testAddAjaxBlockfails atDon't know why or if this is related with this issue or truly random.
I do see a pattern that the fails are related to waiting on ajax-callbacks.
Comment #215
ndf commentedJust re-scheduled all tests and again same failing ajax test in
Drupal\FunctionalJavascriptTests\Ajax\AjaxTest::testInsertAjaxResponseComment #216
oriol_e9gAll tests are green and we have launched all tests in 12 environments (see #194). I can not see any error. I'm still thinking that they are randomly javascript tests errors.
Comment #217
berdirThis is a low-level issue, it affects places in code that are used by basically everything and therefore can affect basically anything else.
Those test fails might be random, but if the random fails in those tests are caused by this patch, then it's still a problem because I haven't seen those tests failing in other issues. Could be a race condition that only exists with the changes done here.
Comment #218
almaudoh commentedIs there a way we could set up multiple tests running on this patch to confirm this? Or will it overload the test server?
Comment #219
catchYou can hack the testing system so it runs the same test loads of times (and none of the others), this has been used on random test failures before, and might help to determine whether this is some kind of concurrency issue or specific to the tests that are failing.
Comment #220
markhalliwellI'm not convinced this issue is the actual cause of these supposed random test failures. At most, it may simply expose already broken tests/code elsewhere. The patch itself does not touch the code that's failing. Even though it is low-level, if it were truly broken, we'd see a lot more catastrophic failures than this since it is such an integral part of the extension system.
Setting back to CNR to trigger tests.
Comment #221
dawehnerI do agree with the worry of @berdir, @alexpott and others. This really low level piece of code is triggered in code paths, you can't necessarily control. Looking through the comments there is an awful amount of failures over time :(
After that I tried to review the patch explicitly for sources of race conditions.
It feels like the removal of systemListReset() at the end could be a reason for a race condition?
Comment #222
markhalliwellDo you mean that
ThemeInstaller::uninstallis resetting the theme handler outside ofThemeInstaller::resetSysteminstead of in it?I think it was removed in and around #137 when @alexpott was doing all the performance optimization patches, which is kind of also when all these "random failures" starting happening.
Not sure why it was added to
ThemeInstaller::uninstalland didn't replace$this->systemListReset()inThemeInstaller::resetSystem. Maybe he could help elaborate a bit more. It was a bit difficult to follow the rapid changes that were made.Also, to clarify, I'm really not throwing @alexpott under the bus either (his work there was amazing). Just trying to help pinpoint what's going on so we don't ship with a half-baked extension list services in 8.6.0.
I mean, I guess we could try moving that one line?
Comment #223
markhalliwellThis is extremely frustrating and absolutely ridiculous to have these kinds of double standards in core. This is yet another example of the theme system being intentionally excluded and thought of as a "non-priority sub-system". I'd say a hell of a lot more, but I'm way too upset and don't want to offend anyone unintentionally.
Comment #224
markhalliwellFTR... not having this issue in has affected my ENTIRE contrib plans for at least the next 6 months across a multitude of projects. I'll now need additional boilerplate code and special handling for theming extensions in 8.6.x. Thanks a lot!
Comment #225
markhalliwellCan anyone actually pin-point what the real issue is here?
Seems like this was stalled on hypothetical "random test failures" without any real proof and then abandoned because... "reasons".
Comment #226
phenaproximaWell, looking at the many failures of the most recent patch, I see a lot of failures in Drupal\FunctionalJavascriptTests\Ajax\AjaxTest. It might be prudent to run that specific test about 100 times locally, with this patch applied, and see if there are any failures. If there are, then we know this patch is breaking stuff and will need to track it down.
That's maybe not the most rigorous way to find a random failure, but it's better than nothing.
Comment #227
phenaproximaRerolled against 8.7.x, and adjusted drupalci.yml so it will only run AjaxTest 100 times. Let's see what happens.
Comment #228
alexpott@phenaproxima I think we need to run all the functional javascript tests. There are know random fails in that test suite. For example the "not clickable thing" in a media test but apart from that its pretty stable.
There is another awful possibility - the changes this makes has some effect when running multiple tests. In general the tests are pretty isolated but some things are hard to predict.
Comment #229
phenaproximaHere is a variant which runs all JS tests (and only the JS tests) 50 times, with a concurrency of 15.
Comment #230
dsnopek@phenaproxima Thanks for taking action to move this forward!
Comment #232
phenaproximaLooks like the build timed out because 110 minutes is the limit. Reducing the number of test suite runs to 42, just to see if we can at least get a complete one.
Comment #233
phenaproximaI have done some detective work, largely consisting of talking to @xjm, and I have reason to believe that the random failures which plagued #194 are no longer an issue.
I'm told that, in late July 2018 (July 17-22 or so, according to @xjm), Drupal\FunctionalJavascriptTests\Ajax\AjaxTest began suffering a spate of random failures. Apparently they were addressed when some sort of change, the nature of which I am not clear on, was made to testbot.
Here is an example of the random failures that AjaxTest experienced during that time frame: https://www.drupal.org/pift-ci-job/1023212. Notice that it looks very, very similar to the failures in #194.
I've searched open and closed issues and I've been unable to find any further documentation or logs to back this up, but it seems that the circumstances of #194's random failures coincide suspiciously with the period of time during which AjaxTest was randomly failing.
However, "it seems fixed now" isn't quite good enough to get this patch committed. Although I'm doubtful that this patch is introducing a random failure, it carries the burden of proof. So, I'm attaching the following patches:
Each of these patches:
Let's see what happens. If it all comes back green, I for one will be pretty convinced that there is no random failure being introduced by this patch. AjaxTest's July failures may have been caused, then, by (take your pick):
If you (especially if you're a committer) know more about the circumstances at that time, feel free to chime in. In the meantime, let's put this patch through its paces.
Comment #236
markhalliwellSo it isn't this issue that's causing the failures... interesting...
Comment #237
alexpottSo #233 proves that we have random fails in JS tests without this patch. And in the same tests as seen on this patch. I'm still wondering if this patch will cause the frequency of fails to increase because as stated at the time, I did not see any other issue fail with the same regularity as this one. Hopefully not.
Let's make the latest patch the correct patch to rtbc so any rtbc retesting will be done against the correct patch.
Patch attached fixes the reroll so that ThemeHandlerTest passes - it was where to the conflict was - due to #2575105: Use cache collector for state.
If we're unsure that we're going to continue to need the class loader in ThemeHandler then we should inline
\Drupal::service('class_loader')and not add a method. If we think ThemeHandler is going always need the class loader then we should inject it. I've gone for inlining the class_loader since we've already got #2941757: Extension System, Part IV: Properly register all installed extensions/namespaces during container generation to address theme class loading.Patch attached also fixes some comments that this patch makes incorrect.
We also need to add something for the new release note snippet section on issue summaries.
Comment #238
alexpottWrote something for the release note snippet.
Comment #239
alexpottFor some reason my re-roll didn't put the new testClassLoading on the right ThemeTest. Weird. Re-did it and now it did.
Comment #241
markhalliwellJust did a quick re-review and a couple of notes:
These all need to be changed to 8.7.0 now.
Is there a specific follow-up issue for this?
Comment #242
markhalliwellAlso, inlining the class loader is fine with me. I wasn't sure what snippet you were referring to at first but then realized you already inlined it in the latest patch, which makes perfect sense when read as a whole:
Comment #243
alexpottFixed #241.1
#241.2 is interesting. Given we're ripping up the ThemeHandler constructor I see no need for it to be an optional argument. I don't think the service is ever set this way in core.
It's good to see that #239 fail on sqlite with Javascript tests much the same way that HEAD is failing more often on SQLite - see https://www.drupal.org/pift-ci-job/1132428
Comment #244
markhalliwellI'm tentatively switching this back to RTBC.
Is there an issue for figuring out the random test failures already created?
While it may be more fequent in SQLite, #233.3 indicates that it can happen in MySQL too.
Comment #245
catchWent over this again and no serious complaints, also good to get this in early-ish in the 8.7.x cycle so there's time to flush out any issues it might introduce.
Committed 10722cd and pushed to 8.7.x. Thanks!
Comment #247
alexpottA very quick follow-up. This patched added a public weight property to the Theme extension object with no discussion. We should remove it asap - see #3016968: Remove weight public property from theme extensions
Comment #248
alexpottAlso #3015812: Introduce new Theme extension object and properly deprecate REGIONS_VISIBLE and REGIONS_ALL starts to build a more function extension object for Themes which hopefully will be the start of making extension objects less of a dumping ground and a bit easier to deal with.
Comment #249
wim leersPublished https://www.drupal.org/node/2941753. Note that "introduced in" says 8.6, perhaps that should become 8.7 since this portion only landed in 8.7?