Problem/Motivation
The validate_component_props Twig function is added twice - for the main template and extended (internally in Twig). But the extended template should not be validated, since it will contain only limited information if the only keyword is used in combination with embed.
Steps to reproduce
You can see the simple example in the 3464-failtest branch. Calling the component ({% embed 'sdc_test:wrapper' with { text: 'Test' } only %}{% endembed %}) with an embed and only keywords leads to WSOD.
NOTICE: PHP message: Uncaught PHP Exception Drupal\Core\Render\Component\Exception\InvalidComponentException: "[text] The property text is required" at /var/www/html/core/lib/Drupal/Core/Theme/Component/ComponentValidator.php line 203
2024-07-30T15:19:02.149398187Z 192.168.192.7 - 30/Jul/2024:15:19:01 +0000 "GET /index.php" 500
But as you can see, the property has been passed.
The next part can be inaccurate.
When Twig renders {% embed 'foo' only %}{% endembed %}, it internally creates something like include 'foo' extends 'foo', which leads to the 'foo' template being processed twice. So the \Drupal\Core\Template\ComponentNodeVisitor will be called on that template twice, and both "templates" will receive a Twig function validate_component_props, which basically validates the component. However, the extended template only receives basic information, because of the only token, which leads to a validation error of the component schema.
Proposed resolution
\Drupal\Core\Template\ComponentNodeVisitor::leaveNode should leave the node if it is a child of another one. The problem "call" will contain parent element. Without it, the extended template will pass all the other checks, because the name will be a proper component plugin with a schema, but the context will be empty.
| Comment | File | Size | Author |
|---|---|---|---|
| #20 | 3464719-nr-bot.txt | 1.84 KB | needs-review-queue-bot |
| compiled-result-with-recursion.png | 135.74 KB | niklan | |
| template-source.png | 78.96 KB | niklan | |
| template.png | 57.81 KB | niklan | |
| example.zip | 2.48 KB | niklan |
Issue fork drupal-3464719
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 3464719-failtest
changes, plain diff MR !9001
- 3464719-possible-fix
changes, plain diff MR !9089
Comments
Comment #2
niklanComment #3
smustgrave commented@Niklan mean to open an MR?
Comment #4
niklanI'm not sure what I should add/change in MR at this point. I can't understand where this bug comes from. It seems to me that it is potentially a bug in Twig itself. I'm not familiar with Twig's internal code, but I think I should try to find out where the template is compiled to find out why it compiles it with a wrong template reference which leads to a recursion.
I just don't know where to approach this task. It's definitely not a ComponentValidator problem. Everything hints and leads to Twig. Basically, that 'example:foo' component tried to be rendered twice, while it is a single call. And the second call comes from a wrong Twig compiled template, which is a little hard to follow and understand, so I want to try to find out where and how these templates are built in the first place.
Maybe I'll try to make a failtest later.
Comment #5
smustgrave commentedIf you’re on slack #components or #ui_patterns someone may be able to help.
Comment #7
niklanAdded a failtest which highlights the issue as well: https://git.drupalcode.org/issue/drupal-3464719/-/jobs/2292129#L3250
Comment #8
pdureau commentedNot
#ui_patternsbut#ui-suite-initiative;)Comment #9
pdureau commentedIf the issue is not specific to SDC (which is resolving template path from component ID:
{% embed 'sdc_test:no-props' only %}) and can be reproduce with normal Twig "embed" (calling directly a template path), the fix must be proposed directly at https://github.com/twigphp/TwigComment #10
niklanDid a quick and dirty test with just Twig, and it works fine.
script.php:
./templates/foo.twig:
./templates/bar.twig:
Hello from Bar!Output:
Comment #12
niklanI'm almost given up, but found a major clue. It seems that
\Drupal\Core\Template\ComponentNodeVisitor::leaveNodeshould exit if the node has a parent.It seems like when you render a node with a parent set, this filter
validate_component_propsreceives a wrong context, which leads to an exception during validation.I've tested locally, and everything seems to be working fine now.
Comment #13
niklanWell, the pipeline confirms that it fixes a problem and doesn't break anything else (at least what has been tested). On my project, everything works as expected now as well. Honestly, for me, it is hard to explain why this helps.
Just an assumption from debugging: It looks like such components are represented twice in the Twig Node Tree, one of them is some kind of container (wrapper), it doesn't have a payload with variables, but
\Drupal\Core\Template\ComponentNodeVisitor::leaveNodestill adds a validation function to it, which leads to an exception. Twig also adds 'extends' to 'embed' tag, which can also be a potential hint to a source of the problem. It internally compiles something likeinclude 'sdc_test:wrapper' extends 'sdc_test:wrapper', and that extends have a different context, but passing checks for component name in\Drupal\Core\Template\ComponentNodeVisitor::leaveNode.Comment #14
smustgrave commentedHello could the issue summary be completed to include the proposed solution section of the default template please
Thanks
Comment #15
niklanUpdated summary and simplified it a little, since there is a failtest and a possible solution exists.
Comment #16
niklanComment #18
smustgrave commentedThanks! Removing issue summary tag
Shows test coverage
Didn't see anything in the code that needed tweak.
Comment #19
alexpottReading the code I'm wondering if this change will lead to things not happening that should. What about the attach_library call? Going to ping @e0ipso to have a look as SDC maintainer.
Comment #20
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #21
smustgrave commentedFalse positive
Comment #22
e0ipsoCan we check weather the fix in #3446933: SDC incorrectly throws an exception about embedded slots also fixes this?
Comment #23
niklanTested locally and it seems to have resolved the issue as well.
Comment #25
smustgrave commentedGoing to close this one as a duplicate and everyone seemed to help so checking all credit.