Re: [heycam/webidl] Define "implements" checks using internal slots (#595)

bzbarsky requested changes on this pull request.

This still leaves open questions about how [Constructor] and [NamedConstructor] set the right prototype in subclassing scenarios.  Right now they delegate to the constructor steps, but don't pass through NewTarget or NewTarget.prototype; the constructor steps presumably invoke the new "create an X object" algorithm, but that does not take the proto to use as an argument....

This is not new, so a followup is probably OK here, except we're going from "totally undefined, use your best judgement" to "defined in a way that is wrong"...

> +<div algorithm>
+    An ECMAScript value |value| <dfn id="es-is-platform-object">is a platform object</dfn>
+    if [$Type$](|value|) is Object and if |value| has a \[[PrimaryInterface]] internal slot.
+</div>
+
+<div algorithm>
+    An ECMAScript value |value| <dfn export>implements</dfn> an [=interface=] |interface|
+    if |value| [=is a platform object=] and one of the following is true:
+    <ul>
+        <li>|value|.\[[PrimaryInterface]] is |interface|.</li>
+        <li>The set of [=inherited interfaces=] of |value|.\[[PrimaryInterface]] contains |interface|.</li>
+    </ul>
+</div>
+
+<div class="note">
+    Specifications use various wordings to reference the "[=implements=]" algorithm,

Maybe:

Specifications may reference the concept "|object| implements |interface|" in various ways, including "|object| is an |interface| object".

>  Every [=platform object=] is associated with a global environment, just
 as the [=initial objects=] are.
 It is the responsibility of specifications using Web IDL to state
 which global environment (or, by proxy, which global object) each platform
 object is associated with.
 
+<div algorithm>
+    To <dfn>create an object implementing the interface</dfn> |interface|, with optional
+    intenal slots |slots|, for an interface which is not declared with the
+    [{{Global}}] [=extended attribute=], perform the following steps:
+
+    1. If |slots| is provided, append \[[PrimaryInterface]] to |slots|.
+    1. Otherwise, let |slots| be &laquo; \[[PrimaryInterface]] &raquo;.
+    1. Let |proto| be the [=interface prototype object=] of |interface|.

So this algorithm doesn't do subclassing.  I assume that's because it's meant to be done from specs that really want the default prototype?

Which global's interface prototype object is used here?  Seems like the right global should be input to this algorithm.

>  Every [=platform object=] is associated with a global environment, just
 as the [=initial objects=] are.
 It is the responsibility of specifications using Web IDL to state
 which global environment (or, by proxy, which global object) each platform
 object is associated with.
 
+<div algorithm>
+    To <dfn>create an object implementing the interface</dfn> |interface|, with optional
+    intenal slots |slots|, for an interface which is not declared with the
+    [{{Global}}] [=extended attribute=], perform the following steps:
+
+    1. If |slots| is provided, append \[[PrimaryInterface]] to |slots|.
+    1. Otherwise, let |slots| be &laquo; \[[PrimaryInterface]] &raquo;.
+    1. Let |proto| be the [=interface prototype object=] of |interface|.
+    1. Let |instance| be [$ObjectCreate$](|proto|, |slots|).
+    1. Set |instance|.\[[PrimaryInterface]] to |interface|.
+    1. Let |realm| be the current [=Realm=].

What if there isn't one?  Lots of objects get created when there is no current Realm around.  As a simple example, documents are (and this matters, because they have unforgeable things on them).  Same thing for events, actually.

This really needs to use the Realm of the passed-in global, not the current Realm.

>  Every [=platform object=] is associated with a global environment, just
 as the [=initial objects=] are.
 It is the responsibility of specifications using Web IDL to state
 which global environment (or, by proxy, which global object) each platform
 object is associated with.
 
+<div algorithm>
+    To <dfn>create an object implementing the interface</dfn> |interface|, with optional
+    intenal slots |slots|, for an interface which is not declared with the
+    [{{Global}}] [=extended attribute=], perform the following steps:
+
+    1. If |slots| is provided, append \[[PrimaryInterface]] to |slots|.
+    1. Otherwise, let |slots| be &laquo; \[[PrimaryInterface]] &raquo;.
+    1. Let |proto| be the [=interface prototype object=] of |interface|.
+    1. Let |instance| be [$ObjectCreate$](|proto|, |slots|).

This probably needs to enter the Realm of the passed-in global or something.  At least to the extent that ObjectCreate cares about its Realm.

> +    intenal slots |slots|, for an interface which is not declared with the
+    [{{Global}}] [=extended attribute=], perform the following steps:
+
+    1. If |slots| is provided, append \[[PrimaryInterface]] to |slots|.
+    1. Otherwise, let |slots| be &laquo; \[[PrimaryInterface]] &raquo;.
+    1. Let |proto| be the [=interface prototype object=] of |interface|.
+    1. Let |instance| be [$ObjectCreate$](|proto|, |slots|).
+    1. Set |instance|.\[[PrimaryInterface]] to |interface|.
+    1. Let |realm| be the current [=Realm=].
+    1. [=Define the unforgeable regular operations=] of |interface| on |instance|, given |realm|.
+    1. [=Define the unforgeable regular attributes=] of |interface| on |instance|, given |realm|.
+    1. Return |instance|.
+</div>
+
+<div class="note">
+    Specifications use various wordings to reference the "[=create an object implementing

Specifications may refer to the "[=create an object implementing the interface=]" algorithm in various ways, including "a new |interface| object".

> +    1. [=Define the unforgeable regular attributes=] of |interface| on |instance|, given |realm|.
+    1. Return |instance|.
+</div>
+
+<div class="note">
+    Specifications use various wordings to reference the "[=create an object implementing
+    the interface=]" algorithm, such as "a new |interface| object".
+</div>
+
+<div class="note">
+
+    The set of interfaces that a [=platform object=] [=implements=] does not change over
+    the lifetime of the object.
+
+    Multiple [=interface objects=] associated with different [=Realm/global objects=]
+    will allocate [=platform objects=] which have \[[PrimaryInterface]] internal

Interface objects don't allocate anything, unless there's a [Constructor]....  I think this is really trying to say that platform objects associated with different globals can have the same [[PrimaryInterface]]; this doesn't involve interface objects.

>  The <dfn id="dfn-primary-interface" export>primary interface</dfn> of a platform object
-that implements one or more interfaces is the most-derived [=interface=]
-that it implements.  The value of the \[[Prototype]] [=internal slot=]
+that [=implements=] one or more interfaces is the value of the object's
+\[[PrimaryInterface]] internal slot, which is is the most-derived [=interface=]
+that it [=implements=].  The value of the \[[Prototype]] [=internal slot=]

Except when subclassing is involved.... I'm not sure there's much of a point to this sentence about [[Prototype]] now.  It's neither normative nor very informative.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/heycam/webidl/pull/595#pullrequestreview-183823782

Received on Tuesday, 11 December 2018 18:17:22 UTC