Skip to content

Comments

Remove thecodingmachine/safe dependency#1484

Draft
SjorsO wants to merge 2 commits intoMyIntervals:mainfrom
SjorsO:explicitly-check-for-false
Draft

Remove thecodingmachine/safe dependency#1484
SjorsO wants to merge 2 commits intoMyIntervals:mainfrom
SjorsO:explicitly-check-for-false

Conversation

@SjorsO
Copy link

@SjorsO SjorsO commented Jan 27, 2026

This PR achieves the same as #1482 but with a different approach.

I've kept the thecodingmachine/phpstan-safe-rule PHPStan rule. I've disabled this rule for test classes, I don't think these unsafe functions are a concern in unit testing code.

The maintenance burden of this PR is lower than my previous PR. With this approach, any new code that uses unsafe functions will fail the PHPStan check. This code can then be changed to explicitly check for false, and then the PHPStan error can be ignored with /** @phpstan-ignore theCodingMachineSafe.function */

}
return iconv('utf-32le', $this->charset, $utf32EncodedCharacter);
/** @phpstan-ignore theCodingMachineSafe.function */
return \iconv('utf-32le', $this->charset, $utf32EncodedCharacter);
Copy link
Author

Choose a reason for hiding this comment

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

The ?string typehint on this method will throw if iconv returns false

if (preg_match($expression, $input, $matches, PREG_OFFSET_CAPTURE) !== 1) {
/** @phpstan-ignore theCodingMachineSafe.function */
if (\preg_match($expression, $input, $matches, PREG_OFFSET_CAPTURE) !== 1) {
throw new UnexpectedTokenException($expression, $this->peek(5), 'expression', $this->lineNumber);
Copy link
Author

Choose a reason for hiding this comment

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

No need to check for false here. If this preg_match returns false then we'll already throw an exception

// Whitespace can't be adjusted within an attribute selector, as it would change its meaning
$this->selector = !$hasAttribute ? preg_replace('/\\s++/', ' ', $selector) : $selector;
/** @phpstan-ignore theCodingMachineSafe.function */
$this->selector = !$hasAttribute ? \preg_replace('/\\s++/', ' ', $selector) : $selector;
Copy link
Author

@SjorsO SjorsO Jan 27, 2026

Choose a reason for hiding this comment

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

preg_replace cannot return false. The dependency has preg_replace as a special case.

I think it should be fine to use the normal version of preg_replace

Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Author

Choose a reason for hiding this comment

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

You're right, I missed that. I've pushed a commit that checks for null

@coveralls
Copy link

coveralls commented Jan 27, 2026

Coverage Status

coverage: 70.34% (-1.0%) from 71.315%
when pulling 2320afc on SjorsO:explicitly-check-for-false
into 9641004 on MyIntervals:main.

/** @phpstan-ignore theCodingMachineSafe.function */
preg_match('/\\s/', $parserState->peek(1, -1)) !== 1
/** @phpstan-ignore theCodingMachineSafe.function */
|| preg_match('/\\s/', $parserState->peek(1, 1)) !== 1
Copy link
Author

Choose a reason for hiding this comment

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

if either of these returns false we'll already throw an exception

@JakeQZ
Copy link
Collaborator

JakeQZ commented Jan 28, 2026

Appreciate your efforts, @SjorsO (code changes look solid), but I honestly don't think this is the best way forward. I think we need to resolve the bloat in the in the 'Safe' package, for which I created thecodingmachine/safe#706, and have had a response.

@SjorsO
Copy link
Author

SjorsO commented Jan 28, 2026

... but I honestly don't think this is the best way forward. I think we need to resolve the bloat in the in the 'Safe' package

Given how widely used PHP-CSS-Parser and emogrifier are, I consider getting rid of any dependency a huge win.

Even if thecodingmachine/safe manages to slim down and remove all the docblocks and other PHP versions, it still autoloads 79 files that contain 1100+ functions (!!), I find this hard to justify, especially considering the alternative is simply checking for false.

I think this PR is a nice middle ground: no dependency that thousands of people have to install, but still a PHPStan rule that warns about unsafe usage during development.

@oliverklee oliverklee changed the title Remove thecodingmachine/safe dependency (2) Remove thecodingmachine/safe dependency Jan 28, 2026
@JakeQZ
Copy link
Collaborator

JakeQZ commented Jan 29, 2026

thecodingmachine/safe#660 is another reason to avoid using this dependency. In WordPress, each plugin (or theme) brings in its own versions of each dependency, which leads to conflicts, though, in fairness, that is an issue with WordPress.

@oliverklee oliverklee marked this pull request as draft February 9, 2026 21:34
@oliverklee
Copy link
Collaborator

Marking this as draft as we're currently working to drastically shrink that package in thecodingmachine/safe#706.

We should revisit this PR here once a new version of Safe has been released.

@JakeQZ
Copy link
Collaborator

JakeQZ commented Feb 15, 2026

Marking this as draft as we're currently working to drastically shrink that package in thecodingmachine/safe#706.

We should revisit this PR here once a new version of Safe has been released.

With version 3.4, the size is reduced from 6.31Mb to 1.58Mb.

To put it in context, this is comparable to the size of one or two photos in HD quality.

Another factor that impacts website managers is the number of individual files. Hosting providers using cPanel usually impose a limit on the number of file handles. The new version reduces the number of files from 573 to 318.

The new version is only availble for PHP versions >=8.1, and I don't expect will be backported - the older PHP versions are already EOL.

Where do we go from here?

I have no strong opinion, but don't see the download size and number of files as a significant impact, and would prefer to use the library to keep the code robust and clean, without having to implement additional checks and tests.

@oliverklee
Copy link
Collaborator

but don't see the download size and number of files as a significant impact, and would prefer to use the library to keep the code robust and clean, without having to implement additional checks and tests.

I fully agree.

@SjorsO
Copy link
Author

SjorsO commented Feb 16, 2026

For the record, I still strongly feel that adding 1.58mb and 318 files to thousands (millions?) of applications is way too much.

Removing this dependency is a good step to prevent everyone's vendor directory from turning into a second node_modules.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants