A Prototype's Name Is Refused

Status: refused by design

a.toString is not FunctionalScript. a.toString is valid JavaScript, and fjs compile refuses it by design: the demo below shows what it prints.

A property name that a built-in prototype defines, toString, push, constructor and the rest, is refused as a read: in JavaScript {}.toString finds a function on Object.prototype, which FunctionalScript does not have, so the read would answer something the value does not own. length is the one exception. To read what a value owns under such a name, the entry helper does (entries).

The row acc.prototype-name of refused constructs registers the refusal, and property accessor gives its reason.

Examples

export default typeof {}.toString;

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: function.

What to Write Instead

Read an own entry with the entry helper (spec/property-access/entries), as alternative.f.js does:

/** @type {(a: object, b: string) => unknown} */
const entry = (a, b) => {
    const x = Object.getOwnPropertyDescriptor(a, b);
    return x?.enumerable ? x.value : undefined;
};
export default typeof entry({}, "toString");

It answers undefined. {} owns no toString, so the read is undefined.

A Better Message

Today fjs compile prints prohibited property name 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:1:26 - error: prohibited property name
1 | export default typeof {}.toString;
  |                          ^

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

sample.mjs:1:26 - error: `toString` is a prototype's name: FunctionalScript reads only what a value owns
1 | export default typeof {}.toString;
  |                          ^^^^^^^^ JavaScript finds a function on `Object.prototype` here
  = help: read an own entry with the `entry` helper (spec/property-access/entries):
          export default typeof entry({}, "toString");
  = note: refused by design, see spec/property-access/prototype-names/README.md

JavaScript source, sample.mjs:

export default typeof {}.toString;

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

function

What to write instead

The FunctionalScript spelling, alternative.f.js:

/**
 * The FunctionalScript spelling of [`sample.mjs`](./sample.mjs): what `{}` owns under the name `toString`, read with the `entry` helper
 * ([`README.md`](./README.md)).
 *
 * @module
 */

/** @type {(a: object, b: string) => unknown} */
const entry = (a, b) => {
    const x = Object.getOwnPropertyDescriptor(a, b);
    return x?.enumerable ? x.value : undefined;
};
export default typeof entry({}, "toString");

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

const $0=($1,$2)=>{const $3=Object.getOwnPropertyDescriptor($1,$2);return $3?.enumerable?$3.value:undefined;};export default typeof $0({},"toString");

What it answers, its default export:

undefined

Emergent Testing

Idle. Press Run to start the suite.

  • ./proof.f.mjs