From 98c9ef6645930a5356e279471f1210cc3ecc7252 Mon Sep 17 00:00:00 2001 From: Daniel Ehrenberg Date: Sun, 9 Dec 2018 17:59:11 +0100 Subject: [PATCH 1/6] Define "implements" checks using internal slots - Define an imperative algorithm for instantiating a platform object, which everything theoretically calls into, and which sets the primary interface into a new internal slot [[PrimaryInterface]]. - Define the "implements" algorithm as checking the [[PrimaryInterface]] internal slot. The algorithm here is roughly in correspondence with the V8 implementation, where operation functions are allocated with a reference to a FunctionTemplate object (which is in corresondence with WebIDL interfaces). When checking the receiver of a method that came from WebIDL, the original prototype chain is traversed by looking at the FunctionTemplate's parent. The same FunctionTemplate is used in multiple JavaScript realms. This PR procrastinates on defining an imperative algorithm for [Global] interfaces, which would be a bit more text. It also doesn't define which global object is associated with platform objects, or how this association is represented. Fixes #97 --- index.bs | 197 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 122 insertions(+), 75 deletions(-) diff --git a/index.bs b/index.bs index c714592f..b84aba0a 100644 --- a/index.bs +++ b/index.bs @@ -7427,7 +7427,7 @@ values are represented by ECMAScript Object values (including [=function objects to an IDL [=interface type=] value by running the following algorithm (where |I| is the [=interface=]): 1. If Type(|V|) is not Object, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. - 1. If |V| is a [=platform object=] that implements |I|, then return the IDL [=interface type=] value that represents a reference to that platform object. + 1. If |V| [=implements=] |I|, then return the IDL [=interface type=] value that represents a reference to that platform object. 1. If |V| is a [=user object=] that is considered to implement |I| according to the rules in [[#es-user-objects]], then return the IDL [=interface type=] value that represents a reference to that user object, with the [=incumbent settings object=] as the [=callback context=]. @@ -7442,7 +7442,6 @@ values are represented by ECMAScript Object values (including [=function objects [=interface type=] value represents.

-

Dictionary types

