Skip to content

Commit

Permalink
Normative: Name getter/setters as kind: "accessor"
Browse files Browse the repository at this point in the history
This doesn't change the expressiveness of decorators, but
it is designed to feel more intuitive when programming.
  • Loading branch information
littledan committed Jan 10, 2019
1 parent 86b7c09 commit 20d4b6d
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 21 deletions.
6 changes: 3 additions & 3 deletions TABLE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
| **parameter descriptor** | **`@decorator`<br/>`class`** | **`@decorator`<br/>`method()`** | **`@decorator`<br/>`field`** | **`@decorator`<br/>`get field()`<br/>`set field()`**|
|----------------------------|------------------------------------------|---------------------------------------------|------------------------------------------------------------------|-----------------------------------------------------|
|`{` | | | | |
|` kind:` |`"class"` |`"method"` |`"field"` |`"method"` <sup>4</sup> |
|` kind:` |`"class"` |`"method"` |`"field"` |`"accessor"` <sup>4</sup> |
|` elements:` |*Array of member descriptors* <sup>1</sup>| - | - | - |
|` key:` | - | *method name* |*property name* |*property name* |
|` placement:` | - |`"prototype" \|\| "static"` |`"own" \|\| "static"` |`"prototype" \|\| "static"` |
Expand All @@ -22,14 +22,14 @@

<sup>3</sup> when `kind` is `field`, don't include the value into the `value` and the value, if it exists, is returned by `initialize` function.

<sup>4</sup> when the decorator is apply over a getter/setter `kind` is `method` and `get` or `set` has value.
<sup>4</sup> when the decorator is apply over a getter/setter `kind` is `accessor` and `get` or `set` has value.

<sup>5</sup> when `get` or `set` has value, the property descriptor doesn't include `writable` value.

| **return descriptor (optional)** | **`class`** | **`method()`** | **`field`** | **`getter/setter`** | **Hooks** |
|----------------------------------|-------------------------------------------|------------------------------------------|-----------------------------------------------------|------------------------------------------|------------------------------------------|
|`{` | | | | | |
|` kind:` |`"class"` |`"method"` |`"field"` |`"method"` |`"hook"` <sup>11</sup> |
|` kind:` |`"class"` |`"method"` |`"field"` |`"accessor"` |`"hook"` <sup>11</sup> |
|` elements:` |*Array of member descriptors* <sup>6</sup> | - | - | - | - |
|` key:` | - | *method name* <sup>8</sup> |*field name* <sup>8</sup> |*field name* <sup>8</sup> | - |
|` placement:` | - |`"prototype" \|\| "static" \|\| "own"` |`"prototype" \|\| "static" \|\| "own"` |`"prototype" \|\| "static" \|\| "own"` |`"prototype" \|\| "static" \|\| "own"` |
Expand Down
8 changes: 4 additions & 4 deletions TAXONOMY.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Decorator reification (from the existing decorator proposal):

