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

Standardise vnode text representation #2670

Merged
merged 14 commits into from
Feb 12, 2022
Merged

Conversation

barneycarroll
Copy link
Member

This addresses the crucial feature of #2669: text is always represented as virtual text nodes, never as a vnode.text. The vnode.text field remains in place for now.

The fix failed many tests which baked-in assumptions about vnode structure, so I took the opportunity of rewriting the tests to always use hyperscript expressions to avoid this category of brittle testing in future. In the process I removed a handful of tests which manually constructed vnode configurations which aren't feasible with hyperscript expressions, and fixed some text tests whose manual construction led them to validate impossible scenarios (boolean nodes are never treated as text nodes).

The fix as is creates a regression whereby <textarea> updates fail, which I'll need to fix.

The test cleanup creates its own strange bug in the <select> value update tests. I don't quite understand how this happened or what it's about, I'd appreciate a second pair of eyes.


o(succeeded).equals(false)
})
o.spec("contenteditable throws on untrusted children", function() {
Copy link
Member Author

Choose a reason for hiding this comment

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

The previous tests duplicated this sequence with a nebulous distinction between 'attr' & 'prop'

{tag:"option", attrs: {value: "0"}},
{tag:"option", attrs: {value: ""}}
]}
return m("select", attrs,
Copy link
Member Author

Choose a reason for hiding this comment

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

Constructing the select element itself via hyperscript rather than manually triggers these errors https://travis-ci.org/github/MithrilJS/mithril.js/builds/767047585#L293-L311:

attributes > select.value > updates with the same value do not re-set the attribute if the select has focus:
1
  should equal
0
    at /home/travis/build/MithrilJS/mithril.js/render/tests/test-attributes.js:639:35
    
attributes > select.value > updates with the same value do not re-set the attribute if the select has focus:
1
  should equal
0
    at /home/travis/build/MithrilJS/mithril.js/render/tests/test-attributes.js:644:35
    
attributes > select.value > updates with the same value do not re-set the attribute if the select has focus:
2
  should equal
1
    at /home/travis/build/MithrilJS/mithril.js/render/tests/test-attributes.js:649:35

Copy link
Member Author

@barneycarroll barneycarroll Apr 14, 2021

Choose a reason for hiding this comment

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

Trying to isolate the issue from the DOM mocks, I can't replicate it with real DOM. Using a spy trap on the HTMLInputElement 'value' setter, both the manually constructed select and the hyperscript equivalent fail the first test but none of the others:

Flems

Copy link
Member

Choose a reason for hiding this comment

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

The spy was buggy

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

I'll have to dig into m.render and the mocks to try and figure out why the setter is triggered extraneously
(tomorrow)

Copy link
Contributor

Choose a reason for hiding this comment

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

In the hyperscript-generated vnode, the empty attrs object (i.e. {}) is re-set to null by execSelector(). This is the difference between the hyperscript-generated vnodes and the manually constructed ones in this case.

In execSelector(), instead of setting the attrs to null, it may be better to set an empty object or undefined.

Copy link
Member Author

Choose a reason for hiding this comment

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

@kfule brilliant! And fixing this would lead to further standardisation. Thanks so much!

@barneycarroll
Copy link
Member Author

The <textarea> bug caused by this fix:

form inputs > textarea > updates after user input:
'bbb'
  should equal
'ccc'
    at /home/travis/build/MithrilJS/mithril.js/render/tests/test-input.js:293:29

Cannot be reproduced using real DOM

docs/migration-v02x.md Outdated Show resolved Hide resolved
render/hyperscript.js Outdated Show resolved Hide resolved
render/render.js Show resolved Hide resolved
@gilbert
Copy link
Contributor

gilbert commented Apr 15, 2021

A worthy effort!

@kfule
Copy link
Contributor

kfule commented May 2, 2021

The <textarea> bug caused by this fix:

form inputs > textarea > updates after user input:
'bbb'
  should equal
'ccc'
    at /home/travis/build/MithrilJS/mithril.js/render/tests/test-input.js:293:29

Cannot be reproduced using real DOM

If you re-bundle the module, it will also fail the real DOM test.

If you move the value of the first child of vnode.children to vnode.attrs.value, as in the previous implementation using vnode.text, the test will pass for now.

@barneycarroll
Copy link
Member Author

barneycarroll commented May 2, 2021

Thanks again @kfule !

So the rules of API precedence for textarea seem to be (lowest to highest):

  1. defaultValue
  2. Element subtree, if this contains text nodes with any character content
  3. value

I therefore propose we rewrite these tests and follow Reacts lead in avoiding use of subtree to define textarea value. This should be present as a warning in the change log for now.

Neither 1 or 3 work as HTML values, but any DOM representation will be serialised with the element subtree, so this shouldn’t be a problem for SSR rendering (@StephanHoyer?).

Thanks again for your insights @kfule

@barneycarroll barneycarroll force-pushed the standardise-vnode-text branch from 429cc4a to 75c6005 Compare May 2, 2021 14:23
@StephanHoyer
Copy link
Member

@barneycarroll I would really like to see this in the next release. Would be great if you can rebase and cleanup this PR so I can review and test this.

@barneycarroll
Copy link
Member Author

Sure, I’ll have a look tomorrow.

@StephanHoyer
Copy link
Member

@barneycarroll Are you still interested in doing this? If not it's ok, then I can take a look at it.

@StephanHoyer StephanHoyer force-pushed the standardise-vnode-text branch from c0fd201 to d223902 Compare February 12, 2022 10:26
@StephanHoyer
Copy link
Member

@barneycarroll just rebased without issues

@StephanHoyer StephanHoyer merged commit e4bd203 into next Feb 12, 2022
@StephanHoyer StephanHoyer deleted the standardise-vnode-text branch February 12, 2022 11:19
@StephanHoyer
Copy link
Member

@barneycarroll Merged!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Closed
Development

Successfully merging this pull request may close these issues.

7 participants