rfcs icon indicating copy to clipboard operation
rfcs copied to clipboard

Default Modifier Manager

Open NullVoxPopuli opened this issue 4 years ago • 10 comments

Rendered

Polyfill: https://github.com/NullVoxPopuli/ember-functions-as-modifiers-polyfill

Places to update (if they aren't mentioned in the RFC (I forget))

  • https://guides.emberjs.com/release/components/template-lifecycle-dom-and-modifiers/#toc_abstracting-the-logic-into-a-custom-modifier

NullVoxPopuli avatar Jul 21 '21 22:07 NullVoxPopuli

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 avatar Dec 10 '21 22:12 NullVoxPopuli

Updated!

NullVoxPopuli avatar Dec 14 '21 00:12 NullVoxPopuli

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

NullVoxPopuli avatar Jan 09 '22 00:01 NullVoxPopuli

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!

chriskrycho avatar Feb 19 '22 00:02 chriskrycho

We’ll be in touch...

Narrator: They were not in touch.


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

wagenet avatar Jul 23 '22 23:07 wagenet

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.

chriskrycho avatar Jul 24 '22 02:07 chriskrycho

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

wagenet avatar Jul 24 '22 03:07 wagenet

@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 😄

wycats avatar Aug 18 '22 19:08 wycats

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

MelSumner avatar Sep 09 '22 18:09 MelSumner

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

  • https://github.com/emberjs/rfcs/pull/883
  • and https://github.com/emberjs/rfcs/pull/957

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.

NullVoxPopuli avatar Jan 24 '24 22:01 NullVoxPopuli