tc39/proposal-function.sent

Review of function.sent

Closed this issue · 25 comments

Opening this thread to put a review of the function.sent proposal
@bterlson @domenic

  • Probably you should attach LastYieldValue as an internal slot of the GeneratorObject (in Table 56), rather than in Table 24. This is an aesthetic judgement, though.
  • There are a couple cases where function.sent can have a default undefined value visible. Was this intentional? Should we get a TDZ in these cases, or is undefined the intention? I have no preference here.
    • after calling generator.return(), in the finally block
    • in default argument evaluation for the generator

Also, sounds like function.sent can't be used from an eval inside the generator, in this spec text, since it wouldn't be produced by the grammar. I'm happy with that decision, but I wanted to double-check that that was the intention.

I like undefined over exception, personally. It would be pretty easy to change this to throw for those cases (strawman: GeneratorStart and GeneratorYield set the slot to Empty rather than undefined, and function.sent can throw if it sees Empty). I am having trouble coming up with a strong rationale for either side. Wonder what @allenwb thinks?

Given that you can't yield from eval I wouldn't expect that you can function.sent in eval either.

I think things like new.target and function.sent should consistently work like lexically scoped variables with fancy names. In that sense, it would be rather odd if they weren't accessible from an eval.

anba commented

in default argument evaluation for the generator

This is not possible in the current draft because of the [Yield] production parameter restriction.

@rossberg-chromium yeah I agree in principle that this should probably work inside eval, but it would mean we can't throw a syntax error for function.sent outside of generator bodies without much effort. Would you say it's ok for function.sent to work like new.target in the sense that it is allowed everywhere, returns undefined when not inside a generator, and store [[LastYieldValue]] on the lexical environment rather than execution context?

Also means the following works:

function* foo() {
  let thunk = () => function.sent;
  yield;
  thunk();
}

Seems ok?

Treating it like a fancily named variable would imply that it is simply unbound outside any generator. That is, it would yield a static ReferenceError in strict mode, or a dynamic ReferenceError in sloppy mode.

There are a couple cases where function.sent can have a default undefined value visible. Was this intentional? Should we get a TDZ in these cases, or is undefined the intention? I have no preference here.
after calling generator.return(), in the finally block

I believe the finally after generator.return is the only place this is observable. This was not intentional.

However, the only reason that I specified that GeneratorYield should set LastYieldValue to undefined was to keep from memory leaking the current LastYieldValue in case the generator object (and associated) context was retained but never activated again. However, I was assuming that setting it to undefined was unobservable.

Given that it is observable and that the generator context is also potentially memory leaking all the state referenced from its local variable bindings I don't think we should be concerned about plugging that one potential leak source.

I suggest that we simply delete from the proposal the change to GeneratorYield. Then finally blocks will see the last actual sent value via function.sent and the memory leakage potential of function.sent is the same as any local variable of the generator function.

@allenwb are you still interested in advancing function.sent? If so, it'd be great if you could make a proposal repo for it, and then we can move this thread there.

I'm generally out of the proposal writing and championing business. Assuming that the committee is still interested, somebody else should take it over.

It's a relatively small features so I suspect that one of the editors could just pick it up fairly easily.

Absent a champion, it should probably be considered withdrawn - I’ll add an item to this week’s agenda to ask if anyone is interested in picking it up.

Absent a champion, it should probably be considered withdrawn

I don't think that's correct. As a stage two means: "The committee expects the feature to be developed and eventually included in the standard". A champion resigning from that role because they have become less active within TC39 is not the same thing as withdrawing the proposal and it isn't by intent to withdraw it.

If the committee wants to change it's mind it certainly can, but otherwise it needs to identify a new champion.

Fair point; either way I'll ask for a champion to step up.

@ljharb Thanks for bringing this up at the meeting. Have you heard any interest?

Nothing yet; I’ll update here if i do.

OK, if we continue to not get a champion in the committee, I like your idea of considering it withdrawn at some point.

Techincally the category is “inactive”, and things may be inactive because they’re withdrawn, or rejected; I’m sure we could put “no champion” as the reason.

What does "considering it withdrawn" mean? I don't think any real or "considered" action taken via this thread is appropriate.

TC39 in meeting and via a minuted consensus decision, promoted this proposal to Stage 2. It should require a similar decision by TC39 to change its status to something else. It is presumably the responsibility of the TC39 management team to set agenda items to address such situations. I don't believe that it is appropriate for such an agenda item to recommend "considering the proposal" withdrawn. An appropriate item for the committee would be: "XXX is no longer available to serve as champion for this stage 2 proposal. If TC39 still believe that it expects the feature to be developed and eventually included in the standard then it must appoint a new champion."

That is exactly how it’s going to go - i had an agenda item last month to ask for a new champion, if none arises, we’ll add an agenda item to make the proposal inactive, which would include seeking committee consensus that the feature no longer is intended to be developed and included in the language. If a champion materializes, then it’ll be a moot point.

Thanks for taking this on, @ljharb. That strategy sounds fair to me. I am not against function.sent, but it is really helpful to have this clearly articulated and up to date metadata about what is happening with proposals.

It's been almost a year since https://github.com/rwaldron/tc39-notes/blob/c2aaad7ef4a348b7ab019cca9f19b07f7484478a/es9/2018-03/mar-22.md#functionsent-needs-a-champion and nobody's stepped up to champion this proposal. It seems that we need an agenda item to make the proposal inactive. I won't be physically present in June, so I'll add this to the July agenda if nobody else beats me to it.

Today at TC39, @hax has volunteered to champion function.sent; I'll help them create a proposal repo. @allenwb, if you could add me as a maintainer of this repo, I can transfer the relevant issues directly into the new proposal repo.

@hax are you still planning to champion function.sent?

The repo is at https://github.com/tc39/proposal-function.sent; I’ll transfer this issue there once i can get a GitHub problem sorted out.

In the meantime, closing, as @hax is now the champion for this proposal.

hax commented

@devsnek Yes, I am working on it and trying different approaches to solve the current issues. May present updates in the future meetings if I finished the experiments.