From 4faf8d2c6fc425553828edabfde2e4124a575d18 Mon Sep 17 00:00:00 2001 From: Timothy Gu Date: Sun, 20 Jun 2021 12:17:25 -0700 Subject: [PATCH] Add more static class property ordering tests Since https://github.com/tc39/ecma262/pull/1490, the "length" and "name" properties of a class are defined before any static methods. This is tested by #2057, in test/language/computed-property-names of all places. At the same time, static methods with "name" as the name would overwrite the original property, but retain the original property enumeration order. This was not previously tested. In fact, the overwriting behavior was not tested at all for the "length" property. This commit mends both holes in test coverage. --- .../definition/fn-length-static-precedence.js | 82 +++++++++++++++++++ .../definition/fn-name-static-precedence.js | 37 ++++++--- 2 files changed, 107 insertions(+), 12 deletions(-) create mode 100644 test/language/statements/class/definition/fn-length-static-precedence.js diff --git a/test/language/statements/class/definition/fn-length-static-precedence.js b/test/language/statements/class/definition/fn-length-static-precedence.js new file mode 100644 index 00000000000..1fccc46e0fa --- /dev/null +++ b/test/language/statements/class/definition/fn-length-static-precedence.js @@ -0,0 +1,82 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-runtime-semantics-classdefinitionevaluation +description: > + Function `length` attribute not inferred in presence of static `length` method +info: | + ClassTail : ClassHeritage_opt { ClassBody_opt } + + 14. If constructor is empty, then [...] + b. Let F be ! CreateBuiltinFunction(steps, 0, className, « [[ConstructorKind]], [[SourceText]] », empty, constructorParent). + 15. Else, + a. Let constructorInfo be ! DefineMethod of constructor with arguments proto and constructorParent. + [ This sets the length property on constructorInfo.[[Closure]]. ] + b. Let F be constructorInfo.[[Closure]]. + [...] + 25. For each ClassElement e of elements, do + a. If IsStatic of e is false, then [...] + b. Else, + i. Let field be ClassElementEvaluation of e with arguments F and false. + [ This overwrites the length property on F. ] +includes: [compareArray.js] +features: [generators] +---*/ + +class A { + static method() { + throw new Test262Error('Static method should not be executed during definition'); + } + static length() { + throw new Test262Error('Static method should not be executed during definition'); + } +} + +assert.sameValue(typeof A.length, 'function'); +assert(compareArray(Object.getOwnPropertyNames(A), ['length', 'name', 'prototype', 'method'])) + +var attr = 'length'; +class B { + static [attr]() { + throw new Test262Error( + 'Static method defined via computed property should not be executed ' + + 'during definition' + ); + } +} + +assert.sameValue(typeof B.length, 'function'); +assert(compareArray(Object.getOwnPropertyNames(B), ['length', 'name', 'prototype'])) + +var isDefined = false; +class C { + static get length() { + if (isDefined) { + return 'pass'; + } + throw new Test262Error('Static `get` accessor should not be executed during definition'); + } +} + +isDefined = true; +assert.sameValue(C.length, 'pass'); +assert(compareArray(Object.getOwnPropertyNames(C), ['length', 'name', 'prototype'])) + +class D { + static set length(_) { + throw new Test262Error('Static `set` accessor should not be executed during definition'); + } +} + +assert.sameValue(D.length, undefined); +assert(compareArray(Object.getOwnPropertyNames(D), ['length', 'name', 'prototype'])) + +class E { + static *length() { + throw new Test262Error('Static GeneratorMethod should not be executed during definition'); + } +} + +assert.sameValue(typeof E.length, 'function'); +assert(compareArray(Object.getOwnPropertyNames(E), ['length', 'name', 'prototype'])) diff --git a/test/language/statements/class/definition/fn-name-static-precedence.js b/test/language/statements/class/definition/fn-name-static-precedence.js index 09a97efc5b7..4d62d1e4b62 100644 --- a/test/language/statements/class/definition/fn-name-static-precedence.js +++ b/test/language/statements/class/definition/fn-name-static-precedence.js @@ -2,32 +2,41 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- -es6id: 14.5.15 +esid: sec-runtime-semantics-classdefinitionevaluation description: > Function `name` attribute not inferred in presence of static `name` method info: | - ClassDeclaration : class BindingIdentifier ClassTail + ClassTail : ClassHeritage_opt { ClassBody_opt } - [...] - 4. Let hasNameProperty be HasOwnProperty(value, "name"). - 5. ReturnIfAbrupt(hasNameProperty). - 6. If hasNameProperty is false, then perform SetFunctionName(value, - className). + 14. If constructor is empty, then [...] + b. Let F be ! CreateBuiltinFunction(steps, 0, className, « [[ConstructorKind]], [[SourceText]] », empty, constructorParent). + 15. Else, [...] + d. Perform ! SetFunctionName(F, className). + 25. For each ClassElement e of elements, do + a. If IsStatic of e is false, then [...] + b. Else, + i. Let field be ClassElementEvaluation of e with arguments F and false. + [ This overwrites the name property on F. ] +includes: [compareArray.js] features: [generators] ---*/ class A { + static method() { + throw new Test262Error('Static method should not be executed during definition'); + } static name() { - $ERROR('Static method should not be executed during definition'); + throw new Test262Error('Static method should not be executed during definition'); } } assert.sameValue(typeof A.name, 'function'); +assert(compareArray(Object.getOwnPropertyNames(A), ['length', 'name', 'prototype', 'method'])) var attr = 'name'; class B { static [attr]() { - $ERROR( + throw new Test262Error( 'Static method defined via computed property should not be executed ' + 'during definition' ); @@ -35,6 +44,7 @@ class B { } assert.sameValue(typeof B.name, 'function'); +assert(compareArray(Object.getOwnPropertyNames(B), ['length', 'name', 'prototype'])) var isDefined = false; class C { @@ -42,25 +52,28 @@ class C { if (isDefined) { return 'pass'; } - $ERROR('Static `get` accessor should not be executed during definition'); + throw new Test262Error('Static `get` accessor should not be executed during definition'); } } isDefined = true; assert.sameValue(C.name, 'pass'); +assert(compareArray(Object.getOwnPropertyNames(C), ['length', 'name', 'prototype'])) class D { static set name(_) { - $ERROR('Static `set` accessor should not be executed during definition'); + throw new Test262Error('Static `set` accessor should not be executed during definition'); } } assert.sameValue(D.name, undefined); +assert(compareArray(Object.getOwnPropertyNames(D), ['length', 'name', 'prototype'])) class E { static *name() { - $ERROR('Static GeneratorMethod should not be executed during definition'); + throw new Test262Error('Static GeneratorMethod should not be executed during definition'); } } assert.sameValue(typeof E.name, 'function'); +assert(compareArray(Object.getOwnPropertyNames(E), ['length', 'name', 'prototype']))