Skip to content
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

Fix tiny bugs of setAttr()/updateStyle() #2988

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

kfule
Copy link
Contributor

@kfule kfule commented Nov 8, 2024

Fixed a few tiny bugs in attributes and style properties updates.

Description

Motivation and Context

I found a strange behavior in the process of #2985, although it rarely happens (#2985 (comment)). And there seems to be a similar trivial issue in updateAttrs() (flems.)
This could be solved by simply swapping the order of set and removal probably without creating new bugs and perf issues.

Also, I am not very familiar with custom elements, but it seemed to me that the #2799 issue could be solved by simply removing key === "is" from setAttr().

How Has This Been Tested?

  • npm run test including test code fix for custom elements
    • Sorry, but I did not make any changes to domMock because the changes seemed more complicated than the bug fix code.
  • I have also confirmed that the issues are not reproduced in flems above using fixed bundle.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • My code follows the code style of this project.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • My change requires a documentation update, and I've opened a pull request to update it already:
  • I have read https://mithril.js.org/contributing.html.

@kfule kfule requested a review from a team as a code owner November 8, 2024 10:47
@kfule
Copy link
Contributor Author

kfule commented Nov 8, 2024

I am a little sorry for my frequent pull requests these days.😢
I did not plan for this pull request, but it seemed like an easy bug to fix...

I think these are bugs that almost no one cares about, so I won't hurry you to review or merge it.

@kfule kfule force-pushed the fix-is-attr-style branch from edc6ab8 to 2ae7003 Compare November 8, 2024 11:02
Copy link
Member

@dead-claudia dead-claudia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You still need to fix the diff algorithm (this will have negative perf impact) to compare is values for non-custom element vnodes.

  • If the is attribute disappears, the element needs replaced so it's no longer a custom element.
  • If the is attribute is newly added, the element needs replaced so it's now a custom element.
  • If the is attribute changes, the backing custom element needs to change to be that new type.

In all three cases, it's simpler and more predictable to just remove and re-create.

@dead-claudia dead-claudia mentioned this pull request Nov 8, 2024
8 tasks
@kfule
Copy link
Contributor Author

kfule commented Nov 8, 2024

@dead-claudia
Thanks for the comment. As you commented, this PR is going to have unpredictable behavior for users (even if it is straightforward javascript behavior). I will take some time to think about it some more.

I think I will close this PR for now. There is no hurry at all to fix the other bugs in this PR.

@kfule kfule closed this Nov 8, 2024
@dead-claudia
Copy link
Member

@dead-claudia

Thanks for the comment. As you commented, this PR is going to have unpredictable behavior for users (even if it is straightforward javascript behavior). I will take some time to think about it some more.

I think I will close this PR for now. There is no hurry at all to fix the other bugs in this PR.

@kfule The current behavior isn't any more "predictable". What I suggested was really just a one line fix plus some more (pretty straightforward) tests. Sorry if this wasn't clear.

kfule added 3 commits February 4, 2025 19:16
This allows the "is" attribute to be set or removed like any other attribute.
This is a leftover from MithrilJS#2811.
@kfule kfule reopened this Feb 4, 2025
@kfule kfule force-pushed the fix-is-attr-style branch from 2ae7003 to f944a7e Compare February 4, 2025 10:27
@kfule
Copy link
Contributor Author

kfule commented Feb 4, 2025

@dead-claudia
I have reopened this PR. I would like to request your review.

The following changes related to attr/style have been added to the previous PR. Both are small changes, I think.

  • remove key === "is" from removeAttr() as well (mainly for code consistency with setAttr())
  • remove cssText property access (cf. Bypass css text #2811)

I have not added any tests, but I would like to add tests if needed.


Also, I thought about your comment about "is" being "unpredictable".
When the value of "is" is set/changed/deleted, it would be better to delete the element and re-create it as you commented.
For instance, it would look fine to change the call updateElement() as follows:

default: {
	if ((old.attrs && old.attrs.is) == (vnode.attrs && vnode.attrs.is)) {
		updateElement(old, vnode, hooks, ns)
	} else {
		removeNode(parent, old)
		createElement(parent, vnode, hooks, ns, nextSibling)
	}
}

However, I personally would be more careful about adding code to this area because of the performance impact (about a several percent drop).
The "is" attribute has not yet been implemented in safari and does not seem to be planned to be implemented. I don't think I will be using “is” for a while yet.

@kfule kfule requested a review from dead-claudia February 4, 2025 12:02
@dead-claudia
Copy link
Member

dead-claudia commented Feb 4, 2025

However, I personally would be more careful about adding code to this area because of the performance impact (about a several percent drop).

@kfule Try adding a bits field to the vnode that has the lowest bit set (var IS_CUSTOMIED_BUILTIN = 1 << 0) if it's a customized built-in. There's slight memory tradeoff (10 -> 11 fields, or 52 -> 56 bytes in V8), but it won't impact much else. Be sure to add it as the first field so it's most likely to reside on the same cache page as the tag.

A bit test from a field allocated inline in the object is very cheap. It's only a few bottlenecking instructions (4-6 at most) in the fast path plus an extra immediate generation + memory store (that won't bottleneck), so it should avoid significant perf deviations.

You'll also have to do a hasOwn.call(vnode.attrs, "is") check in m, which will cause some extra perf degradation, but doing it in m pretty much ensures it'll be fetching from cache, and this will save a lot of time. Plus, it's a pure existence check, so engines can skip some of the property value access work, and the use of hasOwn avoids the prototype walk (and attempt to set up inline caches on the result).

kfule added 2 commits February 5, 2025 20:43
This seems to give better performance than simply adding a `(old.attrs && old.attrs.is) == (vnode.attrs && vnode.attrs.is)` evaluation to updateNode().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants