arthurfiorette / proposal-safe-assignment-operator

Draft for ECMAScript Error Safe Assignment Operator
https://arthur.run/proposal-safe-assignment-operator/
MIT License
1.13k stars 12 forks source link

Conflating `obj[Symbol.result]` with `func[Symbol.result]` breaks functions returning functions #23

Closed andersk closed 4 weeks ago

andersk commented 4 weeks ago

The meanings of Symbol.result in obj[Symbol.result] and func[Symbol.result] are very different. obj[Symbol.result]() is a result corresponding to obj itself, while func[Symbol.result]() is a result corresponding to the return value of func.

Using the same symbol for both of these meanings, along with recursive unwrapping (#6), completely breaks functions that return other functions.

const inner = () => console.log("inner() called");
const outer = () => inner;

try {
    const f = outer(); // returns inner without calling inner()
} catch {}

const [error, data] ?= outer(); // unexpectedly calls inner()

This evaluates as outer[Symbol.result]()inner[Symbol.result]()[null, console.log("inner called")].

Even if you think recursive unwrapping is a good idea, it should only recurse through obj[Symbol.result], not func[Symbol.result]. So we need to use two different symbols for these different meanings.

anacierdem commented 4 weeks ago

This relates to #12

andersk commented 4 weeks ago

Oh I see the polyfill checks typeof result === "object" before recursing. That’s not clear from the description but this hasn’t reached the stage where specification wordsmithing is helpful, so closing for now.