From 0a2d5e179dbf4f48a97871a20b4d13560e09c039 Mon Sep 17 00:00:00 2001 From: ExE Boss <3889017+ExE-Boss@users.noreply.github.com> Date: Wed, 11 Dec 2019 18:30:00 +0100 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20Add=C2=A0`[NonEnumerableMethods]`?= =?UTF-8?q?=20extended=C2=A0attribute?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.bs | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/index.bs b/index.bs index fe1a34d3..7994db8f 100644 --- a/index.bs +++ b/index.bs @@ -9432,6 +9432,80 @@ corresponding to [=interface members=]. +

[LegacyEnumerableMethod]

+ +

+ The [{{LegacyEnumerableMethod}}] [=extended attribute=] is an undesirable feature. + It exists only so that legacy Web platform features can be specified. + It should not be used in specifications + unless required to specify the behavior of legacy APIs, + or for consistency with these APIs. + Editors who wish to use this feature are strongly advised to discuss this + by filing an issue + before proceeding. +

+ +If the [{{LegacyEnumerableMethod}}] +[=extended attribute=] +appears on a [=regular operation|regular=] +or [=static operations|static=] +[=operation=] specified on an interface with [{{NonEnumerableMethods}}], +then it indicates that the ECMAScript property will be enumerable. + +The [{{LegacyEnumerableMethod}}] +extended attribute must +[=takes no arguments|take no arguments=] +and must not appear on methods of an interface +that does not have [{{NonEnumerableMethods}}]. + +
+ + The following [=IDL fragment=] defines an interface with + [{{NonEnumerableMethods}}], which also specifies an instance + and static operation with [{{LegacyEnumerableMethod}}]: + +
+        [Exposed=Window,
+         NonEnumerableMethods]
+        interface HasEnumerableAndNonEnumerableMethods {
+          [LegacyEnumerableMethod]
+          static void staticFoo();
+          static void staticBar();
+          static attribute any staticDataProperty;
+
+          [LegacyEnumerableMethod]
+          void instanceFoo();
+          void instanceBar();
+          attribute any instanceDataProperty;
+        };
+    
+ + An ECMAScript implementation of the above IDL would have the methods + of HasEnumerableAndNonEnumerableMethods + non-enumerable by default, but operations with [{{LegacyEnumerableMethod}}] + would be enumerable. + +
+        for (const key in HasEnumerableAndNonEnumerableMethods) {
+          // logs only "staticFoo" and "staticDataProperty"
+          console.log(key);
+        }
+
+        for (const key in HasEnumerableAndNonEnumerableMethods.prototype) {
+          // logs only "instanceFoo" and "instanceDataProperty"
+          console.log(key);
+        }
+
+        // logs an array containing "staticFoo", "staticBar" and "staticDataProperty"
+        console.log(Object.getOwnPropertyNames(HasEnumerableAndNonEnumerableMethods));
+
+        // logs an array containing "instanceFoo", "instanceBar" and "instanceDataProperty"
+        console.log(Object.getOwnPropertyNames(HasEnumerableAndNonEnumerableMethods.prototype));
+    
+ +
+ +

[LegacyNamespace]

@@ -10026,6 +10100,82 @@ for the specific requirements that the use of +

[NonEnumerableMethods]

+ +If the [{{NonEnumerableMethods}}] [=extended attribute=] +appears on an [=interface=], +it indicates that all methods on that interface +without [{{LegacyEnumerableMethod}}] will be non-enumerable. + +The [{{NonEnumerableMethods}}] +extended attribute must +[=takes no arguments|take no arguments=]. + +Note: Combining the [{{NonEnumerableMethods}}] and [{{LegacyUnenumerableNamedProperties}}] +extended attributes is not forbidden. + +
+ + The following [=IDL fragment=] defines two interfaces, one which + has [{{NonEnumerableMethods}}], and one which doesn’t: + +
+        [Exposed=Window]
+        interface HasEnumerableMethods {
+          static void staticFoo();
+          static attribute any staticDataProperty;
+
+          void instanceFoo();
+          attribute any instanceDataProperty;
+        };
+
+        [Exposed=Window,
+         NonEnumerableMethods]
+        interface NonEnumerableMethods {
+          static void staticBar();
+          static attribute any staticDataProperty;
+
+          void instanceBar();
+          attribute any instanceDataProperty;
+        };
+    
+ + An ECMAScript implementation of the above IDL would have + the methods of HasEnumerableMethods + enumerable, but NonEnumerableMethods + would only have data properties enumerable. + +
+        for (const key in HasEnumerableMethods) {
+          // logs both "staticFoo" and "staticDataProperty"
+          console.log(key);
+        }
+
+        for (const key in HasEnumerableMethods.prototype) {
+          // logs both "instanceFoo" and "instanceDataProperty"
+          console.log(key);
+        }
+
+        for (const key in NonEnumerableMethods) {
+          // logs only "staticDataProperty"
+          console.log(key);
+        }
+
+        for (const key in NonEnumerableMethods.prototype) {
+          // logs only "instanceDataProperty"
+          console.log(key);
+        }
+
+        // logs an array containing "staticBar" and "staticDataProperty"
+        console.log(Object.getOwnPropertyNames(NonEnumerableMethods));
+
+        // logs an array containing "instanceBar" and "instanceDataProperty"
+        console.log(Object.getOwnPropertyNames(NonEnumerableMethods.prototype));
+    
+ +
+ +

