-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Interactivity API: Add debug notices for SSR #6413
Interactivity API: Add debug notices for SSR #6413
Conversation
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
225334a
to
24199ab
Compare
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Core Committers: Use this line as a base for the props when committing in SVN:
To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's an annotation that I believe is the preferred way to implement these tests:
/**
* @expectedIncorrectUsage WP_Interactivity_API::process_directives_args
*/
@@ -639,7 +660,8 @@ public function test_process_directives_changes_html_if_contains_svgs() { | |||
</header> | |||
'; | |||
$processed_html = $this->interactivity->process_directives( $html ); | |||
$p = new WP_HTML_Tag_Processor( $processed_html ); | |||
$this->setExpectedIncorrectUsage( 'WP_Interactivity_API::process_directives_args' ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is available as an annotation. Add this to the tests that are expected to fail and all the changes to implement this tracking can be removed:
* @expectedIncorrectUsage WP_Interactivity_API::process_directives_args
src/wp-includes/interactivity-api/class-wp-interactivity-api.php
Outdated
Show resolved
Hide resolved
src/wp-includes/interactivity-api/class-wp-interactivity-api.php
Outdated
Show resolved
Hide resolved
32fa2d8
to
5758d38
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a few notes but generally I think this is in a good place. I think the messages could be improved to be a bit more brief. I also think it might be helpful to include the interactivity namespace so that it's easier to locate the problem if there are many different interactive regions, what do you think?
For SVG/MATH:
Interactivity directives were detected on an incompatible %s tag when processing {{ namespace }}. These directives will be ignored.
For unbalanced (this is always due to a start tag without an end tag, right?):
Interactivity directives failed to process in {{ namespace }} due to a missing %s end tag.
src/wp-includes/interactivity-api/class-wp-interactivity-api.php
Outdated
Show resolved
Hide resolved
src/wp-includes/interactivity-api/class-wp-interactivity-api.php
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the messages could be a bit more brief (#6413 (review)) but this is working well generally. Thanks!
Done in 4b78690 |
I'm adding more checks to the SSR processing. Now it will also check that the namespace is not |
4b78690
to
42a0572
Compare
src/wp-includes/interactivity-api/class-wp-interactivity-api.php
Outdated
Show resolved
Hide resolved
src/wp-includes/interactivity-api/class-wp-interactivity-api.php
Outdated
Show resolved
Hide resolved
src/wp-includes/interactivity-api/class-wp-interactivity-api.php
Outdated
Show resolved
Hide resolved
*/ | ||
private function evaluate( $directive_value, string $default_namespace, $context = false ) { | ||
list( $ns, $path ) = $this->extract_directive_value( $directive_value, $default_namespace ); | ||
if ( empty( $path ) ) { | ||
if ( 'null' === $default_namespace ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this supposed to be the value null
or the string "null"
? It's the string now which looks pretty strange.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is strange, but is the string. Is read as a valid string namespace for SSR but then crashes in the runtime (need to 100% confirm this)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The JS runtime calls JSON.parse on directives… maybe it should only do that in directives that look like objects.
I assume many stringified JS could make that crash now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think any strings should be valid namespaces. null shouldn't be special.
Seems like a bug.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then I'll try to fix it! 🚀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using numbers only triggers the same error 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*/ | ||
private function evaluate( $directive_value, string $default_namespace, $context = false ) { | ||
list( $ns, $path ) = $this->extract_directive_value( $directive_value, $default_namespace ); | ||
if ( empty( $path ) ) { | ||
if ( 'null' === $default_namespace ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we remove this section expecting WordPress/gutenberg#61960 to land?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this PR is ready. 👌 I just left some suggestions.
* @since 6.6.0 The function now adds a warning when the HTML contains unbalanced | ||
* tags or SVG/Math with directives. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we finally removed the debug message about using directives inside <svg>
or <math>
tags, we would need to update this description.
* @since 6.6.0 The function now adds a warning when the HTML contains unbalanced | |
* tags or SVG/Math with directives. | |
* @since 6.6.0 The function displays a warning message when the HTML contains | |
* unbalanced tags. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in a9f15d8
return $unbalanced || 0 < count( $tag_stack ) ? null : $p->get_updated_html(); | ||
if ( $unbalanced || 0 < count( $tag_stack ) ) { | ||
$tag_errored = 0 < count( $tag_stack ) ? end( $tag_stack )[0] : $tag_name; | ||
/* translators: %s: Tag that caused the error, could by any HTML tag. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if there's a typo here. 👇
/* translators: %s: Tag that caused the error, could by any HTML tag. */ | |
/* translators: %s: The tag that caused the error; could be any HTML tag. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in a9f15d8
<header> | ||
<svg height="100" data-wp-bind--width="myPlugin::state.width"> | ||
<svg height="100"> | ||
<title>Red Circle</title> | ||
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" /> | ||
</svg> | ||
<div data-wp-bind--id="myPlugin::state.id"></div> | ||
<div data-wp-bind--id="myPlugin::state.width"></div> | ||
</header> | ||
'; | ||
$processed_html = $this->interactivity->process_directives( $html ); | ||
$p = new WP_HTML_Tag_Processor( $processed_html ); | ||
$p->next_tag( 'svg' ); | ||
$this->assertNull( $p->get_attribute( 'width' ) ); | ||
$p->next_tag( 'div' ); | ||
$this->assertEquals( 'some-id', $p->get_attribute( 'id' ) ); | ||
$p->next_tag( 'div' ); | ||
$this->assertEquals( '100', $p->get_attribute( 'id' ) ); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be done in a separate PR? As far as I can tell, it doesn't have
anything to do with the changes in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is just cleaning unnecessary repetitions on a test. Is a nitpick.
Overall, it looks good and is close to be ready to merge IMO. I left a comment and had the same comments as David above. Also, it would be good to add a unit test that asserts that the warning message appears correctly in the right circumstances. It could be something like: /**
* Tests that the `process_directives` issues a warning when the HTML
* containing directives contains unbalanced tags.
*
* @ticket 61044
*
* @covers ::process_directives
*
* @expectedIncorrectUsage WP_Interactivity_API::process_directives_args
*/
public function test_process_directives_warns_on_unbalanced_tags() {
$this->expectOutputString( 'Interactivity directives failed to process in "" due to a missing "P" end tag' );
$this->interactivity->state( 'myPlugin', array( 'id' => '1231341324' ) );
$this->interactivity->process_directives(
'<div>
<p data-wp-bind--id="myPlugin::state.id">
Hello, world
</div>
</div>
'
);
} I have tried adding that test but I wasn't able to make it work for some reason:
|
The only case that makes me think about it would be how would work in a future a test like this with two different warnings. 🤔 |
I'm sorry, I don't understand what you mean. Why would there be two different warnings? |
I think he means that the only warning message the Although the message content changes depending on the tag that caused the error, right? @cbravobernal |
I mean that. Maybe in a future, we warn for another cause (I don't know, a directive value processed in that function that requires any specific rule).
Yes, the message includes the tag processed when the unbalance variable sets to true. |
Now we differentiate between SVG and MATH tags and their inner tags with slightly different messages. |
} | ||
if ( $this->get_tag() === $tag_name ) { | ||
if ( $this->has_self_closing_flag() ) { | ||
continue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These whitespaces look wrong. It needs to be double checked before committing.
if ( $this->has_self_closing_flag() ) { | ||
continue; | ||
if ( ! $this->is_tag_closer() && $this->get_attribute_names_with_prefix( 'data-wp-' ) ) { | ||
/* translators: 1: SVG or MATH HTML tag, 2: Namespace of the interactive block. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't see %2 in the translation. The hint for translators needs to be updated.
if ( empty( $path ) ) { | ||
if ( ! $ns || ! $path ) { | ||
/* translators: %s: The directive value referenced. */ | ||
$message = sprintf( 'Namespace or reference path cannot be empty. Directive value referenced: %s ', $directive_value ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This message isn't translated but contains a hint for translators.
return $unbalanced || 0 < count( $tag_stack ) ? null : $p->get_updated_html(); | ||
if ( $unbalanced || 0 < count( $tag_stack ) ) { | ||
$tag_errored = 0 < count( $tag_stack ) ? end( $tag_stack )[0] : $tag_name; | ||
/* translators: %s: The tag that caused the error; could be any HTML tag. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are two tokens, so the hints for translators need some improvements.
@@ -272,6 +272,7 @@ public function process_directives( string $html ): string { | |||
* it returns null if the HTML contains unbalanced tags. | |||
* | |||
* @since 6.5.0 | |||
* @since 6.6.0 The function displays a warning message when the HTML contains unbalanced tags. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* @since 6.6.0 The function displays a warning message when the HTML contains unbalanced tags. | |
* @since 6.6.0 The function displays a warning message when the HTML contains unbalanced tags or a directive appears in a MATH or SVG tag. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 3e64ebb
return $unbalanced || 0 < count( $tag_stack ) ? null : $p->get_updated_html(); | ||
if ( $unbalanced || 0 < count( $tag_stack ) ) { | ||
$tag_errored = 0 < count( $tag_stack ) ? end( $tag_stack )[0] : $tag_name; | ||
/* translators: %1s: Namespace processed , %2s: The tag that caused the error; could be any HTML tag. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/* translators: %1s: Namespace processed , %2s: The tag that caused the error; could be any HTML tag. */ | |
/* translators: %1s: Namespace processed, %2s: The tag that caused the error; could be any HTML tag. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 3e64ebb
if ( empty( $path ) ) { | ||
if ( ! $ns || ! $path ) { | ||
/* translators: %s: The directive value referenced. */ | ||
$message = sprintf( __( 'Namespace or reference path cannot be empty. Directive value referenced: %s ' ), $directive_value ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$message = sprintf( __( 'Namespace or reference path cannot be empty. Directive value referenced: %s ' ), $directive_value ); | |
$message = sprintf( __( 'Namespace or reference path cannot be empty. Directive value referenced: %s.' ), $directive_value ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 3e64ebb
Committed with https://core.trac.wordpress.org/changeset/58321. |
Trac ticket: https://core.trac.wordpress.org/ticket/61044
This PR aims to improve the developer experience of the Interactivity API server directives processing.
Right now, the SSR won't work if the HTML is unbalanced (there is some closer tag missing).
I added also notices for cases where the directive is empty, or the namespace is an empty string, an empty object or null.
This PR adds a warning in those cases, if the developer is in debug mode.
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.