-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
WP_HTML_Tag_Processor: Make get_attribute
reflect attribute set via set_attribute
, even without updating
#46680
Conversation
Ah, it looks like #46598 is going to fix this. Maybe we can add some |
Closing this one; discussing adding some test coverage over there: #46598 (comment) |
Thanks! |
8aa200a
to
fde2790
Compare
get_attribute
doesn't pick up attribute added via set_attribute
get_attribute
picks up attribute set via set_attribute
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.
Good spot!
E2E failures seem irrelevant so I restarted the tests |
wanted to reach out and chat more synchronously on this but I'll leave a note here for everyone's sake. it doesn't seem right to me to say that you are "doing it wrong" here but I've been tossing around the question of whether this is intended behavior for the tag processor. once we flush out changes by calling does it reset? should it reset? I don't know. what's the use-case for reading an attribute we just set? we had to have access to the value to set it before calling I think this is a behavior we didn't codify, what all happens when calling |
Thank you for weighing in @dmsnell! I had a hunch that this had to do with the internal pointer advancing 😊 IMO, if there's a And while your reasons make sense, I think it's another example of how people's habits and expectations could be so strong that they might go as far as to even change the behavior of the class to match those expectations. This is why I think we should match them already 😬 This is assuming that people will actually encounter a need for But here's a more real-world example: For the Interactivity API, whenever we encounter a tag, we watch out for |
@dmsnell |
okay well I thought there was bug here, because if you slightly change the order of operations @ockham you will discover this still isn't quite what you expect. $p = new WP_HTML_Tag_Processor( '<div>' );
$p->next_tag();
$p->set_attribute( 'id', 'test' );
$p->get_attribute( 'id' ) === NULL;
In the docblock comments we have language about attribute updates being enqueued. this makes me wonder if we should rename these functions Or just deal with it. Or add a call to 🤔 so we either change the class to match those expectations or make it more obvious that those expectations shouldn't apply. this class no more serves HTTP requests than it provides a DOM API. there's a problem with immediately updating the document once we call I think we should be able to check first if an attribute update is enqueued and return its value before looking at the parsed values which should solve this. let me prep a patch. |
Just to cycle back to this comment:
To be clear, this is what I did initially. However, shortly after I had filed this PR, #46598 was merged, and after I rebased the PR, the original error was gone -- #46598 had fixed it 😊 |
I think this sounds good!
I saw that you've pushed a commit to add the failing test (9e38e42), but I guess you haven't had time yet to work on the fix. I can do this in the next couple of days unless you'll beat me to it 😊 |
9e38e42
to
ec21489
Compare
Fixed in b559cd4. Still need to add logic (and test coverage) for |
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 note about the unit tests but it looks good to me otherwise. Thank you @ockham for addressing all the feedback!
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.
sorry for the last-minute changes but I pushed 5e25270e66d54dba8a8aa6e9909402523001d782 in which I rearranged a few things stylistically and also reverted the behavioral change, because I find it confusing to preserve add_class
/remove_class
calls after set_attribute
or remove_attribute
has occurred.
this is negotiable, but I didn't see any clear reason why we changed the behavior (though I may have missed it while reading through the comments). if the reason is that it was a side-effect of rearranging the code then I think the change I've proposed is not worse than what it was before or after that change.
now, when calling the transactional swaps set_attribute
or remove_attribute
for class
, all enqueued class-builder changes are wiped out and the new value goes in. any calls to the builder after this point augments the updated value. I believe this maps most closely to how successive edits to any other attribute work.
let me know how you feel. if you don't like what I changed then we can talk about it. the stylistic things are also up for grabs, but I think they are mostly new paint on the framework you built.
if ( 'class' === $name ) { | ||
$this->class_name_updates_to_attributes_updates(); | ||
} |
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.
do we have a reason to change the behavior? I think it's probably important to ensure that set_attribute
and remove_attribute
updates wipe out class builder method changes, as I can reason about what it means to call add_class
after setting the class
attribute, but I can't reason an obvious outcome of calling add_class
before the transactional swap of set_attribute
5e25270
to
d8873df
Compare
Squashed earlier work and rebased against latest Second commit on the rebase contains the changes I made in my work today, which we can discuss, revert, or accept. |
c62ce41
to
fafafce
Compare
I think it's mostly there – I left a few final notes 👍 (have we been repeating this for two weeks now? :D) |
bdaf6c4
to
b9bccca
Compare
…dated values. (#46680) Currently there exists a data race in the tag processor when reading the attribute value for an attribute that has previously been updated. This is due to the fact that when reading attribute values we examine the input HTML document and overlook potential enqueued updates. If we call `get_updated_html()` before reading then those updates are all flushed out and our values will match what we expect, but if we skip this step then we read stale information read during the first parse of the updated tag. In this patch we're fixing that bug by inspecting the set of enqueued changes when reading attribute values. If an update is already enqueued for a given attribute then we read the value from that update instead of from the original HTML. This ensures that the value we report is always the most-recent or most-updated value. Co-Authored-By: Adam Zielinski <adam@adamziel.com> Co-Authored-By: Dennis Snell <dennis.snell@automattic.com>
- Presereed the original behavior when class-builder methods and attribute-setters for the `class` attribute coincide. - Renamed the enqueued-getter to `get_enqueued_attribute_value()` to focus on its semantic purpose instead of the implementation steps. - Un-doc-blocks some accidental docblock comments. - Reworded language use in a comment and removed "OTOH" as an unexplained abbreviation.
b9bccca
to
a9afdcc
Compare
What?
This adds a unit test to make sure
get_attribute()
picks up an attribute added byset_attribute()
.Why?
This seems like a contract we might want to enforce via a unit test.
It didn't work until recently, when #46598 was merged.
How?
See code.
We might want to consider adding an assertion like that to other
set_attribute()
tests as well; or adding a separate test case just for theset_attribut
/get_attribute
pair.Testing Instructions
See unit test.