Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Drop \Serializable implementations #30051

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 17, 2019
Merged

Drop \Serializable implementations #30051

merged 1 commit into from
Feb 17, 2019

Conversation

renanbr
Copy link
Contributor

@renanbr renanbr commented Jan 31, 2019

Q A
Branch? master
Bug fix? no
New feature? no
BC breaks? yes, it removes \Serializable interface from many classes
Deprecations? no
Tests pass? yes
Fixed tickets n/a
License MIT
Doc PR n/a

This PR replaces Serializable implementations with __sleep() and __wakeup().

Changes touch these components:

  • Config
  • DependencyInjection
  • Form
  • HttpKernel
  • Validator

@renanbr
Copy link
Contributor Author

renanbr commented Jan 31, 2019

This is a work in progress.

There are some issues to be solved.

KernelInterface API

I'm not able to mesure the impact of droping \Serializable from KernelInterface, not sure if we should do that in a minor release.

Tests

Traces into objects

This new serialization strategy injects a trace into the serialized objects.
To make some tests pass I had to clone these objects to keep their original instances clean.
Here the list of tests changed:

  • Symfony\Component\Config\Tests\Resource\ComposerResourceTest:testSerializeUnserialize()
  • Symfony\Component\DependencyInjection\Tests\Config\ContainerParametersResourceTest:testSerializeUnserialize()
  • Symfony\Component\Routing\Tests\RouteTest:testSerialize()
  • Symfony\Component\Routing\Tests\RouteTest:testSerializeWhenCompiled()
    • This one is interesting because there is a internal object with the same behavior as its parent

Tests realying on serialized strings

Symfony\Component\HttpKernel\Tests\DataCollector\DumpDataCollectorTest relied on internal serialization engine. I've updated it, but it still depends on the internal implementation. I created a ExposedDumpDataCollector class that expose some internal variables for test purposes.

Tests failing

  • Symfony\Component\Routing\Tests\RouteTest:testSerializedRepresentationKeepsWorking()
  • Symfony\Component\Config\Tests\ResourceCheckerConfigCacheTest:testCacheIsNotFreshWhenUnserializeFails()
    • I guess it's related to Symfony\Component\Config\ResourceCheckerConfigCache:safelyUnserialize()

@nicolas-grekas nicolas-grekas added this to the next milestone Feb 1, 2019
@nicolas-grekas
Copy link
Member

I would consider implementing Serializable an internal implementation detail, which means I'm fine removing it on these classes on master. No BC break here :)

@renanbr
Copy link
Contributor Author

renanbr commented Feb 1, 2019

@stof, using __sleep without transient attribute will break serialization for child classes (if parent class has private attributes in the bulk).

In other words: Serializing extended classes won't work anymore.

Real example: I ketp the trasient attribute in the Symfony\Component\Routing\CompiledRoute in order to keep Symfony\Component\Routing\Tests\RouteTest:testSerializeWhenCompiledWithClass() green.

Here is a list of classes that mention private attributes in __sleep():

  • Symfony\Component\Config\Resource\ClassExistenceResource
  • Symfony\Component\Config\Resource\ComposerResource
  • Symfony\Component\Config\Resource\DirectoryResource
  • Symfony\Component\Config\Resource\FileExistenceResource
  • Symfony\Component\Config\Resource\FileResource
  • Symfony\Component\Config\Resource\GlobResource
  • Symfony\Component\Config\Resource\ReflectionClassResource
  • Symfony\Component\DependencyInjection\Config\ContainerParametersResource
  • Symfony\Component\Form\FormError
  • Symfony\Component\HttpKernel\Debug\FileLinkFormatter
  • Symfony\Component\Routing\Route

Please, check if I should revert it for some of them.

Here is the list of classes mentioning only protected attributes in __sleep():

  • Symfony\Component\HttpKernel\DataCollector\DataCollector
  • Symfony\Component\HttpKernel\Kernel

Here is the list of classes I did changed the transient attribute approach:

  • Symfony\Component\Form\Extension\DataCollector\FormDataCollector
  • Symfony\Component\HttpKernel\DataCollector\DumpDataCollector

@nicolas-grekas s/list(...)/[...] done


Tests still failing:

  • Symfony\Component\Config\Test\ResourceCheckerConfigCacheTest::testCacheIsNotFreshWhenUnserializeFails
  • Symfony\Component\Routing\Tests\RouteTest::testSerializedRepresentationKeepsWorking

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, with a minor comment.
Let's make tests pass and good to go.
We could and should IMHO make all these classes final, in another PR if you're up to.

@nicolas-grekas
Copy link
Member

Actually, we cannot do that for DataCollector as that breaks classes like e.g.
https://github.com/intbizth/toro-admin-bundle/blob/fc85a454fa8c22daffdd6e4ac713b8ea95d23990/DataCollector/ToroDataCollector.php

Maybe split the data-collector related changes to a separate PR to move the rest forward?

@renanbr
Copy link
Contributor Author

renanbr commented Feb 5, 2019

I think we can drop \Serialize nowhere, because related methods become @internal one week ago. We cannot be sure no one is overwriting these methods in other classes 😒

@nicolas-grekas
Copy link
Member

And we still need to move forward, so we need plans :)
Mine would be to drop Serializable from resources and mark them @final because that looks safe enough,
and remove @internal from the base data collector btw, then consider data collectors in a separate PR.

@renanbr
Copy link
Contributor Author

renanbr commented Feb 8, 2019

Updates:

  • Reverted changes in DataCollector
  • Some classes become @final

❗ Test failing ResourceCheckerConfigCacheTest::testCacheIsNotFreshWhenUnserializeFails

It seems the strategy applyed in ResourceCheckerConfigCache:safelyUnserialize() does not work with __sleep() payload.

Here is an example where native unserialize() works, and safelyUnserialize() doesn't: https://3v4l.org/0Chn9

@chalasr
Copy link
Member

chalasr commented Feb 11, 2019

OK for dropping \Serializable on my side but still, it is a BC break that should be mentioned in CHANGELOG/UPGRADE files IMHO. Classes made @final may also be documented as anything that triggers notices.

@nicolas-grekas
Copy link
Member

Changelogs updated. Not sure about upgrade files, so I didn't update them.

@nicolas-grekas
Copy link
Member

Thank you @renanbr.

@nicolas-grekas nicolas-grekas merged commit f8bf973 into symfony:master Feb 17, 2019
nicolas-grekas added a commit that referenced this pull request Feb 17, 2019
This PR was merged into the 4.3-dev branch.

Discussion
----------

Drop \Serializable implementations

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | yes, it removes `\Serializable` interface from many classes
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | n/a
| License       | MIT
| Doc PR        | n/a

This PR replaces [Serializable](https://secure.php.net/serializable) implementations with [__sleep() and __wakeup()](http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.sleep).

Changes touch these components:

- Config
- DependencyInjection
- Form
- HttpKernel
- Validator

Commits
-------

f8bf973 Drop \Serializable
@renanbr renanbr deleted the drop-serializable branch March 14, 2019 20:51
@nicolas-grekas nicolas-grekas modified the milestones: next, 4.3 Apr 30, 2019
@fabpot fabpot mentioned this pull request May 9, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants