ecma262 icon indicating copy to clipboard operation
ecma262 copied to clipboard

Editorial: define thenable

Open ikravets opened this issue 2 years ago • 2 comments

a quick fix for #2868

ikravets avatar Aug 23 '22 11:08 ikravets

I'd like to discuss a seemingly simple question "Is p promise?" a little bit more.

First, it leads me to a more general question: what constitute an is-a relation in JavaScript? I'm not sure the spec addresses this question explicitly. In general OOP sense, is-a determines which behavior is expected from an object (according to its (sub-)type). [[Prototype]] assignment changes the behavior and can be considered a change of an object (sub-)type. For example, instanceof operator can be easily "broken":

const p = Promise.resolve();
console.log(p instanceof Promise); // --> true
Object.setPrototypeOf(p, null); 
console.log(p instanceof Promise); // --> false! Is p still a Promise?

When we "break" the expected behavior of an object should its "type" be considered the same? Here by the "type" I don't mean the result of typeof operator, but the more general OOP meaning, which probably better corresponds to OrdinaryHasInstance ( C, O ).

In case of Promise we indeed have IsPromise() in the spec, but is it the sole source of truth for an "is p a promise" question? How this is determined for other types which do not have Is%Typename%() operation?

Back to the Promise Objects section. There are two definitions literally a dozen lines above the proposed patch:

  • A promise p is fulfilled if p.then(f, r) will immediately enqueue a Job to call the function f.
  • A promise p is rejected if p.then(f, r) will immediately enqueue a Job to call the function r.

When we break the [[Prototype]] these definitions no longer work. I guess, a non-negligible part of the spec breaks as well when we allow [[Prototype]] setting in arbitrary places. And of course there are also infinite number of possibilities to adjust the [[Prototype]] and thus the behavior to different extents which may constitute a different degrees of "behavior breakage".

Now back to your question "Is p promise?". I think that until is-a is formally defined in the spec[^1] my answer would be: it depends on what do you mean by that question. If you mean IsPromise(p) the answer is 'yes', if you mean p instanceof Promise the answer is 'no'.

Summarizing the more general part:

  • is there an official definition for is-a relation in the JavaScript spec[^1]?
  • what about subtyping in the general OOP sense?
  • should one be added?
  • should we open a new discussion/issue regarding this subject?

What do you think?

I'm by no means a JavaScript (or any language) expert, quite the opposite. A feedback from more experienced people is much appreciated.

[^1]: and please point me to such a definition if it exists!

ikravets avatar Aug 25 '22 10:08 ikravets

is there an official definition for is-a relation in the JavaScript spec?

No.

what about subtyping in the general OOP sense?

No.

should one be added?

In my opinion, no. None of the normative requirements in the spec require us to give precise definitions to any of those, and they are used in somewhat vague ways in general, so it's best we stay out of trying to give precise definitions.

bakkot avatar Aug 25 '22 20:08 bakkot