Closed (fixed)
Project:
Drupal core
Version:
8.6.x-dev
Component:
plugin system
Priority:
Major
Category:
Bug report
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
18 Jul 2018 at 23:16 UTC
Updated:
20 Nov 2018 at 16:34 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
berdirComment #3
megachriz@Berdir
What did you need to do to make https://github.com/EdeMeijer/serialize-debugger work? Adjust the library? Adjust code in Drupal?
I get an error when trying the following code in a method called
buildPaneForm()whereserialize($this)failed:The error:
Comment #4
berdirThat is what happens because it manually calls the __sleep(), so this is expected.
The difference is that in serialize(), this recursion happens internally and you can't debug it. Now you have a nice and clear backtrace, all you need to do is set a breakpoint now in Connection::__sleep() and you can look at the object hierarchy that is passed through.
You could also do the same with some print statements in e.g. "RecursiveResolver->resolve" but that will be harder to follow.
Comment #5
megachriz@Berdir
Thanks for your quick reply. I was expecting that the library would stop on an exception and then print where things went wrong.
In my case \Drupal\Core\Entity\EntityTypeManager apparently is the culprit. When inspecting each \EdeMeijer\SerializeDebugger\Node in the trace, I got a chain of the following objects:
Comment #6
berdirEntityTypeManager isn't the culprit, that is a service, that already should not be serialized.
> Drupal\ukkbaccount\Account\Profile
What is that object? Is it a service or a custom object you create that has values? Possibly tht one should use the DependencySerializationTrait to drop the reference to EntityTypeManager on serialize.
Comment #7
megachrizAh, thus services should generally not be serialized at all.
\Drupal\ukkbaccount\Account\Profile is a custom object with several account related methods. Its constructor asks for the entity type manager and an account. Adding a DependencySerializationTrait there solves the issue in my case! An ajaxified form element now gets properly updated.
Would it be a good idea for a better developer experience to throw exceptions in
__sleep()in all service classes as well? This way more developers will be informed that you should avoid serializing these.Comment #8
phenaproximaThis will need tests...
Comment #9
tim.plunkettThis blocks #2976148: Layout-based entity rendering should delegate to the correct section storage instead of hardcoding to either defaults or overrides
Comment #10
phenaproximaHere, have a patch with a test!
Comment #11
tim.plunkettIf this moves from a unit to kernel test, it should move to
core/tests/Drupal/KernelTests/Core/Pluginas well (or just make a new class)Weird using an object property for this instead of a local variable.
This comment is a little odd because it references how code used to be instead of how things are.
I think we need something asserted here.
Comment #12
phenaproximaFor the record, we could solve all future occurrences of this problem if we would never make service getters into implicit setters.
This is an anti-pattern: it's not a getter, it's a setter. And we wonder why we run into sudden serialization failures. We should reject this anti-pattern forever (in fact, we should deprecate it in Drupal 8, and remove it in Drupal 9). Of course, it'd still be possible to cause a serialization failure by explicitly setting the service (setTypedDataManager()) and serializing the consuming object, but at least then it would be traceable to an explicit method call somewhere, and could be addressed by module authors rather than the onus being on core.
In any case, the method says get, but it actually sets. We need to not do that. Not in this issue, necessarily, but we should not allow any more instances of this anti-pattern to land in core. Looks like I found the hill I'm willing to die on!
Comment #13
phenaproximaAll feedback from #11 addressed here. I moved the test to the KernelTests namespace and rewrote the mock object to use Prophecy.
Comment #15
tim.plunkettLooks great, thanks!
Comment #16
tim.plunkettComment #18
phenaproximaWhoops! I had the test in the wrong namespace. Kicking directly back to RTBC on the assumption that it will go green this time.
Comment #19
larowlanAdding issue credits
Comment #22
larowlanCommitted b1ad4a8 and pushed to 8.7.x. Thanks!
C/p as c0c662c427 and pushed to 8.6.x
Thanks
Comment #23
phenaproximaThanks, @larowlan!
For anyone who's interested, I opened an issue pleading with the framework managers to deprecate the "implicit setter" anti-pattern which caused this bug: #3011620: Deprecate the "implicit setter" anti-pattern
Comment #24
tacituseu commentedThis introduced test failure on PHP 5.5:
https://www.drupal.org/pift-ci-job/1113676
https://www.drupal.org/pift-ci-job/1113681
Comment #25
tim.plunkettThat's
shouldBeCalledTimes(1)in older PHPSpec.But it's unnecessary here anyway.
Comment #26
alexpottCommitted and pushed bb9fb66dd7 to 8.7.x and d935fc4871 to 8.6.x. Thanks!
Ran tests locally on PHP5.5,5.6 and 7 and they pass.