-
-
Notifications
You must be signed in to change notification settings - Fork 926
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
Do not normalise component children on ingestion #2155
Do not normalise component children on ingestion #2155
Conversation
I tried running the inbuilt perf tools on this but couldn't get any consistent comparisons: by running tests repeatedly and alternating I could get either branch 10% better than the other for all tests. The most consistent thing was that for any given run, all tests would be either faster or slower than their last run. |
for (var i = 0; i < children.length; i++) { | ||
children[i] = Vnode.normalize(children[i]) | ||
Vnode.normalizeChildren = function normalizeChildren(input) { | ||
var children = [] |
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 issue with having non-normalized children and normalized instance children is that up until now, there was no need to distinguish between the two so they were effectively the same thing. New arrays here stops downstream code mutating upstream references, which is otherwise pretty unsettling.
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.
That's a good point, but I'm afraid it will not be good for performance.
vnodes
should IMO be treated as owned by render
once they leave user code.
OTOH having your children turn from ["a", "b", "c"]
to an array of vnodes
can definitely be surprising.
I'm on the fence on 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 performance concern jumps out. I couldn't get anything significant out of npm run perf
— that is to say of the test suites included, the variation between any given pass and the next is too large to notice any difference plus or minus this patch. I'm tempted to think that in the grand scheme of things, creating disposable arrays is trivial but I'm at a loss as to how to validate it.
IMO your points about ownership & surprise are not contradictory. From a semantic perspective, this patch seeks to address the fact that components are an exception in hyperscript transformation inasmuch as children (and non-lifecycle attributes) have not left the user domain until they have been yielded back into render space by the component's internals.
Great PR, thanks! If you don't see any perf impact, I'd be tempted to merge it as is, with I just introduced a merge conflict by closing #2064, sorry |
@JAForbes I know you were distasteful of the idea of surface API sloppiness in allowing maybe-vnodes-maybe-allsorts , what do you reckon about this? |
I see why you're taking this tack (lazy normalization). I think either way we should have that, it's a good change. As for the intended use: I think I'd prefer first class support for render functions that get assigned to a different property instead of But I certainly don't think that discussion needs to be had here or hold up this great addition. |
The label here is tentative - this might be breaking, so take it with a grain of salt. |
Not landing this in v1.2 (it's a lot more breaking with fresh eyes). |
Description
This PR seeks to change vnode normalisation behaviour to raise a distinction between component vnode children and every other kinds of vnode children. Nominally, component children should only be fully normalised upon interpolation of the component view (or instance) - not upon component vnode normalisation. In a similar way to the fact that element vnodes render non-key, non-lifecycle attributes as events, DOM properties or DOM attributes but components do not (unless they are passed on as such in the component view), so component children should not be fully normalised unless called to do so by their being invoked in the view.
Motivation and Context
This enables more flexibility in developer experience when writing custom component interfaces by being less strict about the nature of children. Significantly, we resolve #2050 such that functions passed in as children can be accessed without having to query an interstitial structure which conforms neither to the input structure, nor to a rational vnode entity in its own right:
How Has This Been Tested?
I modified all existing tests which made assumptions about component children and added a new one, bringing in render, vnode & hyperscript - to deal with component normalisation steps holistically.
https://github.com/MithrilJS/mithril.js/blob/deferred-component-children-normalization/render/tests/test-normalizeComponentChildren.js
Types of changes
Checklist:
docs/change-log.md