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

Default Modifier Manager #757

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

NullVoxPopuli
Copy link
Sponsor Contributor

@NullVoxPopuli NullVoxPopuli commented Jul 21, 2021

@NullVoxPopuli
Copy link
Sponsor Contributor Author

gonna try to update this RFC this weekend with all the things I learned from the default-helper-manager RFC and phrase things from first-principles' perspectives, and then we can get this RFC movin!!!!

@NullVoxPopuli
Copy link
Sponsor Contributor Author

Updated!

text/0757-default-modifier-manager.md Outdated Show resolved Hide resolved
text/0757-default-modifier-manager.md Outdated Show resolved Hide resolved
text/0757-default-modifier-manager.md Outdated Show resolved Hide resolved
text/0757-default-modifier-manager.md Show resolved Hide resolved
text/0757-default-modifier-manager.md Outdated Show resolved Hide resolved
text/0757-default-modifier-manager.md Outdated Show resolved Hide resolved
text/0757-default-modifier-manager.md Outdated Show resolved Hide resolved
text/0757-default-modifier-manager.md Outdated Show resolved Hide resolved
text/0757-default-modifier-manager.md Outdated Show resolved Hide resolved
Co-Authored-By: Chris Krycho <hello@chriskrycho.com>
@NullVoxPopuli
Copy link
Sponsor Contributor Author

Made an addon to try it out: https://github.com/NullVoxPopuli/ember-functions-as-modifiers-polyfill

@chriskrycho
Copy link
Contributor

Hey @NullVoxPopuli, we chatted about this briefly at today’s Framework Core team meeting, and we all agree that the basic idea is good, but folks had some thoughts about what the shape of the API should be, as well as how it fits in timing-wise with #779, which substantially ups the importance and perceived urgency of this design. We’ll be in touch to work through some of those details with you in a “spec” working group context to hammer down those details.

Thanks again for getting the ball rolling here!

@wagenet
Copy link
Member

wagenet commented Jul 23, 2022

We’ll be in touch...

Narrator: They were not in touch.


In all seriousness though, what needs to be done here? @chriskrycho

@chriskrycho
Copy link
Contributor

I believe we actually have been: @wycats has chatted with @NullVoxPopuli about a bunch of related pieces here (and for Resources), based in part on the Starbeam research, and I believe they’ve made some progress there. We should revisit current status though!

I believe the main consideration around function-based modifiers and a default manager is the exact shape of the teardown handling. The current design just returns a teardown function. I think the idea from Starbeam is to return a slightly richer object which includes that.

@wagenet
Copy link
Member

wagenet commented Jul 24, 2022

@chriskrycho I should have made it clear that I thought it was likely that there was some conversation, it’s just not visible here.

@wycats
Copy link
Member

wycats commented Aug 18, 2022

@chriskrycho said:

I believe the main consideration around function-based modifiers and a default manager is the exact shape of the teardown handling. The current design just returns a teardown function. I think the idea from Starbeam is to return a slightly richer object which includes that.

This is about right. The longer version is that Starbeam's design supports multiple setup blocks (each of which can run either in "layout" / pre-paint timing or in normal / idle timing), and each of which can have its own teardown.

Most but not all of this can theoretically be built on top of modifier manager. We don't need to add those features now, but it's nice for the "just a function" API design to leave space for future extensions along these lines.

Another consideration from Starbeam: Starbeam modifiers can be invoked with a "ref" that gets filled in dynamically with an element, and once the ref is filled in, the modifier's lifecycle begins.

Ember doesn't strictly need that design, because our lifecycle is largely managed through the implementation of the template runtime. However, if we want to support invoking modifiers directly, we might want to consider having them take a reference rather than an element. It's not strictly necessary, because you can always call the modifier in the same place as you fill in the element reference.

That said, for Starbeam, the extra indirection allows the reference to be filled in by the internals of third-party code (like another framework), and this may be useful for Ember as well.

I don't think any of this is a blocker to making some tactical progress on this issue, but I suppose @NullVoxPopuli and I should work together to update this proposal to match the Starbeam design and see what people think 😄

@MelSumner
Copy link
Contributor

@wycats @NullVoxPopuli nudge to work on this RFC and update it. <3

@chriskrycho chriskrycho added the S-Exploring In the Exploring RFC Stage label Dec 1, 2022
@wagenet wagenet assigned wycats and unassigned chriskrycho Jan 13, 2023
@NullVoxPopuli
Copy link
Sponsor Contributor Author

Gonna copy some disco from Discord so it doesn't get lost:


last we schemed, we were thinking about ditching ember-modifier in favor of resources -- something similar to: https://reactive.nullvoxpopuli.com/functions/resource_modifier.modifier.html

tho, in general, we need native support for resource builders so the modifier import wouldn't be needed

there are some questions about timing as well, related to

cc @runspired @wycats @ef4

one main thing we need for any of this to be ergonomic is to have a chained invocation (at some timing) in the rendering layer.
like:

// modifier
function myModifier(element, ...args) {
  // abstraction that handles cleanup here 
}

// resource
function ConnectionStatus() {
  // abstraction that handles cleanup here
}

// these are the same, authoring wise, except for their signature and usage in syntax:
<template>
  <div {{myModifier}}>{{Clock}}</div>
</template>

where:

  // abstraction that handles cleanup here

could be:

function myModifier(element, ...args) {
  return resource(({ on }) => {
    on.cleanup(() => {});
  });
}

function ConnectionStatus() {
  return resource(({ on }) => {
    on.cleanup(() => {});
    
    return () => someValue;
  });
}

or

function myModifier(element, ...args) {
  // setup here 
  
  return {
    /* custom properties for reactivity or something */,
    /* handle for the framework to destroy, like on.cleanup */
    [Symbol.dispose]() {
      // cleanup here
    }
  }
}

function ConnectionStatus() {
  // setup here 
  
  return {
    // special getter? or do we require properties?
    // (eliminating the possibility that resources today 
    //  have where they can represent plain values
    //  (I would not like losing that 😅 )
    get value() {
      return someValue;
    },
    /* custom properties for reactivity or something */,
    /* handle for the framework to destroy, like on.cleanup */
    [Symbol.dispose]() {
      // cleanup here
    }
  }
}

using Symbol.dispose could one day be the implementation of resources -- but we still have to explore timing semantics, as on gives us more API/timing surfaces to explore (as well as a synchronization phase, which can't currently be implemented in ember)

an idea if/when dispose lands to get plain values back, maybe we could do some... prototype hacks.
function ConnectionStatus() {
  // setup here 
  
  const result = someValue;
  
  result[Symbol.dispose] = () => { /* cleanup */ };
  
  return result;
}

idk, probably terrible.

the chained invocation is needed because we need to call the factory function, and then "do something" with the thing it returns.

this would either be using the HelperManager or ModifierManager syntems based on usage in the template (edited)
in any case, it'd be very hard to get away from any imports for modifiers unless you didn't need cleanup at all

tho, an importless modifier could be one that uses native disposables, like above -- but we don't even have Symbol.dispose yet in browsers, so we can't really do that yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-Exploring In the Exploring RFC Stage T-framework RFCs that impact the ember.js library T-templates
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants