Skip to content

Normative: Make tail-call optimization normative-optional to match web reality - #3957

Open
gibson042 wants to merge 1 commit into
tc39:mainfrom
gibson042:2026-08-normative-optional-tco
Open

Normative: Make tail-call optimization normative-optional to match web reality#3957
gibson042 wants to merge 1 commit into
tc39:mainfrom
gibson042:2026-08-normative-optional-tco

Conversation

@gibson042

@gibson042 gibson042 commented Aug 22, 2026

Copy link
Copy Markdown
Member

Tail-call optimization was introduced in ECMAScript 2015 (ES6), before our current staging process and before ecmarkup. In the intervening 11 years, it seems to have been included in just one browser implementation and one non-browser implementation:

$ eshost -sx '(function() {
  "use strict";
  function tcoable(n) {
    if (--n <= 0) return;
    return tcoable(n);
  }
  try {
    tcoable(1e9);
    print("TCO ");
  } catch (err) {
    print("TCO ");
  }
})()'
#### GraalJS, Hermes, LibJS, QuickJS, SpiderMonkey, V8
TCO 

#### JavaScriptCore, Moddable XS
TCO 

If it were being proposed today, this would be deemed insufficient for advancement to Stage 4.

It's time to acknowledge reality and update the spec to clarify that tail-call optimization is in fact not required for conformance.

@gibson042 gibson042 added normative change Affects behavior required to correctly evaluate some ECMAScript source text needs consensus This needs committee consensus before it can be eligible to be merged. web reality labels Aug 22, 2026
@github-actions

Copy link
Copy Markdown

The rendered spec preview for this PR is available as a single page at https://tc39.es/ecma262/pr/3957 and as multiple pages at https://tc39.es/ecma262/pr/3957/multipage .

@mhofman

mhofman commented Aug 22, 2026

Copy link
Copy Markdown
Member

IMO this is dealing in unobservable optimizations in a theoretical infinite resource machine. The only reason this is observable in the first place is because in practice there is a call stack limit in implementations.

I wasn't around at the time. But why wasn't TCO added as an editor note instead?

@devsnek

devsnek commented Aug 22, 2026

Copy link
Copy Markdown
Member

IMO this is dealing in unobservable optimizations in a theoretical infinite resource machine

if you're saying this to suggest that the spec shouldn't concern itself with TCO, then this seems a touch overzealous to me. the presence of TCO fundamentally changes how you can author JS code, because we don't run that code on theoretical infinite resource machines...

@mhofman

mhofman commented Aug 22, 2026

Copy link
Copy Markdown
Member

the presence of TCO fundamentally changes how you can author JS code, because we don't run that code on theoretical infinite resource machines

And that's the reality today, as code needs to know it's running under an implementation that supports TCO to reliably use tail calls. Actually I think both this PR and my suggestion send a better signal to authors: be mindful of relying on TCO.

@devsnek

devsnek commented Aug 22, 2026

Copy link
Copy Markdown
Member

That I can agree with :)

@chicoxyzzy

chicoxyzzy commented Aug 23, 2026

Copy link
Copy Markdown
Member

For the record, it’s also implemented in https://github.com/chicoxyzzy/cynic (which, as far as I know, no one uses, though 😅).

@linusg

linusg commented Aug 24, 2026

Copy link
Copy Markdown
Member

For the record, it’s also implemented in https://github.com/chicoxyzzy/cynic (which, as far as I know, no one uses, though 😅).

Citing what appears to be a largely LLM-generated codebase - and thus steered by status quo spec and test262 tests - for this language change seems questionable to me, unless you actively decided to include the feature despite what the majority of implementations do. In that case present your own reasoning for doing so instead.

@hax

hax commented Sep 1, 2026

Copy link
Copy Markdown
Member

Can we revisit https://github.com/tc39/proposal-ptc-syntax ?

@mhofman

mhofman commented Sep 1, 2026

Copy link
Copy Markdown
Member

Can we revisit https://github.com/tc39/proposal-ptc-syntax ?

What would be the expectation for async functions?

Async functions suffer from a similar issue where a chain of promise resolved to another promise is not collapsed in any JS engine implementation. Unlike for sync TCO, collapsing the chain of resolution may be observable if user code can add reactions to intermediate promises. While it's not a stack exhaustion like sync tail call, there is growing heap space taken by the chain of promises and internal reactions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs consensus This needs committee consensus before it can be eligible to be merged. normative change Affects behavior required to correctly evaluate some ECMAScript source text web reality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants