Exporting then Is Refused

Status: refused by design

export const then is not FunctionalScript. export const then = …; is valid JavaScript, and fjs compile refuses it by design: the demo below shows what it prints.

JavaScript treats any object whose then member is a function as a promise, a module namespace included: await import("./m.mjs") of a module that exports a function then calls it, and answers what it passes on rather than the module. A then that is no function is ignored, so whether importing a module answers the module would depend on the type of one export. FunctionalScript reserves then as an export name, whatever its value, and nowhere else: a local const, a parameter or an import may be called then (exporting a value).

The row name.reserved-export of refused constructs registers the refusal, and exporting a value gives its reason.

Examples

/** @type {(resolve: (value: number) => void) => void} */
export const then = resolve => resolve(1);
export default 0;

The demo on this page compiles sample.mjs, the module above, with this build's fjs compile, and shows the line it prints and the token it refuses. Below that it shows what JavaScript answers for the same module: 0, its default export as a static import reads it. The same module loaded with await import() answers 1, what then passed on.

What to Write Instead

Export the value under another name, as alternative.f.js does:

/** @type {(resolve: (value: number) => void) => void} */
export const next = resolve => resolve(1);
export default 0;

It answers 0. await import() of this module answers the module.

A Better Message

Today fjs compile prints reserved export name then at the refused token. The demo proposes what it should print instead: the reason at the same token, what JavaScript does there, and the allowed spelling, the line alternative.f.js writes, as help. The page compiles the alternative too, so the suggestion is one the compiler accepts.

Reference

Demo

Not allowed in FunctionalScript

This is valid JavaScript, and fjs compile refuses it, by design: it is not a FunctionalScript module.

What fjs compile sample.mjs output.js prints:

sample.mjs:2:14 - error: reserved export name then
2 | export const then = resolve => resolve(1);
  |              ^

What it should print instead, pointing to what FunctionalScript allows (proposed):

sample.mjs:2:14 - error: `then` is reserved as an export: JavaScript treats a module that exports a function `then` as a promise
2 | export const then = resolve => resolve(1);
  |              ^^^^ `await import()` of this module calls this and answers `1`, not the module
  = help: export the value under another name:
          export const next = resolve => resolve(1);
  = note: refused by design, see spec/modules/exports/then/README.md

JavaScript source, sample.mjs:

/** @type {(resolve: (value: number) => void) => void} */
export const then = resolve => resolve(1);
export default 0;

What JavaScript answers for the same module, its default export:

0

What to write instead

The FunctionalScript spelling, alternative.f.js:

/**
 * The FunctionalScript spelling of [`sample.mjs`](./sample.mjs): the same export under a name a promise does not read
 * ([`README.md`](./README.md)).
 *
 * @module
 */

/** @type {(resolve: (value: number) => void) => void} */
export const next = resolve => resolve(1);
export default 0;

What fjs compile alternative.f.js output.js writes:

export const next=($0)=>$0(1);export default 0;

What it answers, its default export:

0

Emergent Testing

Idle. Press Run to start the suite.

  • ./proof.f.mjs