IDL [=dictionary type=] values are represented @@ -7926,9 +7925,9 @@ that correspond to the union’s [=member types=]. 1. If |V| is null or undefined, then: 1. If |types| includes a [=dictionary type=], then return the result of [=converted to an IDL value|converting=] |V| to that dictionary type. - 1. If |V| is a [=platform object=], then: + 1. If |V| [=is a platform object=], then: 1. If |types| includes an [=interface type=] that |V| - implements, then return the IDL value that is a reference to the object |V|. + [=implements=], then return the IDL value that is a reference to the object |V|. 1. If |types| includes {{object}}, then return the IDL value that is a reference to the object |V|. 1. If |V| is a {{DOMException}} platform object, then: @@ -8352,7 +8351,7 @@ extended attribute must either The bare form, [Constructor], has the same meaning as using an empty argument list, [Constructor()]. For each [{{Constructor}}] extended attribute -on the interface, there will be a way to construct an object that implements +on the interface, there will be a way to construct an object that [=implements=] the interface by passing the specified arguments. The prose definition of a constructor must @@ -8397,7 +8396,7 @@ for an interface is to be implemented. An ECMAScript implementation supporting these interfaces would have a \[[Construct]] property on the Circle interface object which would - return a new object that implements the interface. It would take + return a new object that [=implements=] the interface. It would take either zero or one argument. The NodeList interface object would not have a \[[Construct]] property. @@ -9212,7 +9211,7 @@ If the [{{LenientThis}}] appears on a [=regular attribute=], it indicates that invocations of the attribute’s getter or setter with a this value that is not an -object that implements the [=interface=] +object that [=implements=] the [=interface=] on which the attribute appears will be ignored. The [{{LenientThis}}] extended attribute @@ -9307,7 +9306,7 @@ has the same meaning as using an empty argument list, [NamedConstructor=identifier()]. For each [{{NamedConstructor}}] extended attribute on the interface, there will be a way to construct an object that -implements the interface by passing the specified arguments to the [=constructor=] +[=implements=] the interface by passing the specified arguments to the [=constructor=] that is the value of the aforementioned property. The [=NamedConstructor identifier|identifier=] used for the named constructor must not @@ -10244,7 +10243,7 @@ If the [{{Unscopable}}] [=extended attribute=] appears on a [=regular attribute=] or [=regular operation=], it -indicates that an object that implements an interface with the given +indicates that an object that [=implements=] an interface with the given interface member will not include its property name in any object environment record with it as its base object. The result of this is that bare identifiers matching the property name will not resolve to @@ -10372,9 +10371,9 @@ Note: The HTML Standard defines how a security check is performed. [[!HTML]] then remove from |S| all other entries. - 1. Otherwise: if |V| is a [=platform object=], and + 1. Otherwise: if |V| [=is a platform object=], and there is an entry in |S| that has one of the following types at position |i| of its type list, - * an [=interface type=] that |V| implements + * an [=interface type=] that |V| [=implements=] * {{object}} * a [=nullable type|nullable=] version of any of the above types * an [=annotated type=] whose [=annotated types/inner type=] is one of the above types @@ -10660,7 +10659,7 @@ as described in sections [[#es-constants]] and [[#es-operations]]. If the [=interface=] is declared with a [{{Constructor}}] [=extended attribute=], then the [=interface object=] can be called as a [=constructor=] -to create an object that implements that interface. +to create an object that [=implements=] that interface. Calling that interface as a function will throw an exception. [=Interface objects=] whose [=interfaces=] are not declared @@ -10702,7 +10701,7 @@ the typeof operator will return "function" when applied to an inter Rethrow any exceptions. 1. Let |O| be the result of [=converted to an ECMAScript value|converting=] |R| to an ECMAScript [=interface type=] value |I|. - 1. Assert: |O| is an object that implements |I|. + 1. Assert: |O| is an object that [=implements=] |I|. 1. Assert: |O|.\[[Realm]] is equal to |realm|. 1. Return |O|. 1. Let |constructorProto| be |realm|.\[[Intrinsics]].[[{{%FunctionPrototype%}}]]. @@ -10738,7 +10737,7 @@ implement the interface on which the [{{NamedConstructor}}] extended attributes appear. If the actions listed in the description of the constructor return normally, -then those steps must return an object that implements interface |I|. +then those steps must return an object that [=implements=] interface |I|. This object's relevant [=Realm=] must be the same as that of the [=named constructor=].
@@ -10955,7 +10954,7 @@ is the concatenation of the [=interface=]’s is called with property key |P|, the following steps are taken: 1. Let |A| be the [=interface=] for the [=named properties object=] |O|. - 1. Let |object| be the sole object from |O|’s ECMAScript global environment that implements |A|. + 1. Let |object| be the sole object from |O|’s ECMAScript global environment that [=implements=] |A|. Note: For example, if the [=interface=] is the {{Window}} interface, then the sole object will be this global environment’s window object. @@ -10972,7 +10971,7 @@ is the concatenation of the [=interface=]’s 1. Let |desc| be a newly created [=Property Descriptor=] with no fields. 1. Set |desc|.\[[Value]] to the result of [=converted to an ECMAScript value|converting=] |value| to an ECMAScript value. - 1. If |A| implements an interface with the + 1. If |A| [=implements=] an interface with the [{{LegacyUnenumerableNamedProperties}}] [=extended attribute=], then set |desc|.\[[Enumerable]] to false, @@ -11036,7 +11035,7 @@ is the concatenation of the [=interface=]’s [=Constants=] are exposed on [=interface objects=], [=legacy callback interface objects=], [=interface prototype objects=], and -on the single object that implements the interface, +on the single object that [=implements=] the interface, when an interface is declared with the [{{Global}}] [=extended attribute=].
@@ -11061,7 +11060,7 @@ when an interface is declared with the [{{Global}}] [=extended attribute=]. [=Regular attributes=] are exposed on the [=interface prototype object=], unless the attribute is [=unforgeable=] or if the interface was declared with the [{{Global}}] [=extended attribute=], -in which case they are exposed on every object that implements the interface. +in which case they are exposed on every object that [=implements=] the interface.
To define the regular attributes of [=interface=] or [=namespace=] |definition| on |target|, @@ -11126,9 +11125,9 @@ in which case they are exposed on every object that implements the interface. specified.) 1. Otherwise, set |O| to the this value. - 1. If |O| is a [=platform object=], then [=perform a security check=], passing |O|, + 1. If |O| [=is a platform object=], then [=perform a security check=], passing |O|, |attribute|'s [=identifier=], and "getter". - 1. If |O| is not a [=platform object=] that implements the interface |target|, + 1. If |O| is not a [=platform object=] that [=implements=] the interface |target|, then: 1. If |attribute| was specified with the [{{LenientThis}}] [=extended attribute=], then return undefined. @@ -11174,9 +11173,9 @@ in which case they are exposed on every object that implements the interface. specified.) 1. Otherwise, set |O| to the this value. - 1. If |O| is a [=platform object=], then [=perform a security check=], passing |O|, + 1. If |O| [=is a platform object=], then [=perform a security check=], passing |O|, |id|, and "setter". - 1. Let |validThis| be true if |O| is a [=platform object=] that implements the + 1. Let |validThis| be true if |O| [=implements=] the interface |target|, or false otherwise. 1. If |validThis| is false and |attribute| was not specified with the [{{LenientThis}}] [=extended attribute=], then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. @@ -11243,7 +11242,7 @@ there exist a corresponding property. [=Regular operations=] are exposed on the [=interface prototype object=], unless the operation is [=unforgeable=] or the interface was declared with the [{{Global}}] [=extended attribute=], -in which case they are exposed on every object that implements the interface. +in which case they are exposed on every object that [=implements=] the interface.
To define the regular operations of [=interface=] or [=namespace=] |definition| on |target|, given [=Realm=] |realm|, @@ -11303,9 +11302,9 @@ in which case they are exposed on every object that implements the interface. object does not implement |target|.) 1. Otherwise, set |O| to the this value. - 1. If |O| is a [=platform object=], then [=perform a security check=], passing |O|, + 1. If |O| [=is a platform object=], then [=perform a security check=], passing |O|, |id|, and "method". - 1. If |O| is not a [=platform object=] that implements the interface |target|, + 1. If |O| is not a [=platform object=] that [=implements=] the interface |target|, [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. 1. Let |n| be the [=list/size=] of |args|. 1. Let |S| be the [=effective overload set=] for [=regular operations=] (if |op| is a @@ -11509,7 +11508,7 @@ then there must exist a property with the following characteristics: * The name of the property is "toString". * If the [=stringifier=] is [=unforgeable=] on the interface or if the interface was declared with the [{{Global}}] [=extended attribute=], - then the property exists on every object that implements the interface. + then the property exists on every object that [=implements=] the interface. Otherwise, the property exists on the [=interface prototype object=]. * The property has attributes { \[[Writable]]: |B|, \[[Enumerable]]: true, \[[Configurable]]: |B| }, @@ -11520,12 +11519,12 @@ then there must exist a property with the following characteristics: The value of the property is a [=built-in function object=], which behaves as follows: 1. Let |O| be the result of calling ToObject on the this value. - 1. If |O| is a [=platform object=], + 1. If |O| [=is a platform object=], then [=perform a security check=], passing: * the platform object |O|, * the [=identifier=] of the [=stringifier=], and * the type "method". - 1. If |O| is not an object that implements the [=interface=] + 1. If |O| is not an object that [=implements=] the [=interface=] on which the stringifier was declared, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. 1. Let |V| be an uninitialized variable. 1. Depending on where stringifier was specified: @@ -11572,7 +11571,7 @@ and whose value is a [=function object=]. The location of the property is determined as follows: * If the interface was declared with the [{{Global}}] [=extended attribute=], - then the property exists on the single object that implements the interface. + then the property exists on the single object that [=implements=] the interface. * Otherwise, the property exists solely on the interface’s [=interface prototype object=]. If the interface defines an [=indexed property getter=], @@ -11584,14 +11583,14 @@ then the [=function object=] is {{%ArrayProto_values%}}. when invoked, must behave as follows: 1. Let |object| be the result of calling ToObject on the this value. - 1. If |object| is a [=platform object=], + 1. If |object| [=is a platform object=], then [=perform a security check=], passing: * the platform object |object|, * the identifier "@@iterator", and * the type "method". 1. Let |interface| be the [=interface=] the [=iterable declaration=] is on. - 1. If |object| is not a [=platform object=] that implements |interface|, + 1. If |object| is not a [=platform object=] that [=implements=] |interface|, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. 1. Let |iterator| be a newly created [=default iterator object=] for |interface| with |object| as its target and iterator kind "key+value". @@ -11605,13 +11604,13 @@ then the [=function object=] is {{%ArrayProto_values%}}. when invoked, must behave as follows: 1. Let |object| be the result of calling ToObject on the this value. - 1. If |object| is a [=platform object=], + 1. If |object| [=is a platform object=], then [=perform a security check=], passing: * the platform object |object|, * the identifier "@@iterator", and * the type "method". 1. If |object| is not a [=platform object=] - that implements the [=interface=] + that [=implements=] the [=interface=] on which the [=maplike declaration=] or [=setlike declaration=] is defined, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. @@ -11648,7 +11647,7 @@ and whose value is a [=function object=]. The location of the property is determined as follows: * If the interface was declared with the [{{Global}}] [=extended attribute=], - then the property exists on the single object that implements the interface. + then the property exists on the single object that [=implements=] the interface. * Otherwise, the property exists solely on the interface’s [=interface prototype object=]. If the interface defines an [=indexed property getter=], @@ -11692,7 +11691,7 @@ then the [=function object=] is {{%ArrayProto_forEach%}}. the method, when invoked, must behave as follows: 1. Let |object| be the result of calling ToObject on the this value. - 1. If |object| is a [=platform object=], + 1. If |object| [=is a platform object=], then [=perform a security check=], passing: * the platform object |object|, * the identifier "forEach", and @@ -11701,7 +11700,7 @@ then the [=function object=] is {{%ArrayProto_forEach%}}. on which the [=maplike declaration=] or [=setlike declaration=] is declared. 1. If |object| is not a [=platform object=] - that implements |interface|, + that [=implements=] |interface|, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. 1. Let |callbackFn| be the value of the first argument passed to the function, or undefined if the argument was not supplied. 1. If IsCallable(|callbackFn|) is false, [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. @@ -11748,7 +11747,7 @@ and whose value is a [=function object=]. The location of the property is determined as follows: * If the interface was declared with the [{{Global}}] [=extended attribute=], - then the property exists on the single object that implements the interface. + then the property exists on the single object that [=implements=] the interface. * Otherwise, the property exists solely on the interface’s [=interface prototype object=]. If the interface has a [=value iterator=], @@ -11769,7 +11768,7 @@ and whose value is a [=function object=]. The location of the property is determined as follows: * If the interface was declared with the [{{Global}}] [=extended attribute=], - then the property exists on the single object that implements the interface. + then the property exists on the single object that [=implements=] the interface. * Otherwise, the property exists solely on the interface’s [=interface prototype object=]. If the interface has a [=value iterator=], @@ -11781,7 +11780,7 @@ then the [=function object=] is {{%ArrayProto_keys%}}. then the method, when invoked, must behave as follows: 1. Let |object| be the result of calling ToObject on the this value. - 1. If |object| is a [=platform object=], + 1. If |object| [=is a platform object=], then [=perform a security check=], passing: * the platform object |object|, * the identifier "keys", and @@ -11789,7 +11788,7 @@ then the [=function object=] is {{%ArrayProto_keys%}}. 1. Let |interface| be the [=interface=] on which the [=iterable declaration=] is declared on. 1. If |object| is not a [=platform object=] - that implements |interface|, + that [=implements=] |interface|, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. 1. Let |iterator| be a newly created [=default iterator object=] for |interface| with |object| as its target and iterator kind "key". @@ -11812,7 +11811,7 @@ and whose value is a [=function object=]. The location of the property is determined as follows: * If the interface was declared with the [{{Global}}] [=extended attribute=], - then the property exists on the single object that implements the interface. + then the property exists on the single object that [=implements=] the interface. * Otherwise, the property exists solely on the interface’s [=interface prototype object=]. If the interface has a [=value iterator=], @@ -11825,7 +11824,7 @@ the value of the {{@@iterator}} property. then the method, when invoked, must behave as follows: 1. Let |object| be the result of calling ToObject on the this value. - 1. If |object| is a [=platform object=], + 1. If |object| [=is a platform object=], then [=perform a security check=], passing: * the platform object |object|, * the identifier "entries", and @@ -11833,7 +11832,7 @@ the value of the {{@@iterator}} property. 1. Let |interface| be the [=interface=] on which the [=iterable declaration=] is declared on. 1. If |object| is not a [=platform object=] - that implements |interface|, + that [=implements=] |interface|, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. 1. Let |iterator| be a newly created [=default iterator object=] for |interface| with |object| as its target and iterator kind "value". @@ -11896,7 +11895,7 @@ must be {{%IteratorPrototype%}}. 1. Let |interface| be the [=interface=] for which the [=iterator prototype object=] exists. 1. Let |object| be the result of calling ToObject on the this value. - 1. If |object| is a [=platform object=], + 1. If |object| [=is a platform object=], then [=perform a security check=], passing: * the platform object |object|, * the identifier "next", and @@ -11941,7 +11940,7 @@ and the string " Iterator".

Maplike declarations

-Any object that implements an [=interface=] +Any object that [=implements=] an [=interface=] that has a [=maplike declaration=] must have a \[[BackingMap]] [=internal slot=], which is initially set to a newly created {{ECMAScript/Map}} object. @@ -11963,12 +11962,12 @@ These additional properties are described in the sub-sections below. 1. Let |O| be the this value. 1. Let |arguments| be the list of arguments passed to this function. 1. Let |name| be the function name. - 1. If |O| is a [=platform object=], + 1. If |O| [=is a platform object=], then [=perform a security check=], passing: * the platform object |O|, * an identifier equal to |name|, and * the type "method". - 1. If |O| is not an object that implements A, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. + 1. If |O| is not an object that [=implements=] A, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. 1. Let |map| be the {{ECMAScript/Map}} object that is the value of |O|’s \[[BackingMap]] [=internal slot=]. 1. Let |function| be [=?=] GetMethod(|map|, |name|). 1. If |function| is undefined, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. @@ -11992,12 +11991,12 @@ with the following characteristics: whose behavior when invoked is as follows: 1. Let |O| be the this value. - 1. If |O| is a [=platform object=], + 1. If |O| [=is a platform object=], then [=perform a security check=], passing: * the platform object |O|, * the identifier "size", and * the type "getter". - 1. If |O| is not an object that implements A, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. + 1. If |O| is not an object that [=implements=] A, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. 1. Let |map| be the {{ECMAScript/Map}} object that is the value of |O|’s \[[BackingMap]] [=internal slot=]. 1. Return Get(|map|, "size").
@@ -12044,12 +12043,12 @@ For both of get and has, there 1. Let |O| be the this value. 1. Let |name| be the name of the property – "get" or "has". - 1. If |O| is a [=platform object=], + 1. If |O| [=is a platform object=], then [=perform a security check=], passing: * the platform object |O|, * an identifier equal to |name|, and * the type "method". - 1. If |O| is not an object that implements A, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. + 1. If |O| is not an object that [=implements=] A, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. 1. Let |map| be the {{ECMAScript/Map}} object that is the value of |O|’s \[[BackingMap]] [=internal slot=]. 1. Let |keyType| be the key type specified in the [=maplike declaration=]. 1. Let |function| be [=!=] Get(|map|, |name|). @@ -12096,12 +12095,12 @@ must exist on |A|’s The value of the property is a [=built-in function object=] that behaves as follows when invoked: 1. Let |O| be the this value. - 1. If |O| is a [=platform object=], + 1. If |O| [=is a platform object=], then [=perform a security check=], passing: * the platform object |O|, * the identifier "delete", and * the type "method". - 1. If |O| is not an object that implements A, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. + 1. If |O| is not an object that [=implements=] A, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. 1. Let |map| be the {{ECMAScript/Map}} object that is the value of |O|’s \[[BackingMap]] [=internal slot=]. 1. Let |keyType| be the key type specified in the [=maplike declaration=]. 1. Let |function| be [=!=] Get(|map|, "delete"). @@ -12130,12 +12129,12 @@ must exist on |A|’s [=interface prototype object=]: The value of the property is a [=built-in function object=] that behaves as follows when invoked: 1. Let |O| be the this value. - 1. If |O| is a [=platform object=], + 1. If |O| [=is a platform object=], then [=perform a security check=], passing: * the platform object |O|, * the identifier "set", and * the type "method". - 1. If |O| is not an object that implements A, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. + 1. If |O| is not an object that [=implements=] A, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. 1. Let |map| be the {{ECMAScript/Map}} object that is the value of |O|’s \[[BackingMap]] [=internal slot=]. 1. Let |keyType| and |valueType| be the key and value types specified in the [=maplike declaration=]. 1. Let |function| be [=!=] Get(|map|, "set"). @@ -12156,7 +12155,7 @@ The value of the [=function object=]’s name property

Setlike declarations

-Any object that implements an [=interface=] +Any object that [=implements=] an [=interface=] that has a [=setlike declaration=] must have a \[[BackingSet]] [=internal slot=], which is initially set to a newly created {{ECMAScript/Set}} object. @@ -12177,12 +12176,12 @@ These additional properties are described in the sub-sections below. 1. Let |O| be the this value. 1. Let |arguments| be the list of arguments passed to this function. 1. Let |name| be the function name. - 1. If |O| is a [=platform object=], + 1. If |O| [=is a platform object=], then [=perform a security check=], passing: * the platform object |O|, * an identifier equal to |name|, and * the type "method". - 1. If |O| is not an object that implements A, + 1. If |O| is not an object that [=implements=] A, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. 1. Let |set| be the {{ECMAScript/Set}} object that is the value of |O|’s \[[BackingSet]] [=internal slot=]. @@ -12207,12 +12206,12 @@ with the following characteristics: whose behavior when invoked is as follows: 1. Let |O| be the this value. - 1. If |O| is a [=platform object=], + 1. If |O| [=is a platform object=], then [=perform a security check=], passing: * the platform object |O|, * the identifier "size", and * the type "getter". - 1. If |O| is not an object that implements A, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. + 1. If |O| is not an object that [=implements=] A, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. 1. Let |set| be the {{ECMAScript/Set}} object that is the value of |O|’s \[[BackingSet]] [=internal slot=]. 1. Return the result of calling the \[[Get]] internal method of |set| passing "size" and |set| as arguments.
@@ -12259,12 +12258,12 @@ with the following characteristics: The value of the property is a [=built-in function object=] that behaves as follows when invoked: 1. Let |O| be the this value. - 1. If |O| is a [=platform object=], + 1. If |O| [=is a platform object=], then [=perform a security check=], passing: * the platform object |O|, * the identifier "has", and * the type "method". - 1. If |O| is not an object that implements A, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. + 1. If |O| is not an object that [=implements=] A, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. 1. Let |set| be the {{ECMAScript/Set}} object that is the value of |O|’s \[[BackingSet]] [=internal slot=]. 1. Let |type| be the value type specified in the [=setlike declaration=]. 1. Let |function| be [=!=] Get(|set|, "has"). @@ -12296,12 +12295,12 @@ must exist on |A|’s [=interface prototype object=]: 1. Let |O| be the this value. 1. Let |name| be the name of the property – "add" or "delete". - 1. If |O| is a [=platform object=], + 1. If |O| [=is a platform object=], then [=perform a security check=], passing: * the platform object |O|, * an identifier equal to |name|, and * the type "method". - 1. If |O| is not an object that implements A, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. + 1. If |O| is not an object that [=implements=] A, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. 1. Let |set| be the {{ECMAScript/Set}} object that is the value of |O|’s \[[BackingSet]] [=internal slot=]. 1. Let |type| be the value type specified in the [=setlike declaration=]. 1. Let |function| be [=!=] Get(|set|, |name|). @@ -12337,18 +12336,73 @@ The value of the [=function object=]’s name property

Platform objects implementing interfaces

+
+ An ECMAScript value |value| is a platform object + if [$Type$](|value|) is Object and if |value| has a \[[PrimaryInterface]] internal slot. +
+ +
+ An ECMAScript value |value| implements an [=interface=] |interface| + if |value| [=is a platform object=] and one of the following is true: +
    +
  • |value|.\[[PrimaryInterface]] is |interface|.
  • +
  • The set of [=inherited interfaces=] of |value|.\[[PrimaryInterface]] contains |interface|.
  • +
+ +
+ 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. +
+ To create an object implementing the interface |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 « \[[PrimaryInterface]] ». + 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|. +
+ +
+ Specifications use various wordings to reference the "[=create an object implementing + the interface=]" algorithm, such as "a new |interface| object". +
+ +
+ + 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 + slots referencing the same underlying [=interface=]. For example, a page may + contain a same-origin iframe, with the iframe's method being called on the + main page's element of the same kind, with no exception thrown. + + [=Interface mixins=] do not participate directly in the evaluation of the [=implements=] + algorithm. Instead, each [=interface=] that the [=interface mixin=] is [=included=] in + has its own "copy" of each [=member=] of the [=interface mixin=], and the corresponding + [=creating an operation function|operation function=] checks that the receiver [=implements=] + the particular [=interface=] which [=includes=] the [=interface mixin=]. + +
+ The primary interface 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=] of the platform object is the [=interface prototype object=] -of the [=primary interface=] -from the [=platform object=]’s associated global environment. +of the [=primary interface=] from the [=platform object=]’s associated global environment. The global environment that a given [=platform object=] is associated with can change after it has been created. When @@ -12367,13 +12421,6 @@ of the platform object. [=Platform objects=] have an internal \[[SetPrototypeOf]] method 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 which is declared with the [{{Global}}] [=extended attribute=], then for each [=interface=] |interface| implemented by |obj|, From cc74839e576cf0e7c2fa8dd33ace7e6b0a0cda50 Mon Sep 17 00:00:00 2001 From: Daniel Ehrenberg Date: Mon, 10 Dec 2018 13:23:09 +0100 Subject: [PATCH 2/6] Editorial: Clarify other wordings to reference "implements" --- index.bs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/index.bs b/index.bs index b84aba0a..3086f349 100644 --- a/index.bs +++ b/index.bs @@ -12348,7 +12348,11 @@ The value of the [=function object=]’s name property
  • |value|.\[[PrimaryInterface]] is |interface|.
  • The set of [=inherited interfaces=] of |value|.\[[PrimaryInterface]] contains |interface|.
  • +
    +
    + Specifications use various wordings to reference the "[=implements=]" algorithm, + such as "|object| is an |interface| object", to mean, "|object| implements |interface|".
    Every [=platform object=] is associated with a global environment, just From 43fd98ac9ebc41226c7f1bb4b89826fa1cea86e1 Mon Sep 17 00:00:00 2001 From: Daniel Ehrenberg Date: Wed, 12 Dec 2018 17:38:15 +0100 Subject: [PATCH 3/6] Clarify the prototype of constructed objects - The new.target value is used when available (verified in Chromium that usage of new.target is implemented). - When new.target is not available, the relevant Realm of the this value is used. It's not clear how the this value should be passed in; this patch uses some sloppy wording there. --- index.bs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/index.bs b/index.bs index 3086f349..6ce56771 100644 --- a/index.bs +++ b/index.bs @@ -141,6 +141,7 @@ urlPrefix: https://tc39.github.io/ecma262/; spec: ECMA-262 text: OrdinaryGetOwnProperty; url: sec-ordinarygetownproperty text: OrdinaryPreventExtensions; url: sec-ordinarypreventextensions text: OrdinarySetWithOwnDescriptor; url: sec-ordinarysetwithowndescriptor + text: OrdinaryCreateFromConstructor; url: sec-ordinarycreatefromconstructor text: Set; url: sec-set-o-p-v-throw text: SetFunctionLength; url: sec-setfunctionlength text: SetFunctionName; url: sec-setfunctionname @@ -12363,13 +12364,16 @@ object is associated with.
    To create an object implementing the interface |interface|, with optional - intenal slots |slots|, for an interface which is not declared with the - [{{Global}}] [=extended attribute=], perform the following steps: + intenal slots |slots| and |new.target| value |newTarget|, 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 « \[[PrimaryInterface]] ». - 1. Let |proto| be the [=interface prototype object=] of |interface|. - 1. Let |instance| be [$ObjectCreate$](|proto|, |slots|). + 1. If |NewTarget| is provided, let |instance| be ? [$OrdinaryCreateFromConstructor$](|newTarget|, "%ObjectPrototype%") + 1. Otherwise, + 1. Let |realm| be the [=relevant Realm=] of the |this| value that led to the execution of this algorithm. + 1. Let |proto| be the [=interface prototype object=] of |interface| in |realm|. + 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|. @@ -12377,6 +12381,9 @@ object is associated with. 1. Return |instance|.
    +Issue: The relevant |this| value is not always well-defined; see +#135 for discussion. +
    Specifications use various wordings to reference the "[=create an object implementing the interface=]" algorithm, such as "a new |interface| object". From dceb2672c735000a36b6d14b66eb421c13bad723 Mon Sep 17 00:00:00 2001 From: Daniel Ehrenberg Date: Wed, 12 Dec 2018 17:55:11 +0100 Subject: [PATCH 4/6] Editorial: Remove/clean up some informative text --- index.bs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/index.bs b/index.bs index 6ce56771..93cef809 100644 --- a/index.bs +++ b/index.bs @@ -12352,8 +12352,8 @@ The value of the [=function object=]’s name property
    - Specifications use various wordings to reference the "[=implements=]" algorithm, - such as "|object| is an |interface| object", to mean, "|object| implements |interface|". + 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 @@ -12385,8 +12385,8 @@ Issue: The relevant |this| value is not always well-defined; see #135 for discussion.
    - Specifications use various wordings to reference the "[=create an object implementing - the interface=]" algorithm, such as "a new |interface| object". + Specifications may refer to the "[=create an object implementing the + interface=]" algorithm in various ways, including "a new |interface| object".
    @@ -12394,11 +12394,11 @@ Issue: The relevant |this| value is not always well-defined; see 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 - slots referencing the same underlying [=interface=]. For example, a page may - contain a same-origin iframe, with the iframe's method being called on the - main page's element of the same kind, with no exception thrown. + Multiple [=platform objects=] with different [=Realm/global objects=] will share + a reference to the same [=interface=] in their \[[PrimaryInterface]] internal + slots. For example, a page may contain a same-origin iframe, with the iframe's + method being called on the main page's element of the same kind, with no exception + thrown. [=Interface mixins=] do not participate directly in the evaluation of the [=implements=] algorithm. Instead, each [=interface=] that the [=interface mixin=] is [=included=] in @@ -12411,9 +12411,7 @@ Issue: The relevant |this| value is not always well-defined; see The primary interface of a platform object 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=] -of the platform object is the [=interface prototype object=] -of the [=primary interface=] from the [=platform object=]’s associated global environment. +that it [=implements=]. The global environment that a given [=platform object=] is associated with can change after it has been created. When From 8e57f765b3ad0964952e66d7a0a2b5f927877d18 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Fri, 21 Dec 2018 22:59:08 +0100 Subject: [PATCH 5/6] Clean up create definition Co-Authored-By: littledan --- index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.bs b/index.bs index 93cef809..c78a76b3 100644 --- a/index.bs +++ b/index.bs @@ -12363,7 +12363,7 @@ which global environment (or, by proxy, which global object) each platform object is associated with.
    - To create an object implementing the interface |interface|, with optional + To create an object implementing the interface |interface|, with optional intenal slots |slots| and |new.target| value |newTarget|, for an interface which is not declared with the [{{Global}}] [=extended attribute=], perform the following steps: From 15f81cdae774a832c0c3170f522c01abd0722bee Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Fri, 21 Dec 2018 23:02:24 +0100 Subject: [PATCH 6/6] Update index.bs Co-Authored-By: littledan --- index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.bs b/index.bs index c78a76b3..a3f655ca 100644 --- a/index.bs +++ b/index.bs @@ -12364,7 +12364,7 @@ object is associated with.
    To create an object implementing the interface |interface|, with optional - intenal slots |slots| and |new.target| value |newTarget|, for an interface which is not + internal slots |slots| and `new.target` value |newTarget|, 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|.