[OverrideBuiltins]

From d5ad4b8b82e16290b60a6e2ca6f1cb7dd33d9a76 Mon Sep 17 00:00:00 2001 From: ExE Boss <3889017+ExE-Boss@users.noreply.github.com> Date: Wed, 11 Dec 2019 19:20:00 +0100 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20Define=C2=A0behaviour=20of=C2=A0met?= =?UTF-8?q?hod=20and=C2=A0stringifier=20enumerability?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.bs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/index.bs b/index.bs index 7994db8f..984632ac 100644 --- a/index.bs +++ b/index.bs @@ -10103,8 +10103,8 @@ for the specific requirements that the use of

[NonEnumerableMethods]

If the [{{NonEnumerableMethods}}] [=extended attribute=] -appears on an [=interface=], -it indicates that all methods on that interface +appears on an [=interface=], [=interface mixin=] or [=namespace=], +it indicates that all methods defined on that interface without [{{LegacyEnumerableMethod}}] will be non-enumerable. The [{{NonEnumerableMethods}}] @@ -11907,8 +11907,12 @@ in which case they are exposed on every object that [=implements=] the interface given |op|, |definition|, and |realm|. 1. Let |modifiable| be false if |op| is [=unforgeable=] and true otherwise. + 1. Let |enumerable| be true + 1. If |definition| is declared with [{{NonEnumerableMethods}}] + and |op| is not declared with [{{LegacyEnumerableMethod}}] + set |enumerable| to false 1. Let |desc| be the PropertyDescriptor{\[[Value]]: |method|, - \[[Writable]]: |modifiable|, \[[Enumerable]]: true, + \[[Writable]]: |modifiable|, \[[Enumerable]]: |enumerable|, \[[Configurable]]: |modifiable|}. 1. Let |id| be |op|'s [=identifier=]. 1. Perform [=!=] DefinePropertyOrThrow(|target|, |id|, |desc|). @@ -12145,9 +12149,10 @@ then there must exist a property with the following characteristics: 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| }, + { \[[Writable]]: |B|, \[[Enumerable]]: |E|, \[[Configurable]]: |B| }, where |B| is false if the stringifier is [=unforgeable=] on the interface, - and true otherwise. + and true otherwise, and where |E| is false if the interface + is declared with [{{NonEnumerableMethods}}] and true otherwise. *
The value of the property is a [=built-in function object=], which behaves as follows: From 23ebaa5a99eb1b4c873829959d697fad4c9080dd Mon Sep 17 00:00:00 2001 From: ExE Boss <3889017+ExE-Boss@users.noreply.github.com> Date: Thu, 12 Dec 2019 15:00:00 +0100 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20Define=C2=A0behaviour=20of=C2=A0ite?= =?UTF-8?q?rable=20method=C2=A0enumerability?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.bs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/index.bs b/index.bs index 984632ac..9a3ad7b2 100644 --- a/index.bs +++ b/index.bs @@ -12321,8 +12321,9 @@ If the [=interface=] has any of the following: * a [=setlike declaration=] then a forEach data property must exist with attributes -{ \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true } -and whose value is a [=function object=]. +{ \[[Writable]]: true, \[[Enumerable]]: |E|, \[[Configurable]]: true } +and whose value is a [=function object=], where |E| is false if the interface +is declared with [{{NonEnumerableMethods}}] and true otherwise. The location of the property is determined as follows: @@ -12418,8 +12419,9 @@ property is the String value "forEach". If the [=interface=] has an [=iterable declaration=] or an [=asynchronously iterable declaration=], then an entries data property must exist with attributes -{ \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true } -and whose value is a [=function object=]. +{ \[[Writable]]: true, \[[Enumerable]]: |E|, \[[Configurable]]: true } +and whose value is a [=function object=], where |E| is false if the interface +is declared with [{{NonEnumerableMethods}}] and true otherwise. The location of the property is determined as follows: @@ -12441,8 +12443,9 @@ the value of the {{@@asyncIterator}} property. If the [=interface=] has an [=iterable declaration=] or an [=asynchronously iterable declaration=], then a keys data property must exist with attributes -{ \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true } -and whose value is a [=function object=]. +{ \[[Writable]]: true, \[[Enumerable]]: |E|, \[[Configurable]]: true } +and whose value is a [=function object=], where |E| is false if the interface +is declared with [{{NonEnumerableMethods}}] and true otherwise. The location of the property is determined as follows: @@ -12505,8 +12508,9 @@ The value of the [=function object=]’s name property If the [=interface=] has an [=iterable declaration=] or an [=asynchronously iterable declaration=], then a values data property must exist -with attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true } -and whose value is a [=function object=]. +with attributes { \[[Writable]]: true, \[[Enumerable]]: |E|, \[[Configurable]]: true } +and whose value is a [=function object=], where |E| is false if the interface +is declared with [{{NonEnumerableMethods}}] and true otherwise. The location of the property is determined as follows: