Repository navigation
Add a portability audit script (npm run portability) - #58
Merged
Merged
Conversation
scripts/portability-audit.cjs (npm run portability) tells which expressions of a code base do not mean the same thing in PHP (Symfony) and in JavaScript, from the expressions alone, without any data. - Reads expressions from a JSON or text file, from stdin, or extracts them from source code (--extract): PHP attributes and annotations, YAML / XML configuration (security:, condition:, guard:, @=...), evaluate() calls. - Every leaf of an expression (variable, property chain, function call) becomes a placeholder whose type is inferred from how it is used; the expression is evaluated with the "portable" semantics on values of three kinds: typical values, edge values (0, "", "0", [], null) and values of the wrong type. - Reports the share of portable expressions per regime, the causes, which expressions would give another result with the rules of 2.x than with the default ones of 3.0, and what could not be parsed. - --fail-on <regime> sets the exit code for CI, --json writes the report, --seed makes it reproducible, --lib audits an installed package. - --php-symfony <dir> also evaluates every sample with Symfony's own PHP (scripts/portability-audit.php) and lists the answers that differ. The core is importable and takes the library as a parameter, so the tests run it against the sources; the PHP comparison is opt-in like the other PHP checks and runs in the CI job that already has PHP and Symfony. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Turns the one-off portability audit into a repo script:
scripts/portability-audit.cjs(npm run portability). Given expressions, or a source tree to extract them from, it tells which ones do not mean the same thing in PHP (Symfony) and in JavaScript. It needs no data.How it works
An expression has no data, so every leaf (a variable, a property chain like
object.getOwner(), a call likeis_granted('X')) becomes a placeholder, its type is inferred from how it is used (an operand of<is a number, the left ofmatchesa string...), and the expression is evaluated with the'portable'semantics on values of three kinds:ordinaryedge0,"","0",[],nullmixedThe report gives the share of portable expressions per regime, the causes, which expressions would give a different result under 3.0's default than under 2.x's rules (the number to read before upgrading), and what could not be parsed.
--php-symfonyalso evaluates every sample with Symfony's own PHP and lists differences.What it found on real input
Run on 691 expressions extracted from 242 open-source projects (306 audited, the rest are a bare name or a single call):
==/===(the ownership checkobject.getOwner() == user). PHP saystrue; 2.x saidfalse; the 3.0 default saystrue.(A correction while building this: my first run treated a value tested for truthiness (
name or alias) as an object, which hid the""/"0"cases where PHP and JS disagree. Fixed here; it moved "typical and edge" from 78.5% to 72.5%.)Review notes
createAuditor(lib)), so the tests run it against the sources, no build needed.--libpoints the CLI at any build, e.g. an installed package.'@=service(...)'in a quoted YAML list) that the first version missed; fixed.scripts/is in.npmignore).Test plan
npm test: 558 passed (58 new: reading lists, extraction from 15 syntaxes and a real tree, classification of typical expressions, the report, every CLI path and exit code)phpjob runs these): 153 passed, including the comparison with PHPtsc --strict, builds + smoke tests,npm audit --omit=dev-),--libon the installed3.0.0-beta.1, a pre-3.0 library refused,--helpphpjob to "PHP against Symfony's own code": the aggregateCIcheck is unchanged)🤖 Generated with Claude Code