```js
{
kind: "method",
kind: "accessor",
key: "foo",
placement: "static",
get: function foo() {},
Expand Down Expand Up @@ -168,7 +168,7 @@ Decorator reification (from the existing decorator proposal):

```js
{
kind: "method",
kind: "accessor",
key: "foo",
placement: "prototype",
get: function foo() {},
Expand Down Expand Up @@ -255,7 +255,7 @@ Decorator reification:

```js
{
kind: "method",
kind: "accessor",
key: decorators.PrivateName("foo"),
placement: "static",
get: function foo() {},
Expand Down Expand Up @@ -338,7 +338,7 @@ Decorator reification:

```js
{
kind: "method",
kind: "accessor",
key: decorators.PrivateName("foo"),
placement: "own",
get: function foo() {},
Expand Down
6 changes: 3 additions & 3 deletions friend.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export function inherit(descriptor) {
let superKey;
let keyString = key.description;
return {
kind: "method",
kind: "accessor",
key,
placement,
get() { return superKey.get(this); },
Expand Down Expand Up @@ -207,7 +207,7 @@ export function abstract(descriptor) {

return {
key,
kind: "method",
kind: "accessor",
placement: "own",
get() {
return internalKey.get(this);
Expand Down Expand Up @@ -249,7 +249,7 @@ export function override(descriptor) {
let internalKey;
let keyString = key.description;
return {
kind: "method",
kind: "accessor",
key,
placement,
// All reads of the method read the underlying shared internal
Expand Down
36 changes: 25 additions & 11 deletions spec.html
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ <h1>The ElementDescriptor Specification Type</h1>
<tr> <th>Field Name</th> <th>Value</th> </tr>
</thead>
<tbody>
<tr> <td>[[Kind]]</td> <td>One of `"method"`, `"field"` or `"hook"`</td> </tr>
<tr> <td>[[Kind]]</td> <td>One of `"method"`, `"accessor"`, `"field"` or `"hook"`</td> </tr>
<tr> <td>[[Key]]</td> <td>A Property Key or %PrivateName% object</td> </tr>
<tr> <td>[[Descriptor]]</td> <td>A Property Descriptor</td> </tr>
<tr> <td>[[Placement]]</td> <td>One of `"static"`, `"prototype"`, or `"own"`</td> </tr>
Expand All @@ -187,7 +187,7 @@ <h1>The ElementDescriptor Specification Type</h1>
<p>
In addition, given an ElementDescriptor _element_, the following conditions are always respected:
<ul>
<li>If _element_.[[Kind]] is `"method"`, then
<li>If _element_.[[Kind]] is `"method"` or `"accessor"`, then
<ul>
<li>_element_.[[Initializer]] is absent.</li>
<li>_element_.[[Start]] is absent.</li>
Expand Down Expand Up @@ -227,6 +227,18 @@ <h1>The ElementDescriptor Specification Type</h1>
<li>_element_.[[Decorators]] is absent.</li>
</ul>
</li>
<li>
If _element_.[[Kind]] is `"method"`, then
<ul>
<li>IsDataDescriptor(_element_.[[Descriptor]]) is *true*.</li>
</ul>
</li>
<li>
If _element_.[[Kind]] is `"accessor"`, then
<ul>
<li>IsAccessorDescriptor(_element_.[[Descriptor]]) is *true*.</li>
</ul>
</li>
</ul>
</p>
</emu-clause>
Expand Down Expand Up @@ -429,7 +441,7 @@ <h1>CoalesceClassElements ( _elements_ )</h1>
1. Assert: _elements_ is a List of ElementDescriptor Records.
1. Let _newElements_ be an empty List.
1. For _element_ in _elements_,
1. If _element_.[[Kind]] is `"method"` and _newElements_ contains a Record _other_ where _other_.[[Kind]] is `"method"`, _other_.[[Key]] is _element_.[[Key]], and _other_.[[Placement]] is _element_.[[Placement]],
1. If _element_.[[Kind]] is `"method"` or `"accessor"`, and _newElements_ contains a Record _other_ where _other_.[[Kind]] is `"method"` or `"accessor"`, _other_.[[Key]] is _element_.[[Key]], and _other_.[[Placement]] is _element_.[[Placement]],
1. If IsDataDescriptor(_element_.[[Descriptor]]) is *true* or IsDataDescriptor(_other_.[[Descriptor]]) is *true*, then
1. Assert: _element_.[[Key]] is not a Private Name.
1. Assert: _element_.[[Descriptor]].[[Configurable]] is *true*, and _other_.[[Descriptor]].[[Configurable]] is *true*.
Expand All @@ -454,7 +466,7 @@ <h1>InitializeInstanceElements ( _O_, _constructor_ )</h1>
1. Assert: Assert _constructor_ is an ECMAScript function object.
1. Let _elements_ be the value of _F_'s [[Elements]] internal slot.
1. For each item _element_ in order from _elements_,
1. If _element_.[[Placement]] is `"own"` and _element_.[[Kind]] is `"method"`,
1. If _element_.[[Placement]] is `"own"` and _element_.[[Kind]] is `"method"` or `"accessor"`,
1. Perform ? DefineClassElement(_O_, _element_).
1. For each item _element_ in order from _elements_,
1. If _element_.[[Placement]] is `"own"` and _element_.[[Kind]] is `"field"`,
Expand All @@ -477,7 +489,7 @@ <h1>InitializeClassElements(_F_, _proto_)</h1>
1. Let _elements_ be the value of _F_'s [[Elements]] internal slot.
1. For each item _element_ in order from _elements_,
1. Assert: If _element_.[[Placement]] is `"prototype"` <del>or `"static"`, and if _element_.[[Kind]] is not `"hook"`</del>, then _element_.[[Key]] is not a Private Name.
1. If _element_.[[Kind]] is `"method"` <ins>and _element_.[[Placement]] is `"static"` or `"prototype"`</ins>,
1. If _element_.[[Kind]] is `"method"` or `"accessor"` <ins>and _element_.[[Placement]] is `"static"` or `"prototype"`</ins>,
1. Let _receiver_ be _F_ if _element_.[[Placement]] is `"static"`, else let _receiver_ be _proto_.
1. Perform ? DefineClassElement(_receiver_, _element_).
1. For each item _element_ in order from _elements_,
Expand Down Expand Up @@ -654,13 +666,13 @@ <h1>CreateIntrinsics ( _realmRec_ )</h1>
<h1>Decorator semantics</h1>
<emu-clause id=sec-decorator-functions>
<h1>Decorator Functions</h1>
<p>A <dfn>decorator function</dfn> is a function that takes and returns either a element descriptor or a class descriptor. The body of a decorator function modifies and returns the descriptor it receives to change the semantics of the decorated entity. Descriptor types can be differentiated by their `kind` property, which is either `"method"`, `"field"` or `"class"`. Descriptors also have a @@toStringTag property which has the value `"Descriptor"`; this property helps differentiate them from other objects.</p>
<p>A <dfn>decorator function</dfn> is a function that takes and returns either a element descriptor or a class descriptor. The body of a decorator function modifies and returns the descriptor it receives to change the semantics of the decorated entity. Descriptor types can be differentiated by their `kind` property, which is either `"method"`, `"accessor"`, `"field"`, or `"class"`. Descriptors also have a @@toStringTag property which has the value `"Descriptor"`; this property helps differentiate them from other objects.</p>
<emu-clause id=sec-decorator-functions-element-descriptor>
<h1>Element Descriptors</h1>
<p>An <dfn>element descriptor</dfn> describes an element of a class or object literal and has the following shape:</p>
<pre><code class=typescript>
interface ElementDescriptor {
kind: "method", "hook", or "field"
kind: "method", "accessor", "hook", or "field"
key: String, Symbol or Private Name,
placement: "static", "prototype", or "own"
...PropertyDescriptor,
Expand Down Expand Up @@ -826,14 +838,14 @@ <h1>FromElementDescriptors ( _elements_ )</h1>
<h1>FromElementDescriptor ( _element_ )</h1>
<emu-alg>
1. Assert: _element_ is an ElementDescriptor Record.
1. If _element_.[[Kind]] is `"method"` or `"field"`,
1. If _element_.[[Kind]] is `"method"`, `"accessor"`, or `"field"`,
1. Let _obj_ be ! FromPropertyDescriptor(_element_.[[Descriptor]])).
1. Otherwise,
1. Let _obj_ be ! ObjectCreate(%ObjectPrototype%).
1. Let _desc_ be PropertyDescriptor{ [[Value]]: `"Descriptor"`, [[Writable]]: *false*, [[Enumerable]]: *false*, [[Configurable]]: *true* }.
1. Perform ! DefinePropertyOrThrow(_obj_, @@toStringTag, _desc_).
1. Perform ! CreateDataPropertyOrThrow(_obj_, `"kind"`, _element_.[[Kind]]).
1. If _element_.[[Kind]] is `"method"` or `"field"`,
1. If _element_.[[Kind]] is `"method"`, `"accessor"`, or `"field"`,
1. Let _key_ be _element_.[[Key]].
1. If _key_ is a Private Name, set _key_ to ? PrivateNameObject(_key_).
1. Perform ! CreateDataPropertyOrThrow(_obj_, `"key"`, _key_).
Expand Down Expand Up @@ -875,7 +887,7 @@ <h1>ToElementDescriptor ( _elementObject_ )</h1>
<emu-alg>
1. Assert: Type(_elementObject_) is Object.
1. Let _kind_ be ? ToString(? Get(_elementObject_, `"kind"`)).
1. If _kind_ is not one of `"hook"`, `"method"`, or `"field"`, throw a *TypeError* exception.
1. If _kind_ is not one of `"hook"`, `"method"`, `"accessor"` or `"field"`, throw a *TypeError* exception.
1. Let _key_ be ? Get(_elementObject_, `"key"`).
1. If _kind_ is `"hook"`,
1. If _key_ is not *undefined*, throw a *TypeError* exception.
Expand All @@ -888,6 +900,8 @@ <h1>ToElementDescriptor ( _elementObject_ )</h1>
1. If _descriptor_ has an [[Enumerable]] field and _descriptor_.[[Enumerable]] is *true*, throw a *TypeError* exception.
1. If _descriptor_ has an [[Configurable]] field and _descriptor_.[[Configurable]] is *true*, throw a *TypeError* exception.
1. If _placement_ is `"prototype"`, throw a *TypeError* exception.
1. If _kind_ is `"accessor"` or `"hook"` and IsDataDescriptor(_descriptor_) is *true*, throw a *TypeError* exception.
1. If _kind_ is `"field"`, `"method"` or `"hook"`, and IsAccessorDescriptor(_descriptor_) is *true*, throw a *TypeError* exception.
1. If _kind_ is `"field"`,
1. If _descriptor_ has a [[Get]], [[Set]] or [[Value]] field, throw a *TypeError* exception.
1. Let _initialize_ be ? Get(_elementObject_, `"initialize"`).
Expand All @@ -912,7 +926,7 @@ <h1>ToElementDescriptor ( _elementObject_ )</h1>
1. Let _elements_ be ? Get(_elementObject_, `"elements"`).
1. If _elements_ is not *undefined*, throw a *TypeError* exception.
1. Let _element_ be the ElementDescriptor { [[Kind]]: _kind_, [[Placement]]: _placement_ }.
1. If _kind_ is `"method"` or `"field",
1. If _kind_ is `"method"`, `"accessor"`, or `"field",
1. Set _element_.[[Key]] to _key_.
1. Set _element_.[[Descriptor]] to _descriptor_.
1. If _kind_ is `"field"`,
Expand Down

0 comments on commit 20d4b6d

Please sign in to comment.