Here is a screenshot of an empty status message in Drupal.ajax.prototype.success during an AJAX request.
https://drupal.org/files/issues/developer-tools-http-gardens.dev-node-32...

The output from this AJAX request contains an empty div tag:
https://drupal.org/files/issues/developer-tools-http-gardens.dev-node-32...

Comments

jessebeach’s picture

Status: Active » Needs review
StatusFileSize
new669 bytes

The empty status message response item is not plumbed through to the success callback arguments:
https://drupal.org/files/issues/developer-tools-http-gardens.dev-node-32...

Issue tracked down by @jessebeach
Patch code provded by @effulgentsia

effulgentsia’s picture

Subscribe. #1 looks good to me, though jessebeach and I worked on that together, so it needs a review from someone else before RTBC.

Most of the time, there aren't any status messages, and there's no reason to so commonly issue an empty prepend().

For reasons explained inside Drupal.ajax.prototype.commands.insert() in misc/ajax.js (not touched by this patch), the empty string is wrapped in a DIV. Possibly the Drupal.ajax.prototype.commands.insert() function should be made to check for empty string and treat that case specially (no div wrapper, no effects, no attachBehaviors()), but that's a separate issue: regardless of whether empty inserts should be supported in the abstract, there's no reason for core to create the condition.

sammys’s picture

Nicely spotted @jessebeach! I confirm that the patch works on Drupal 7, which has the same problem. This code is trivial and identical in both D7 and D8. Even though I would have used !empty() instead of != '' I have two enthusiastic thumbs up for the patch. I'd mark it RTBC but I think my clout has run dry.

effulgentsia’s picture

Assigned: jessebeach » Unassigned
Status: Needs review » Reviewed & tested by the community
Issue tags: +Needs backport to D7
StatusFileSize
new688 bytes

Thanks! This is just a reroll for D8's "core" folder. No substantive change, so RTBC.

catch’s picture

Status: Reviewed & tested by the community » Needs review

Is it worth adding a test for this? Looks like it could be done.

effulgentsia’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

Good point.

nod_’s picture

Like pointed out in#2, it's ultimately a JS issue: #1031600: AJAX requests cause duplicate, invalid CSS includes and multi-nested response data output anyway the fix totally makes sense.

pwolanin’s picture

Status: Needs work » Needs review
pwolanin’s picture

jhedstrom’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll
madhavvyas’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll

Ajax.inc file removed from 8.0.x branch. I guess, no further action on this issue. Working on Backport to D7

madhavvyas’s picture

Status: Needs review » Patch (to be ported)
madhavvyas’s picture

Status: Patch (to be ported) » Needs review
Issue tags: -Needs backport to D7
StatusFileSize
new668 bytes

D7 Patch created

Status: Needs review » Needs work

The last submitted patch, 13: patch_to_ported_1237012-4.patch, failed testing.

madhavvyas’s picture

Status: Needs work » Needs review

Can someone help how can I test D7 patch here? This is my first backport patch

madhavvyas’s picture

Version: 8.0.x-dev » 7.x-dev
StatusFileSize
new668 bytes

madhavvyas’s picture

StatusFileSize
new668 bytes
madhavvyas’s picture

Issue tags: -Needs tests
madhavvyas’s picture

effulgentsia’s picture

Version: 7.x-dev » 8.0.x-dev
Issue tags: +Needs tests
StatusFileSize
new732 bytes

Moving back to 8.0.x, because per #5, this still needs tests. Looks like this was fixed as part of #1843220-48: Convert form AJAX to new AJAX API based on a review comment in #1843220-35: Convert form AJAX to new AJAX API, but no test was added for it there. Possibly some test coverage was added since, so here's a patch to try to expose such coverage if there is any.

effulgentsia’s picture

StatusFileSize
new507 bytes

Additionally, the if statement commented out in #21 is no longer a sufficient fix for this issue, even if there is test coverage for it, because the Classy theme outputs a newline instead of an empty string when there are no messages. Here's a patch with one possible fix for that.

Possibly we should create a spin-off issue for it, especially if there are any non Ajax related problems with a newline instead of empty string as a status message output.

The last submitted patch, 21: ajax-empty-status-messages-1237012-21-test.patch, failed testing.

