-
Notifications
You must be signed in to change notification settings - Fork 157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Specify open dictionaries. #180
Changes from all commits
2e084f4
2008d7f
2b5f2a8
3dc8ca9
1a8ae76
05252bf
747ba1e
6646a17
7c5c25a
756f55d
399fc10
59c34ac
06ca8e2
84d1bc3
0386c5d
fc878b0
fe44f9c
665d408
9e22b41
20c46cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -106,6 +106,8 @@ urlPrefix: https://tc39.github.io/ecma262/; spec: ECMA-262 | |
text: Set; url: sec-set-o-p-v-throw | ||
text: IsConstructor; url: sec-isconstructor | ||
text: Construct; url: sec-construct | ||
text: own property; url: sec-own-property | ||
text: enumerable; url: sec-property-attributes | ||
text: DefinePropertyOrThrow; url: sec-definepropertyorthrow | ||
url: sec-code-realms | ||
text: Realm | ||
|
@@ -120,6 +122,7 @@ urlPrefix: https://tc39.github.io/ecma262/; spec: ECMA-262 | |
text: ECMA-262 section 9.1.8; url: sec-ordinary-object-internal-methods-and-internal-slots-get-p-receiver | ||
text: ECMA-262 section 19.2.2.3; url: sec-function-@@create | ||
text: ECMA-262 section 19.2.3.8; url: sec-function.prototype-@@hasinstance | ||
text: List; url: sec-list-and-record-specification-type | ||
text: Array methods; url: sec-properties-of-the-array-prototype-object | ||
text: typed arrays; url: sec-typedarray-objects | ||
text: GetMethod; url: sec-getmethod | ||
|
@@ -1358,8 +1361,10 @@ The type of the attribute, after resolving typedefs, must not be a | |
|
||
* a [=sequence type=] | ||
* a [=dictionary type=] | ||
* a [=record type=] | ||
* a [=union type=] | ||
that has a nullable or non-nullable sequence type or dictionary | ||
that has a nullable or non-nullable sequence type, dictionary, | ||
or record | ||
as one of its [=flattened member types=] | ||
|
||
The attribute is <dfn id="dfn-read-only" export>read only</dfn> if the | ||
|
@@ -1750,15 +1755,15 @@ corresponding argument omitted. | |
conversion of <emu-val>undefined</emu-val> to be used (i.e., <emu-val>false</emu-val>). | ||
</p> | ||
|
||
If the type of an argument is a [=dictionary type=] | ||
If the type of an argument is a [=dictionary type=] or [=record type=] | ||
or a [=union type=] that has a | ||
dictionary type as one of its [=flattened member types=], | ||
dictionary or record 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 followed only by | ||
[=optional arguments=], then | ||
the argument must be specified as optional. | ||
Such arguments are always considered to have a | ||
[=optional argument/default value=] of an empty dictionary, | ||
[=optional argument/default value=] of an empty dictionary or record, as appropriate, | ||
unless otherwise specified. | ||
|
||
<div class="note"> | ||
|
@@ -3249,7 +3254,6 @@ extended attribute’s [=takes a named argument list|named argument list=]. | |
|
||
Two types are <dfn id="dfn-distinguishable" export>distinguishable</dfn> if | ||
at most one of the two [=includes a nullable type=] | ||
or is a [=dictionary type=], | ||
and at least one of the following three conditions is true: | ||
|
||
1. The two types (taking their [=inner types=] | ||
|
@@ -3280,7 +3284,7 @@ and at least one of the following three conditions is true: | |
<span>callback function</span> | ||
</div></th> | ||
<th><div> | ||
<span>dictionary</span> | ||
<span>dictionary/record</span> | ||
</div></th> | ||
<th><div> | ||
<span>sequence<|T|></span> | ||
|
@@ -3389,7 +3393,7 @@ and at least one of the following three conditions is true: | |
<td>●</td> | ||
</tr> | ||
<tr> | ||
<th>dictionary</th> | ||
<th>dictionary/record</th> | ||
<td class="belowdiagonal"></td> | ||
<td class="belowdiagonal"></td> | ||
<td class="belowdiagonal"></td> | ||
|
@@ -5160,9 +5164,7 @@ type. | |
NonAnyType : | ||
PrimitiveType Null | ||
PromiseType Null | ||
"ByteString" Null | ||
"DOMString" Null | ||
"USVString" Null | ||
StringType Null | ||
identifier Null | ||
"sequence" "<" Type ">" Null | ||
"object" Null | ||
|
@@ -5171,6 +5173,7 @@ type. | |
"DOMException" Null | ||
BufferRelatedType Null | ||
"FrozenArray" "<" Type ">" Null | ||
RecordType Null | ||
</pre> | ||
|
||
<div data-fill-with="grammar-ConstType"></div> | ||
|
@@ -5214,11 +5217,23 @@ type. | |
ε | ||
</pre> | ||
|
||
<pre class="grammar" id="prod-StringType"> | ||
StringType : | ||
"ByteString" | ||
"DOMString" | ||
"USVString" | ||
</pre> | ||
|
||
<pre class="grammar" id="prod-PromiseType"> | ||
PromiseType : | ||
"Promise" "<" ReturnType ">" | ||
</pre> | ||
|
||
<pre class="grammar" id="prod-RecordType"> | ||
RecordType : | ||
"record" "<" StringType "," Type ">" | ||
</pre> | ||
|
||
<pre class="grammar" id="prod-Null"> | ||
Null : | ||
"?" | ||
|
@@ -5664,10 +5679,11 @@ character after an existing type. The inner type must not | |
be {{any}}, | ||
another nullable type, or a [=union type=] | ||
that itself has [=includes a nullable type=] | ||
or has a dictionary type as one of its | ||
or has a dictionary or record type as one of its | ||
[=flattened member types=]. | ||
|
||
Note: Although dictionary types can in general be nullable, they cannot when used | ||
Note: Although dictionary and record types can in general be nullable, | ||
they cannot when used | ||
as the type of an operation argument or a dictionary member. | ||
|
||
Nullable type constant values in IDL are represented in the same way that | ||
|
@@ -5737,6 +5753,36 @@ is the concatenation of the type name for |T| and | |
the string “Sequence”. | ||
|
||
|
||
<h4 id="idl-record" dictionary lt="record">Record types — record<|K|, |V|></h4> | ||
|
||
A <dfn export>record type</dfn> is a parameterized type | ||
whose values are ordered associative arrays mapping instances of |K| to | ||
instances of |V|. The (key, value) pairs are called | ||
<dfn for="record">mappings</dfn>. | ||
The order of a record's mappings is determined when the record value is created. | ||
In a specification, a record's value can be written: | ||
<blockquote> | ||
« (key1, value1), (key2, value2), … » | ||
</blockquote> | ||
|
||
However, there is no way to represent a constant record value in IDL. | ||
|
||
|K| must be one of {{DOMString}}, {{USVString}}, or {{ByteString}}. | ||
|
||
Records are always passed by value. In language bindings where a record | ||
is represented by an object of some kind, passing a record | ||
to a [=platform object=] will not result in a reference to the record | ||
being kept by that object. Similarly, any record returned from a | ||
platform object will be a copy and modifications made to it will not be visible | ||
to the platform object. | ||
|
||
Records must not be used as the type of an [=attribute=] or | ||
[=constant=]. | ||
|
||
The [=type name=] of a record type is the concatenation of the type | ||
name for |K|, the type name for |V| and the string “Record”. | ||
|
||
|
||
<h4 oldids="dom-promise" id="idl-promise" interface lt="Promise|Promise<T>">Promise types — Promise<|T|></h4> | ||
|
||
A <dfn id="dfn-promise-type" export>promise type</dfn> is a parameterized type | ||
|
@@ -5833,7 +5879,7 @@ be used as a [=member types|union member type=]. | |
The [=number of nullable member types=] | ||
of a [=union type=] must | ||
be 0 or 1, and if it is 1 then the union type must also not have | ||
a [=dictionary type=] in its | ||
a [=dictionary type=] or [=record type=] in its | ||
[=flattened member types=]. | ||
|
||
A type <dfn id="dfn-includes-a-nullable-type" export>includes a nullable type</dfn> if: | ||
|
@@ -7529,6 +7575,101 @@ iterable |iterable| and an iterator getter | |
</div> | ||
|
||
|
||
<h4 id="es-record">Records — record<|K|, |V|></h4> | ||
|
||
IDL {{record}}<|K|, |V|> values are represented by | ||
ECMAScript <emu-val>Object</emu-val> values. | ||
|
||
<p id="es-to-record"> | ||
An ECMAScript value |O| is [=converted to an IDL value|converted=] to an IDL <code>{{record}}<|K|, |V|></code> value as follows: | ||
</p> | ||
|
||
<ol class="algorithm"> | ||
1. Let |result| be a new empty instance of <code>{{record}}<|K|, |V|></code>. | ||
1. If [=Type=](|O|) is Undefined or Null, | ||
return |result|. | ||
1. If [=Type=](|O|) is not Object, | ||
<a lt="es throw">throw a <emu-val>TypeError</emu-val></a>. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This check should not be there, for consistency with closed dictionaries. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, closed dictionaries do throw a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As above, my bad; disregard this. |
||
1. Let |keys| be [=?=] |O|.\[[OwnPropertyKeys]](). | ||
1. Repeat, for each element |key| of |keys| in [=List=] order: | ||
1. Let |desc| be [=?=] |O|.\[[GetOwnProperty]](|key|). | ||
1. If |desc| is not <emu-val>undefined</emu-val> | ||
and |desc|.\[[Enumerable]] is <emu-val>true</emu-val>: | ||
1. Let |typedKey| be |key| [=converted to an IDL value=] of type |K|. | ||
1. Let |value| be [=?=] [=Get=](|O|, |key|). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @domenic Done. Note that it's a little weird to call |
||
1. Let |typedValue| be |value| [=converted to an IDL value=] of type |V|. | ||
1. If |typedKey| is already a key in |result|, set its value to |typedValue|. | ||
|
||
Note: This can happen when |O| is a proxy object. | ||
1. Otherwise, append to |result| a [=record/mapping=] (|typedKey|, |typedValue|). | ||
1. Return |result|. | ||
</ol> | ||
|
||
<p id="record-to-es"> | ||
An IDL <code>{{record}}<…></code> value |D| is [=converted to an | ||
ECMAScript value|converted=] to an ECMAScript value as follows: | ||
</p> | ||
|
||
<ol class="algorithm"> | ||
1. Let |result| be [=!=] [=ObjectCreate=]([=%ObjectPrototype%=]). | ||
1. Repeat, for each [=record/mapping=] (|key|, |value|) in |D|: | ||
1. Let |esKey| be |key| [=converted to an ECMAScript value=]. | ||
1. Let |esValue| be |value| [=converted to an ECMAScript value=]. | ||
1. Let |created| be [=!=] [=CreateDataProperty=](|result|, |esKey|, |esValue|). | ||
1. Assert: |created| is <emu-val>true</emu-val>. | ||
1. Return |result|. | ||
</ol> | ||
|
||
<div class="example" id="example-es-record"> | ||
Passing the ECMAScript value <code>{b: 3, a: 4}</code> as a | ||
<code>{{record}}<DOMString, double></code> argument | ||
would result in the IDL value « ("b", 3), ("a", 4) ». | ||
|
||
Records only consider [=own property|own=] [=enumerable=] | ||
properties, so given an IDL operation | ||
<code>record<DOMString, double> | ||
identity(record<DOMString, double> arg)</code> which returns its | ||
argument, the following code passes its assertions: | ||
|
||
<pre highlight="js"> | ||
let proto = {a: 3, b: 4}; | ||
let obj = {__proto__: proto, d: 5, c: 6} | ||
Object.defineProperty(obj, "e", {value: 7, enumerable: false}); | ||
let result = identity(obj); | ||
console.assert(result.a === undefined); | ||
console.assert(result.b === undefined); | ||
console.assert(result.e === undefined); | ||
let entries = Object.entries(result); | ||
console.assert(entries[0][0] === "d"); | ||
console.assert(entries[0][1] === 5); | ||
console.assert(entries[1][0] === "c"); | ||
console.assert(entries[1][1] === 6); | ||
</pre> | ||
|
||
Record keys and values can be constrained, although keys can only be | ||
constrained among the three string types. | ||
The following conversions have the described results: | ||
<table class="data"> | ||
<thead><th>Value</th><th>Passed to type</th><th>Result</th></thead> | ||
<tr> | ||
<td><code>{"😞": 1}</code></td> | ||
<td><code>{{record}}<ByteString, double></code></td> | ||
<td><emu-val>TypeError</emu-val></td> | ||
</tr> | ||
<tr> | ||
<td><code>{"\uD83D": 1}</code></td> | ||
<td><code>{{record}}<USVString, double></code></td> | ||
<td>« ("\uFFFD", 1) »</td> | ||
</tr> | ||
<tr> | ||
<td><code>{"\uD83D": {hello: "world"}}</code></td> | ||
<td><code>{{record}}<DOMString, double></code></td> | ||
<td>« ("\uD83D", 0) »</td> | ||
</tr> | ||
</table> | ||
</div> | ||
|
||
|
||
<h4 id="es-promise">Promise types — Promise<|T|></h4> | ||
|
||
IDL [=promise type=] values are | ||
|
@@ -7695,6 +7836,9 @@ represented by ECMAScript values that correspond to the union’s | |
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 |types| includes a [=record type=], then return the | ||
result of [=converted to an IDL value|converting=] | ||
|V| to that record type. | ||
1. If |types| includes a [=callback interface=] | ||
type, then return the result of | ||
[=converted to an IDL value|converting=] | ||
|
@@ -9843,6 +9987,7 @@ and a list of IDL values or the special value “missing”. The algorithm beha | |
and there is an entry in |S| that has one of the following types at position |i| of its type list, | ||
* a [=nullable type=] | ||
* a [=dictionary type=] | ||
* a [=record type=] | ||
* a [=union type=] that | ||
[=includes a nullable type=] or that | ||
has a [=dictionary type=] in its [=flattened member types|flattened members=] | ||
|
@@ -9955,6 +10100,7 @@ and a list of IDL values or the special value “missing”. The algorithm beha | |
there is an entry in |S| that has one of the following types at position |i| of its type list, | ||
* a [=callback interface=] type | ||
* a [=dictionary type=] | ||
* a [=record type=] | ||
* {{object}} | ||
* a [=nullable type|nullable=] version of any of the above types | ||
* a [=union type=] or [=nullable type|nullable=] union type | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should throw a TypeError for consistency with closed dictionaries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was in response to @bzbarsky's «Do we want to allow passing null or undefined to mean "empty open dictionary" the way we do for dictionaries?», and he's right that closed dictionaries treat null and undefined as empty.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uh, what are you reading? Can you quote? I see there a very clear step 1 that says "If Type(V) is not Undefined, Null or Object, then throw a TypeError."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, wow, I totally misread the sentence that I quoted. Sorry. This seems good then.