Re: [heycam/webidl] Add an algorithm to create a platform object. (#635)

domenic commented on this pull request.



> @@ -12349,12 +12363,54 @@ 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 create a <dfn export>new</dfn> object implementing the interface |interface| in the
+  Realm |realm|, with optional `new.target` value |newTarget|, perform the following steps:

I think we should not allow providing `new.target`. I cannot think of any specs that would use it.

> @@ -12349,12 +12363,60 @@ 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 export lt="new|create|create a new|create an object implementing|create an object
+  implementing the interface">create an object implementing the interface</dfn> |interface| in the
+  Realm |realm|, with optional `new.target` value |newTarget|, perform the following steps:
+
+    1.  Assert: |interface| is [=exposed=] in |realm|.
+    1.  Let prototype be the [=interface prototype object=] for |interface| in
+        |realm|.
+    1.  If |newTarget| is provided, then:
+        1.  Issue: If we just pass {{NewTarget}} through in a constructor, would this not
+            always be defined (sometimes to the [=interface object=] itself)?

If I am understanding @littledan correctly, +1. Inside a constructor "Create a new X" should implicitly grab the NewTarget that exists. Elsewhere, it should just be the X constructor. In neither case should the caller of "new" pass anything.

(In the future I think constructors would be nicer if Web IDL created the object for you, and constructor spec text elsewhere just operated on the created object using a known variable name like `this` or something. But, that's a bigger project, and maybe not worth the churn. For now we have to work with the world where all constructors say "create a new X" as their first step or so.)

>  
     1.  Assert: |interface| is [=exposed=] in |realm|.
+    1.  Let prototype be the [=interface prototype object=] for |interface| in
+        |realm|.
+    1.  If |newTarget| is provided, then:
+        1.  Issue: If we just pass {{NewTarget}} through in a constructor, would this not
+            always be defined (sometimes to the [=interface object=] itself)?
+        1.  Let |newTargetPrototype| be [=?=] [$Get$](|newTarget|, "prototype").

Given the three-way divergence, and the extreme edge-casey nature of this `Reflect.construct` madness, I think it'll be pretty safe to pick one, write tests, and file bugs on everyone else. So I encourage us to pick Gecko. /cc @yuki3 @cdumez in case they want to weigh in, but IMO we shouldn't block.

Note that for custom elements we tried to copy ES more exactly: https://html.spec.whatwg.org/multipage/dom.html#html-element-constructors steps 7 and 8.

> +        1.  If [$Type$](|newTargetPrototype|) is Object, then set |prototype| to
+            |newTargetPrototype|.
+    1.  Let |instance| be a newly created [=ECMAScript/object=] in |realm|.
+    1.  Set |instance|.\[[Prototype]] to |prototype|.
+    1.  Set |instance|'s essential internal methods to the definitions specified in
+        [=ECMA-262 Ordinary object internal methods and internal slots=].
+    1.  Let |interfaces| be the [=inclusive inherited interfaces=] of |interface|.
+    1.  [=list/iterate|For every=] [=interface=] |ancestor interface| in |interfaces|:
+        1.  [=Define the unforgeable regular operations=] of |ancestor interface| on |instance|,
+            given |realm|.
+        1.  [=Define the unforgeable regular attributes=] of |ancestor interface| on |instance|,
+            given |realm|.
+    1.  If |interface| is declared with the [{{Global}}] [=extended attribute=], then:
+        1.  [=Define the regular operations=] of |interface| on |instance|, given |realm|.
+        1.  [=Define the regular attributes=] of |interface| on |instance|, given |realm|.
+        1.  Set |instance|.\[[SetPrototypeOf]] as defined in [[#platform-object-setprototypeof]].

Oh, really sweet to make this imperative; great stuff.

> -as defined in [[#platform-object-setprototypeof]].
-
-Within a [=Realm=] |realm|,
-for each [=interface=] |interface| implemented by a [=platform object=] |obj|,
-the following steps must be run as part of |obj|'s creation:
-
-1.  [=Define the unforgeable regular operations=] of |interface| on |obj|, given |realm|.
-1.  [=Define the unforgeable regular attributes=] of |interface| on |obj|, given |realm|.
-
-If within a [=Realm=] |realm| a [=platform object=] |obj| implements
-an interface |interface| which is declared with the [{{Global}}] [=extended attribute=], then
-the following steps must be run as part of |obj|'s creation:
-
-1.  [=Define the regular operations=] of |interface| on |obj|, given |realm|.
-1.  [=Define the regular attributes=] of |interface| on |obj|, given |realm|.
-
 Additionally, [=platform objects=] which implement an [=interface=]
 which has a [{{Global}}] [=extended attribute=]
 get properties declaratively from:

This can be deleted or rephrased too, I think.

> @@ -12349,12 +12363,60 @@ 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 export lt="new|create|create a new|create an object implementing|create an object
+  implementing the interface">create an object implementing the interface</dfn> |interface| in the
+  Realm |realm|, with optional `new.target` value |newTarget|, perform the following steps:
+
+    1.  Assert: |interface| is [=exposed=] in |realm|.
+    1.  Let prototype be the [=interface prototype object=] for |interface| in
+        |realm|.
+    1.  If |newTarget| is provided, then:
+        1.  Issue: If we just pass {{NewTarget}} through in a constructor, would this not
+            always be defined (sometimes to the [=interface object=] itself)?

I guess we should also make the Realm optional inside constructors; it should always be the current Realm, and asking people to figure that out is a recipe for badness.

> @@ -13327,7 +13363,7 @@ Each {{DOMException}} object has an associated <dfn for="DOMException">name</dfn
 The <dfn constructor for="DOMException"><code>DOMException(|message|, |name|)</code></dfn>
 constructor, when invoked, must run these steps:
 
-1. Let |e| be a new {{DOMException}} object.
+1. Let |e| be a [=new=] {{DOMException}} object in {{NewTarget}}'s Realm, with {{NewTarget}}.

It should be the current Realm, not NewTarget's realm. (But, see my comment above about making it optional.)

-- 
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/635#pullrequestreview-201334319

Received on Thursday, 7 February 2019 21:55:23 UTC