diff --git a/index.bs b/index.bs index c6e4dd42..8655b60a 100644 --- a/index.bs +++ b/index.bs @@ -2279,7 +2279,7 @@ corresponding argument omitted. If the type of an argument is a [=dictionary type=] or a [=union type=] that has a [=dictionary type=] as one of its [=flattened member types=], and that dictionary type and its ancestors have no -[=required dictionary member|required members=], and the argument is either the final argument or is +[=dictionary member/required=] [=dictionary member|members=], and the argument is either the final argument or is followed only by [=optional arguments=], then the argument must be specified as optional and have a default value provided. @@ -3877,8 +3877,8 @@ defined with [=optional arguments=] and merged into one, }; -the [=overload resolution algorithm=] would treat the path argument as [=not -present=] given the same call stroke(undefined), and not throw any exceptions. +the [=overload resolution algorithm=] would treat the path argument as missing +given the same call stroke(undefined), and not throw any exceptions. Note: For this particular example, the latter behavior is actually what Web developers would generally expect. If {{CanvasDrawPath}} were to be designed today, [=optional arguments=] would be @@ -4062,8 +4062,7 @@ determine what Web IDL language feature to use: class="idl">foo(|arg|) operation, with |arg| set to null, while foo() alone would go to the first overload. This can be a surprising behavior for many API users. Instead, specification authors are encouraged to use an [=optional argument=], which would categorize - both foo() and foo(undefined) as "|arg| is [=not - present=]". + both foo() and foo(undefined) as "|arg| is missing".
         interface A {
@@ -4741,9 +4740,15 @@ where [=map/keys=] are strings and [=map/values=] are of a particular type speci
     };
 
-Dictionaries are always passed by value. In language bindings where a dictionary is represented by an object of some kind, passing a -dictionary to a [=platform object=] will not result in a reference to the dictionary being kept by that object. -Similarly, any dictionary returned from a platform object will be a copy and modifications made to it will not be visible to the platform object. +Dictionary instances do not retain a reference to their language-specific representations (e.g., +the corresponding ECMAScript object). So for example, returning a dictionary from an [=operation=] +will result in a new ECMAScript object being created from the current values of the dictionary. And, +an operation that accepts a dictionary as an argument will perform a one-time conversion from the +given ECMAScript value into the dictionary, based on the current properties of the ECMAScript +object. Modifications to the dictionary will not be reflected in the corresponding ECMAScript +object, and vice-versa. + +Dictionaries must not be used as the type of an [=attribute=] or [=constant=]. A dictionary can be defined to inherit from another dictionary. If the identifier of the dictionary is followed by a colon and a [=identifier=], @@ -4772,30 +4777,49 @@ from another dictionary, then the set is empty. Otherwise, the set includes the dictionary |E| that |D| [=interface/inherits=] from and all of |E|’s [=inherited dictionaries=]. -A dictionary value of type |D| can have key–value pairs corresponding -to the dictionary members defined on |D| and on any of |D|’s -[=inherited dictionaries=]. -On a given dictionary value, the presence of each dictionary member -is optional, unless that member is specified as required. -A dictionary member is said to be -present -in a dictionary value if the value [=map/exists|contains an entry with the key=] -given by the member's [=identifier=], otherwise it is [=not present=]. -Dictionary members can also optionally have a default value, which is -the value to use for the dictionary member when passing a value to a -[=platform object=] that does -not have a specified value. Dictionary members with default values are -always considered to be present. +[=Dictionary members=] can be specified as +required, meaning that +converting a language-specific value to a dictionary requires providing a value for that member. Any +dictionary member that is not [=dictionary member/required=] is +optional. + +Note that specifying [=dictionary members=] as [=dictionary member/required=] only has +an observable effect when converting other representations of dictionaries (like an ECMAScript value +supplied as an argument to an [=operation=]) to an IDL dictionary. Specification authors should +leave the members [=dictionary member/optional=] in all other cases, including when a dictionary +type is used solely as the [=return type=] of [=operations=]. + +[=dictionary member/Optional=] [=dictionary members=] can also be specified as having a +default value, +which is the value used by default when author code or specification text does not provide a value +for that member. + +A given dictionary value of type |D| can have [=map/entries=] for each of the dictionary members +defined on |D| and on any of |D|’s [=inherited dictionaries=]. Dictionary members that are specified +as [=dictionary member/required=], or that are specified as having a +[=dictionary member/default value=], will always have such corresponding [=map/entries=]. Other +members' entries might or might not [=map/exist=] in the dictionary value.

- In the ECMAScript binding, a value of undefined is treated as - [=not present=], or will trigger the [=dictionary member/default value=] where applicable. + In the ECMAScript binding, a value of undefined for the property + corresponding to a [=dictionary member=] is treated the same as omitting that property. Thus, it + will cause an error if the member is [=dictionary member/required=], or will trigger the + [=dictionary member/default value=] if one is present, or will result in no [=map/entry=] + existing in the dictionary value otherwise. +

