For AI agents: the complete documentation index is available at /tc39-atlas/en/llms.txt, the full documentation bundle is available at /tc39-atlas/en/llms-full.txt, and this page is available as Markdown at /tc39-atlas/en/proposals/proposal-wavy-dot.md.
  • English
  • Wavy Dot: Syntactic Support for Promise Pipelining S1

    Proposal details
    Proposal overview

    This proposal introduces a new syntax 'wavy dot' (~.) for promise pipelining, providing syntactic sugar for the eventual-send API. It defines an infix operator with the same precedence as dot (.) to enable eventual gets and method calls on promises.

    Note

    The README below comes from the upstream repository and may contain outdated stage or status metadata. Use the proposal details above as the current source of truth.

    proposal-wavy-dot

    Pleasant Notation for promise pipelining.

    • Mark S. Miller @erights, Agoric
    • Michael Fig @michaelfig, Agoric
    • Chip Morningstar @FUDCo, Evernote

    Status

    Presented to TC39 (Javascript standards committee), achieving stage 1.

    Presentation to TC39

    Slides

    Summary

    This is a follow on proposal to proposal-eventual-send, providing syntactic sugar for the APIs of that proposal.

    The 2011 ECMAScript strawman concurrency proposal also described a simple desugaring of an infix bang (!) operator to support promise pipelining. To avoid conflict with TypeScript, this proposal instead introduces the wavy dot (~.) syntax.

    Wavy Dot

    Like the (?.) of the optional chaining proposal, wavy dot (~.) is a proposed infix operator with the same precedence as dot (.). Both can be understood as adjective dot, i.e., an operation that is dot-like, but differs according to the adjective. Once the optional chaining proposal is accepted, we will add to this proposal an operator combining the two adjectives, such as (?~.) or (~?.).

    When the wavy dot expression occurs in a syntactic context in which the value of the expression might be used, the syntax has the following equivalences

    SyntaxInternal Method
    p~.namep.[[GetSend]]('name')
    p~.[prop]p.[[GetSend]](prop)
      
    p~.(...args)p.[[ApplyFunctionSend]](args)
      
    p~.name(...args)p.[[ApplyMethodSend]]('name', args)
    p~.[prop](...args)p.[[ApplyMethodSend]](prop, args)

    When the expression occurs in a syntactic context where the value of the expression is obviously ignored, such as an ExpressionStatement, the equivalences are as above, but using the [[*SendOnly]] variant of these internal methods.

    SyntaxInternal Method
    void p~.(...args);p.[[ApplyFunctionSendOnly]](args)
      
    void p~.name(...args);p.[[ApplyMethodSendOnly]]('name', args)
    void p~.[prop](...args);p.[[ApplyMethodSendOnly]](prop, args)

    Proposed Syntax

    Abstract Syntax:

     Expression : ...
          Expression ~. [ Expression ]              // eventual get
          Expression ~. Arguments                   // eventual apply function
          Expression ~. [ Expression ] Arguments    // eventual apply method

    Attempted Concrete Syntax, where "..." signifies the existing productions of that non-terminal. Our intention is that this syntax follow the pattern of the optional chaining proposal.

      WavyDot ::
          ~. [lookahead ∉ DecimalDigit]
    
      MemberExpression : ...
          MemberExpression WavyDot [ Expression ]
          MemberExpression WavyDot IdentifierName
      CallExpression : ...
          CallExpression WavyDot [ Expression ] Arguments
          CallExpression WavyDot IdentifierName Arguments
          MemberExpression WavyDot Arguments
          CallExpression WavyDot Arguments
          CallExpression WavyDot [ Expression ]
          CallExpression WavyDot IdentifierName

    Prototype

    A Babel playground implements this proposal using static methods on the HandledPromise object that is in the current scope. The Work-In-Progress Babel pull request for this syntax is also available.