The last submitted patch, 21: ajax-empty-status-messages-1237012-21-test.patch, failed testing.

tic2000’s picture

Status: Needs review » Needs work

The commented out "fix" in 21 is not a fix. Clearly the issue is that PrependCommand and removing the check will make it be used every time no matter what. But since the return of $this->drupalRenderRoot($status_messages) is never empty that condition will never work.

A quick fix is to trim. $output = trim($this->drupalRenderRoot($status_messages)); .

I didn't test the patch in #22, but since it's only in the classy theme I can safely assume that it doesn't fix the problem since I experienced this in Seven.

There shouldn't be any problems with empty lines in HTML. This is only an issue with that AJAX command sent on every request no matter if there are messages or not.

If we want to trim everything we need to return a trimmed output from Renderer::doRender();

tic2000’s picture

Status: Needs work » Needs review
StatusFileSize
new781 bytes
wim leers’s picture

Assigned: Unassigned » effulgentsia

Let's find out what @effulgentsia thinks about that.

effulgentsia’s picture

+1 to #26, because yeah, I think it's totally reasonable to assume that whitespace isn't a meaningful status message list. I queued #21 for a retest, because I still want to make sure we have sufficient test coverage both for cases where $this->drupalRenderRoot($status_messages) returns empty and for cases where it returns only whitespace.

effulgentsia’s picture

+++ b/core/lib/Drupal/Core/Render/MainContent/AjaxRenderer.php
@@ -72,7 +72,7 @@ public function renderResponse(array $main_content, Request $request, RouteMatch
-    $output = $this->drupalRenderRoot($status_messages);
+    $output = trim($this->drupalRenderRoot($status_messages));
     if (!empty($output)) {
       $response->addCommand(new PrependCommand(NULL, $output));
     }

I wonder if we should check emptiness on the trimmed value, but in the case where it's not empty, output the untrimmed value. I know that in #736066: ajax.js insert command sometimes wraps content in a div, potentially producing invalid HTML and other bugs, we're running into separate problems of trailing whitespace, and in the course of solving that issue, we may decide to trim in some/all places, but for purposes of this issue, I wonder if we should avoid removing whitespace that a template may have decided to put in there intentionally (which I realize is unlikely given that status messages usually get themed with block-level HTML elements).

effulgentsia’s picture

since it's only in the classy theme I can safely assume that it doesn't fix the problem since I experienced this in Seven

Seven uses Classy as a base theme, so fixing Classy fixes Seven too. But regardless, #26 is better.

tic2000’s picture

StatusFileSize
new908 bytes
new736 bytes

But the only way a template would output

Like the provided patch?

I know that in #736066: ajax.js insert command sometimes wraps content in a div, potentially producing invalid HTML and other bugs we're running into separate problems of trailing whitespace,

I think I will provide a patch which doesn't care about text nodes.

Seven uses Classy as a base theme, so fixing Classy fixes Seven too.

I looked then for a base theme value and I saw none. I found out later that's the case.

tic2000’s picture

StatusFileSize
new958 bytes
new848 bytes

This is wrong.

tic2000’s picture

StatusFileSize
new760 bytes

No need to run $this->drupalRenderRoot($status_messages) twice.

No interdiff, cause now the patch is actually smaller.

The last submitted patch, 31: emptystatus-1237012-30.patch, failed testing.

The last submitted patch, 32: emptystatus-1237012-32.patch, failed testing.

nod_’s picture

Status: Needs review » Reviewed & tested by the community

Looks good to me.

catch’s picture

Status: Reviewed & tested by the community » Needs review

#33 could use a comment explaining why we're not doing #26. At least it's not clear to me from the discussion why it's worth making the distinction. @todo for #736066: ajax.js insert command sometimes wraps content in a div, potentially producing invalid HTML and other bugs might be enough.

tic2000’s picture

The reason for #33 is

but for purposes of this issue, I wonder if we should avoid removing whitespace that a template may have decided to put in there intentionally (which I realize is unlikely given that status messages usually get themed with block-level HTML elements).

Although now that I think of it, this messages are displayed if the developer didn't add them already, which he should have done. And if he's not happy that the empty space got removed he can add the command himself.

I will provide a patch with a comment.

tic2000’s picture

StatusFileSize
new690 bytes
new839 bytes
nod_’s picture

Status: Needs review » Needs work

Need help with what to test and how to test it to be able to wrap up this patch.

twistor’s picture

+++ b/core/lib/Drupal/Core/Render/MainContent/AjaxRenderer.php
@@ -73,7 +73,9 @@ public function renderResponse(array $main_content, Request $request, RouteMatch
+    $output_trimmed = trim($output);
+    if (!empty($output_trimmed)) {
+      // There are messages so output them exactly as the theme renders them.

We shouldn't use empty() on strings. '0' is a valid status message. Either strlen($output_trimmed) or isset($output_trimmed[0]).

tic2000’s picture

Status: Needs work » Needs review
StatusFileSize
new3.44 KB
new4.28 KB

I added a test for an empty message. The test currently in head is actually checking the current behavior and not that the code actually does what it should do.

The interdiff is the test and in AjaxRenderer

- if (!empty($output_trimmed)) {
+ if (!empty($output_trimmed) && $output_trimmed != '') {

The last submitted patch, 42: 1237012-42-test.patch, failed testing.

nod_’s picture

Issue tags: -Needs tests

Looks good to me.

andypost’s picture

Status: Needs review » Reviewed & tested by the community

There's a test coverage!

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/lib/Drupal/Core/Render/MainContent/AjaxRenderer.php
@@ -73,7 +73,9 @@ public function renderResponse(array $main_content, Request $request, RouteMatch
-    if (!empty($output)) {
+    $output_trimmed = trim($output);
+    if (!empty($output_trimmed) && $output_trimmed != '') {
php -r "var_dump(empty(''));"
bool(true)

So the second part of this conditional is unnecessary.

In fact I think changing this to if (!empty(trim($output))) { as since 5.5 PHP supports arbitrary expressions in empty - https://secure.php.net/manual/en/migration55.new-features.php#migration5...

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

jcisio’s picture

Status: Needs work » Needs review
StatusFileSize
new4.25 KB
new787 bytes

Re #46: because of #41.

Here is a reroll with simplified condition. We already know that $output_trimmed, as a result of trim(), is of type string.

jcisio’s picture

StatusFileSize
new845 bytes
new4.21 KB

Even simpler, based on comment #47.

The last submitted patch, 48: 1237012-48.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 49: 1237012-49.patch, failed testing.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

larowlan’s picture

Version: 8.9.x-dev » 9.3.x-dev
Status: Needs work » Needs review
Issue tags: +Bug Smash Initiative
StatusFileSize
new1.97 KB
new2.68 KB

Triaged this as part of bug-smash initiative

I suspect the original issue was specific to the status message theme template in use on Digital Gardens.

Re-rolled the patch because the test still fails without the change.

@effulgentsia do you still want to be assigned here?

kristen pol’s picture

Status: Needs review » Reviewed & tested by the community

Reviewing previous comments... looks RTBC to me since:

1. It was previous reviewed and approved in 44 and 45 other than some minor changes noted in 46 which were addressed in 49 and 59

2. Test-only patch fails as expected

3. Automated tests pass

4. Not sure how to test manually but hoping the new test is sufficient since this is a simple change

effulgentsia’s picture

Assigned: effulgentsia » Unassigned
Status: Reviewed & tested by the community » Closed (duplicate)

Oops, I had forgotten all about this issue and having it assigned to me. Sorry about that.

I'm closing this as a duplicate, because:

+++ b/core/lib/Drupal/Core/Render/MainContent/AjaxRenderer.php
@@ -72,7 +72,7 @@ public function renderResponse(array $main_content, Request $request, RouteMatch
-    if (!empty($output)) {
+    if (!empty(trim($output))) {

When this issue was first opened, the problem was that this if statement wasn't here at all, so an empty div was output regardless of theme. Per #21, that was fixed in #1843220: Convert form AJAX to new AJAX API.

Per #22, $output containing only whitespace was a problem present in Classy and possibly other themes. However, #2853509: Don't render status messages if there are no messages but also include their assets if there might be fixed that for all themes by adding an if ($messages) { statement in Drupal\Core\Render\Element\StatusMessages::renderMessages(). Therefore, there's no need to trim here anymore.

Thank you to everyone who worked on this. It's satisfying to close out a 10 year old issue, even if it's not by committing anything.