+ +

+ As with [=optional argument/default value|operation argument default values=], it is strongly + encouraged not to use true as the [=dictionary member/default value=] for + {{boolean}}-typed [=dictionary members=], as this can be confusing for authors who might + otherwise expect the default conversion of undefined to be used (i.e., + false).

An [=ordered map=] with string [=map/keys=] can be implicitly treated as a dictionary value of a -specific dictionary |D| if all of its [=map/entries=] correspond to [=dictionary members=], in the -correct order and with the correct types, and with appropriate [=map/entries=] for any required -dictionary members. +specific dictionary |D| if all of its [=map/entries=] correspond to [=dictionary members=], as long +as those entries have the correct types, and there are [=map/entries=] present for any +[=dictionary member/required=] or [=dictionary member/default value|defaulted=] dictionary members.
@@ -4811,16 +4835,6 @@ dictionary members.
     1.  Return «[ "name" → "test", "serviceIdentifiers" → |identifiers| ]».
 
-

- As with [=optional argument/default value|operation argument default values=], - it is strongly suggested not to use true as the - [=dictionary member/default value=] for - {{boolean}}-typed - [=dictionary members=], - as this can be confusing for authors who might otherwise expect the default - conversion of undefined to be used (i.e., false). -

- Each [=dictionary member=] (matching DictionaryMember) is specified as a type (matching Type) followed by an @@ -4876,9 +4890,8 @@ is an [=enumeration=], then its be one of the [=enumeration values|enumeration’s values=]. If the type of the dictionary member is preceded by the -required keyword, the member is considered a -required dictionary member -and must be present on the dictionary. +required keyword, the member is considered a [=dictionary member/required=] +[=dictionary member=].
     dictionary identifier {
@@ -5000,10 +5013,6 @@ The identifier of a dictionary member must not be
 the same as that of another dictionary member defined on the dictionary or
 on that dictionary’s [=inherited dictionaries=].
 
-Dictionaries must not be used as the type of an
-[=attribute=] or
-[=constant=].
-
 No [=extended attributes=] are applicable to dictionaries.
 
 
@@ -7756,9 +7765,7 @@ the object (or its prototype chain) correspond to [=dictionary members=]. running the following algorithm (where |D| is the [=dictionary type=]): 1. If Type(|esDict|) is not Undefined, Null or Object, then [=ECMAScript/throw=] a {{ECMAScript/TypeError}}. - 1. Let |idlDict| be an empty dictionary value of type |D|; - every [=dictionary member=] - is initially considered to be [=not present=]. + 1. Let |idlDict| be an empty [=ordered map=], representing a dictionary of type |D|. 1. Let |dictionaries| be a list consisting of |D| and all of |D|’s [=inherited dictionaries=], in order from least to most derived. 1. For each dictionary |dictionary| in |dictionaries|, in order: @@ -7774,13 +7781,12 @@ the object (or its prototype chain) correspond to [=dictionary members=]. 1. If |esMemberValue| is not undefined, then: 1. Let |idlMemberValue| be the result of [=converted to an IDL value|converting=] |esMemberValue| to an IDL value whose type is the type |member| is declared to be of. - 1. Set the dictionary member on |idlDict| with key name |key| to the value |idlMemberValue|. This dictionary member is considered to be [=present=]. + 1. [=map/Set=] |idlDict|[|key|] to |idlMemberValue|. 1. Otherwise, if |esMemberValue| is undefined but |member| has a [=dictionary member/default value=], then: 1. Let |idlMemberValue| be |member|’s default value. - 1. Set the dictionary member on |idlDict| with key name |key| to the value |idlMemberValue|. This dictionary member is considered to be [=present=]. - 1. Otherwise, if |esMemberValue| is - undefined and |member| is a - [=required dictionary member=], then throw a {{ECMAScript/TypeError}}. + 1. [=map/Set=] |idlDict|[|key|] to |idlMemberValue|. + 1. Otherwise, if |esMemberValue| is undefined and |member| is + [=dictionary member/required=], then throw a {{ECMAScript/TypeError}}. 1. Return |idlDict|. @@ -7799,10 +7805,13 @@ up on the ECMAScript object are not necessarily the same as the object’s prope 1. For each dictionary |dictionary| in |dictionaries|, in order: 1. For each dictionary member |member| declared on |dictionary|, in lexicographical order: 1. Let |key| be the [=identifier=] of |member|. - 1. If the dictionary member named |key| is [=present=] in |V|, then: - 1. Let |idlValue| be the value of |member| on |V|. + 1. If |V|[|key|] [=map/exists=], then: + 1. Let |idlValue| be |V|[|key|]. 1. Let |value| be the result of [=converted to an ECMAScript value|converting=] |idlValue| to an ECMAScript value. 1. Perform [=!=] CreateDataProperty(|O|, |key|, |value|). + +

Recall that if |member| has a [=dictionary member/default value=], + then |key| will always [=map/exist=] in |V|.

1. Return |O|.