Skip to content

Commit

Permalink
Add explanation of vtable-as-brand for exotic objects
Browse files Browse the repository at this point in the history
  • Loading branch information
syg committed Jan 10, 2020
1 parent 390999e commit 69a884b
Showing 1 changed file with 3 additions and 1 deletion.
4 changes: 3 additions & 1 deletion spec.html
Original file line number Diff line number Diff line change
Expand Up @@ -8846,7 +8846,9 @@ <h1>CreateBuiltinFunction ( _steps_, _internalSlotsList_ [ , _realm_ [ , _protot

<emu-clause id="sec-built-in-exotic-object-internal-methods-and-slots">
<h1>Built-in Exotic Object Internal Methods and Slots</h1>
<p>This specification defines several kinds of built-in exotic objects. These objects generally behave similar to ordinary objects except for a few specific situations. The following exotic objects use the ordinary object internal methods except where it is explicitly specified otherwise below:</p>
<p>This specification defines several kinds of built-in exotic objects. These objects generally behave similar to ordinary objects except for a few specific situations.</p>
<p>In some algorithms, there are steps of the form "If object is an X exotic object, ...", where X names a kind of exotic object such as Array, Bound Function, or Proxy. Each kind of exotic object is specified to have a particular collection of internal methods. A conformant implementation must provide X exotic objects and must recognize them as such by inspecting the object's internal methods. In other words, an implementation-provided exotic object that is behaviourally equivalent to an X exotic object but does not have the same collection of internal methods specified for X exotic objects is not recognized as an X exotic object.</p>

This comment has been minimized.

Copy link
@jmdyck

jmdyck Jan 10, 2020

Collaborator

Well, that wording implies that internal methods exist in the implementation (and can be inspected), which is at odds with the idea that internal methods are merely a specification mechanism (defined "purely for expository purposes"). But that doesn't seem to bother anyone else, so I've almost given up.


More concerning though: consider an implementation-provided exotic object that has exactly the same collection of internal methods specified for X exotic objects, but was created in a different way. This wording suggests that that object would be recognized as an X exotic object, but presumably we don't want it to be.

One way to resolve this problem would be if the XCreate operation were somehow part of "the collection of internal methods for X"; however, that wouldn't really make sense with the way things are set up now.


Here's some revised wording that takes from both, is less verbose that either, and avoids the above problems:

In some algorithms, there are steps of the form "If object is an X exotic object, ...", where X names a kind of exotic object such as Array or Bound Function. A conformant implementation must provide X exotic objects, and must recognize them as such in steps of this form. Any other object, even if it has equivalent behaviour to an X exotic object, must not be recognized as an X exotic object.

(BTW, I dropped the "or Proxy" because it kept sounding to me like a complete list (which of course it isn't), even despite the "such as". With only 2 items, it seems clearer that it's just a couple of examples.)

This comment has been minimized.

Copy link
@syg

syg Jan 10, 2020

Author Contributor

Well, that wording implies that internal methods exist in the implementation (and can be inspected), which is at odds with the idea that internal methods are merely a specification mechanism (defined "purely for expository purposes"). But that doesn't seem to bother anyone else, so I've almost given up.

I mean... not really? It implies observable behavior in the spec can depend on the spec being able to inspect those spec-internal methods. This is true of literally everything in the spec. I can change the wording to "[...] and must recognize them as such. The spec recognizes them by inspecting the object's internal methods."

consider an implementation-provided exotic object that has exactly the same collection of internal methods specified for X exotic objects, but was created in a different way. This wording suggests that that object would be recognized as an X exotic object, but presumably we don't want it to be.

That is intentional. That's how structural typing usually works in JS -- the gatekeeping isn't going through the right creation methods, but having the right set of internal methods.

As for your newest revision, editorially, I don't it gets across the idea that internal methods are what's distinguishing the exotic objects, just that what's not distinguishing them is behavioral equivalence. I'm tempted to just shorten the prose to something like:

The spec recognizes different kinds of exotic objects by those objects' internal methods. An object that is behaviourally equivalent to a particular kind of exotic object (such as Array or Bound Function) but does not have the same collection of internal methods is not recognized as that kind of exotic object.

This comment has been minimized.

Copy link
@jmdyck

jmdyck Jan 10, 2020

Collaborator

observable behavior in the spec can depend on the spec being able to inspect those spec-internal methods.

I'm okay with that.

I can change the wording to "[...] and must recognize them as such. The spec recognizes them by inspecting the object's internal methods."

I think that would address my concern.

consider an implementation-provided exotic object that has exactly the same collection of internal methods specified for X exotic objects, but was created in a different way. This wording suggests that that object would be recognized as an X exotic object, but presumably we don't want it to be.

That is intentional.

Hold on: you're saying that we do want the object I described to be recognized as an X exotic object? This surprises me, because I got the impression that at least some TC39ers saw the semantics of (for instance) ArrayCreate as being important to determining whether something "is" an Array exotic object.

If XCreate is part of the specification of required behavior for X exotic objects, and an object is created in a way that doesn't conform to the semantics of XCreate, then it doesn't fulfill the requirements of an X exotic object, so it would be fairly odd for "object is an X exotic object" to succeed for it.

But it sounds like you're saying that XCreate isn't part of the required semantics for X exotic objects. (Objects created in conformance with XCreate will certainly qualify as X exotic objects, but they're just a subset. The real criterion is just the set of internal methods.) I suppose that could be a coherent position, but it seems like the spec isn't really encouraging me to think that way, given that the clause that defines X exotic objects includes the definition of XCreate among the definitions of X's internal methods.

As for your newest revision, editorially, I don't it gets across the idea that internal methods are what's distinguishing the exotic objects,

Indeed it doesn't, because I thought that example would go differently.

The spec recognizes different kinds of exotic objects by those objects' internal methods. An object that is behaviourally equivalent to a particular kind of exotic object (such as Array or Bound Function) but does not have the same collection of internal methods is not recognized as that kind of exotic object.

I might agree that that's a valid statement of the desired semantics, but I'm not really sure which way is up any more.

This comment has been minimized.

Copy link
@syg

syg Jan 10, 2020

Author Contributor

Hold on: you're saying that we do want the object I described to be recognized as an X exotic object? This surprises me, because I got the impression that at least some TC39ers saw the semantics of (for instance) ArrayCreate as being important to determining whether something "is" an Array exotic object.

If XCreate is part of the specification of required behavior for X exotic objects, and an object is created in a way that doesn't conform to the semantics of XCreate, then it doesn't fulfill the requirements of an X exotic object, so it would be fairly odd for "object is an X exotic object" to succeed for it.

But it sounds like you're saying that XCreate isn't part of the required semantics for X exotic objects. (Objects created in conformance with XCreate will certainly qualify as X exotic objects, but they're just a subset. The real criterion is just the set of internal methods.) I suppose that could be a coherent position, but it seems like the spec isn't really encouraging me to think that way, given that the clause that defines X exotic objects includes the definition of XCreate among the definitions of X's internal methods.

Right, I am saying that XCreate isn't what confers the brand, the brand is just the internal method vtable. The distinction is that XCreate isn't a special method: just its being called isn't enough to confer the brand, it has to the do the right thing as well. However, XCreate not setting the internal method vtable correctly should be a bug, since that would be super confusing to not follow the convention that XCreate always correctly creates X exotic objects.

This kind of setup offers the most editorial freedom. Suppose in the future we want to create X exotic objects a little differently. If the distinguishing thing was which allocation method you called, that ties our hands more editorially than is necessary.

Do you remember where the discussion was for thinking ArrayCreate being important for distinguishing whether something is an Array exotic object? Instead I remember the opposite argument being made and agreed to, that checking for a particular allocation abstract method having been used shouldn't be material.

This comment has been minimized.

Copy link
@syg

syg Jan 10, 2020

Author Contributor

btw PTAL at the latest commit.

This comment has been minimized.

Copy link
@jmdyck

jmdyck Jan 11, 2020

Collaborator

Hold on: you're saying that we do want the object I described to be recognized as an X exotic object? This surprises me, ...

Right, I am saying that XCreate isn't what confers the brand, the brand is just the internal method vtable.

I understand that part -- I'm wondering how to square it with other aspects of the spec.

The distinction is that XCreate isn't a special method: just its being called isn't enough to confer the brand, it has to the do the right thing as well.

Although, up until this PR, it's basically the definition of what the right thing is, so the possibility of it not doing the right thing can't really arise.

However, XCreate not setting the internal method vtable correctly should be a bug, since that would be super confusing to not follow the convention that XCreate always correctly creates X exotic objects.

You mean a spec bug, right? But, to be clear, XCreate not setting the internal methods correctly isn't the example case I brought up.

This kind of setup offers the most editorial freedom. Suppose in the future we want to create X exotic objects a little differently. If the distinguishing thing was which allocation method you called, that ties our hands more editorially than is necessary.

I'm not sure what you mean. We can always make editorial changes to XCreate whether it's part of the required semantics of X exotic objects or not.

Do you remember where the discussion was for thinking ArrayCreate being important for distinguishing whether something is an Array exotic object?

Mostly in Issue #1453. E.g. here is @allenwb saying "Within ECMA-262, an object is an Array exotic object if and only if it is created using the ArrayCreate abstract operations." And here he clarifies that there's no magic involved with the ArrayCreate name.

And in the last sentence of this, I think he's saying that anything that an implementation wants to call an Array exotic object must be observably no different from objects created in conformance with ArrayCreate. By which I infer that my example object (not created in conformance with XCreate) would not qualify as an X exotic object, counter to what you're saying above. (And I notice that you gave that comment a thumbs-up, so I'm quite puzzled.)

Instead I remember the opposite argument being made and agreed to, that checking for a particular allocation abstract method having been used shouldn't be material.

There were multiple possibilities discussed (see here for 3 of them), so I don't think it's correct to say "the opposite argument", but yes, arguments were made, but not agreed to that I know of. (Was it discussed at a meeting? I don't think so, but maybe I missed it.) I think basically the discussion just moved to this PR.

This comment has been minimized.

Copy link
@syg

syg Jan 14, 2020

Author Contributor

You mean a spec bug, right?

Yeah, I mean a spec bug.

And in the last sentence of this, I think he's saying that anything that an implementation wants to call an Array exotic object must be observably no different from objects created in conformance with ArrayCreate. By which I infer that my example object (not created in conformance with XCreate) would not qualify as an X exotic object, counter to what you're saying above. (And I notice that you gave that comment a thumbs-up, so I'm quite puzzled.)

What I am saying and what I think Allen agrees with is something like this:

WLOG, let's talk about Array exotic objects.

  • The spec provides a single way to create Array exotic objects with ArrayCreate.
  • The spec provides a decidable way to detect if an object is an Array exotic object with internal methods vtable brand checking.
  • Ontologically, the vtable brand is what an exotic object is, not that it was allocated by an Abstract Operation named ArrayCreate.
  • Within the closed world of Ecma262, the two imply each other. So a conformant implementation without extensions should do all the observable things that ArrayCreate does, including the meta-branding, when create Array exotic objects.

AFAIU, you're asking, "if the implementation, via an extension, provides an exotic object that has the right Array meta-brand but something else is weird like the 'length' property, is that object ontologically an Array exotic object"?

My position is: yes, it is. But if now you introduced observable differences from Array exotic objects created solely within ecma262, that implementation is buggy. An implementation can create objects that are recognized by spec to be Array exotic objects and still be buggy. The "is an Array exotic object" is a bottoming out to determine the next step of execution. We have an operational semantics here: we can't define "is an Array exotic object" in terms of all possible future executions about its behavior.

I do hope that is clear enough. I am unfortunately out of energy discussing this.

This comment has been minimized.

Copy link
@jmdyck

jmdyck Jan 15, 2020

Collaborator

I agree with most of what you're saying, but not this:

But if now you introduced observable differences from Array exotic objects created solely within ecma262, that implementation is buggy.

If the implementation were presenting this example object as the implementation of arrays-as-created-by-ArrayCreate (e.g., the kind of object you get when you call Array()), then yes that would be buggy (nonconformant). But if the implementation isn't claiming that, is instead saying that you get this object by calling (say) Arrayish(), then I don't think it would be buggy. Defining "array exotic object" via a required set of internal methods establishes a gamut of behavior: objects created via the ArrayCreate operation fall within that gamut, and so would objects created via the ArrayishCreate operation -- both objects exhibit all the behavior that is required of array exotic objects. The fact that they're observably different wouldn't imply that one is "buggy".

I am unfortunately out of energy discussing this.

Okay, thanks for the discussion.

<p>The following exotic objects use the ordinary object internal methods except where it is explicitly specified otherwise below:</p>

<emu-clause id="sec-bound-function-exotic-objects">
<h1>Bound Function Exotic Objects</h1>
Expand Down

0 comments on commit 69a884b

Please sign in to comment.