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

Render new #107

Closed
wants to merge 13 commits into from
Closed

Render new #107

wants to merge 13 commits into from

Conversation

pdf
Copy link
Contributor

@pdf pdf commented May 10, 2017

Refactor rendering for reliability and performance.

NEW:

  • Keyer interface provides support for efficient list element re-use.
    Components simply need to implement the Key function, or the
    vecty.Key Markup may be used for HTML.

BREAKING:

  • Restorer interface is now Updater, and its Restore method is now
    ShouldUpdate. The previous Restorer implementation was variously
    broken in any case, and poorly named IMO.

    Additionally, it requires a Clone method to support passing a
    previous Component instance to ShouldUpdate. There is a limited
    generic version available on vecty.Core using reflection that may
    satisfy for users that do not wish to implement it themselves.

  • Context method on Component interface is no longer public.

  • Restore method on HTML is no longer public.

Supersedes: #93 #94 #104
Impacts: #84 #75 #54
Fixes: #106 #92 #85 #78 #25

dom.go Outdated
// core/central struct which all Component implementations should embed.
var (
errMissingParent = fmt.Errorf("Missing parent node")
errEmptyElement = fmt.Errorf("Empty element or node")
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor Go style issue, error strings should not be capitalized (unless beginning with proper nouns or acronyms) or end with punctuation, since they are usually printed following other context.

Source: https://github.com/golang/go/wiki/CodeReviewComments#error-strings.

Copy link
Contributor

@dmitshur dmitshur left a comment

Choose a reason for hiding this comment

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

Implementing Keyer will provide a significant performance boost when rendering siblings that may change order.

Ooh, that's very interesting. I'll want to play with it for Go Package Store (i.e., issue #92).

dom.go Outdated
}

// Keyer is an optional interface that Components may implement to uniquely
// identify an instance amongst a list of its siblings. Implementing Keyer
Copy link
Contributor

Choose a reason for hiding this comment

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

Another minor style issue. Go style uses a single space between sentences.

Source: https://dmitri.shuralyov.com/idiomatic-go#single-spaces-between-sentences.

dom.go Outdated
// core/central struct which all Component implementations should embed.
var (
errMissingParent = fmt.Errorf("missing parent node")
errEmptyElement = fmt.Errorf("empty element or node")
Copy link
Contributor

Choose a reason for hiding this comment

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

Also, minor, since these are static errors and you're not using any %v verbs, you could use the simpler errors.New instead of fmt.Errorf.

@pdf
Copy link
Contributor Author

pdf commented May 11, 2017

We may be able to make an additional improvement by reducing reflows using a single append to the DOM via a DocumentFragment, but I need to work out how best to handle deferring lifecycle (mount/unmount) events there, since they need to be triggered for children after the DOM change. Also need to determine which cases this is optimal for, but should be a safe bet for new elements at a minimum.

I probably won't tackle this strategy for this PR though.

@emidoots
Copy link
Member

emidoots commented May 11, 2017

Thanks for sending this. I'm on a vacation for two weeks (since Monday), so I have more spare time. I should have time to merge these changes soon. I'll respond to your other comment #106 (comment) here for better context.

I realise that you're keen to get some tests in before accepting PRs, and I understand that you've had little time to work on this project recently, however I'd like to get something more robust working than what we currently have so that I can move on with my project.

I totally understand your desire to push this forward. I'll be doing my best very soon (hopefully today) to take a look at these changes one-by-one and add tests for them while doing so. I should point out that it is hard to work on such a large PR as this, so I'll be personally breaking up your changes into smaller segments and referencing this PR. I'll keep your git author data attached, though, so it doesn't look like I am stealing your work :P I hope that's alright!

Although I would certainly have preferred smaller more scoped PRs, I just wanted to say thanks again for doing this! Your work was not a wasted effort, and I appreciate you taking the time to contribute!

Will be back with more soon.

@pdf
Copy link
Contributor Author

pdf commented May 11, 2017

@slimsag write:

I should point out that it is hard to work on such a large PR as this

Yes, and I apologise, but with the scope of the changes I wanted to make I couldn't see much in the way of alternatives - I essentially rewrote the render chain, and not much more than the prop/attr/etc assignment code remains of the original.

I tried to include a decent level of commenting, but if there are any explanations or clarifications I can provide that will ease your efforts, please don't hesitate to ask.

pdf added 8 commits May 13, 2017 01:35
This allows the creation of elements like inline SVG.

Refs hexops#54
NEW:
- `Keyer` interface provides support for efficient list element re-use.
  Components simply need to implement the `Key` function, or the
  `vecty.Key` Markup may be used for HTML.

BREAKING:
- `Restorer` interface is now `Updater`, and its `Restore` method is now
  `ShouldUpdate`. The previous `Restorer` implementation was variously
  broken in any case, and poorly named.

  Additionally, it requires a `Clone` method to support passing a
  previous Component instance to `ShouldUpdate`.  There is a limited
  generic version available on `vecty.Core` using reflection that may
  satisfy for users that do not wish to implement it themselves.

- `Context` method on `Component` interface is no longer public.

- `Restore` method on HTML is no longer public.
@pdf
Copy link
Contributor Author

pdf commented May 12, 2017

Rebased against master with the new node structure.

I'm still testing this - I think some of my DOM code may be affected by the wrappedObject.

@emidoots
Copy link
Member

emidoots commented May 12, 2017

Thanks for the rebase. I'm still working on tests against the master branch right now. Once that's done I will be picking apart portions of your branch to review and merge separately. I'll handle rebasing your branch in this repo once I begin doing that (and will open a 2nd PR / cc you)

This allows Mount handlers that depend on sibling or parent elements to
function as expected, and for performing tasks like detecting element
sizes.

On double-mount, perform unmount first.
On double-unmount, skip event.
@pdf
Copy link
Contributor Author

pdf commented May 16, 2017

@slimsag FYI, I have one bug to fix here that I'm aware of, related to a scenario where Rerender is called on a Component that has already been replaced.

Batching makes updates smoother, and dedup avoids unnecessary mutations,
since Component state must be maintained internally.
@pdf
Copy link
Contributor Author

pdf commented May 16, 2017

The above-mentioned bug should be fixed by d0d5cd0, which stops components from being re-rendered directly after they're removed, but retains the ability to pass components around and render them as children.

The latest commit (242ab03) adds batching via requestAnimationFrame, and deduplication of Component re-renders. I believe deduplication in this fashion should be safe since any component implementation I can think of must manage state internally, so we're just skipping over intermediate states. If you believe that there are some conditions where this may not be safe, we can omit dedup, but it's working well here. I may take one more pass over the code, but I wanted to get it out to obtain some feedback.

The raf dependency/polyfill I've pulled in is pretty small, so we could just add it locally if you'd prefer not to carry an external dependency for it.

@emidoots emidoots mentioned this pull request May 17, 2017
emidoots pushed a commit that referenced this pull request May 17, 2017
This allows the creation of elements like inline SVG.

Helps #54

Author amended to @pdf instead of me (@slimsag), to provide credit for his
original change at #107
@emidoots
Copy link
Member

emidoots commented May 17, 2017

ecbef2a, "Add support for namespaced elements", is the first part of your change that I've taken a look at. I've factored it out into #110 and merged it.

@emidoots
Copy link
Member

-> #112 for rebased branch

@pdf
Copy link
Contributor Author

pdf commented Jun 17, 2017

I think we may as well close this for now, let's work on getting changes in one at a time.

@pdf pdf closed this Jun 17, 2017
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.

3 participants