Skip to content
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

update constructor and Symbol.toStringTag properties on Iterator.prototype #3970

Merged
merged 7 commits into from Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 10 additions & 12 deletions test/built-ins/Iterator/prototype/Symbol.toStringTag/prop-desc.js
@@ -1,20 +1,18 @@
// Copyright (C) 2023 Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 25.1.2.1
michaelficarra marked this conversation as resolved.
Show resolved Hide resolved
esid: sec-iteratorprototype-@@tostringtag
description: Property descriptor
info: |
ES6 Section 17

Every other data property described in clauses 18 through 26 and in Annex
B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false,
[[Configurable]]: true } unless otherwise specified.
`Iterator.prototype[@@toStringTag]` is an accessor property with attributes { [[Enumerable]]: *false*, [[Configurable]]: *true* }
features: [iterator-helpers]
includes: [propertyHelper.js]
---*/
verifyProperty(Iterator.prototype, Symbol.toStringTag, {
value: 'Iterator',
writable: true,
enumerable: false,
configurable: true,
});
verifyConfigurable(Iterator.prototype, Symbol.toStringTag);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test and the corresponding one for constructor property are broken. verifyConfigurable() calls isConfigurable() that deletes the property. So, the subsequent parts of this test fail because the property is not there anymore.

If you want to use verifyConfigurable() then it should be the last statement of the test.

verifyNotEnumerable(Iterator.prototype, Symbol.toStringTag);

let desc = Object.getOwnPropertyDescriptor(Iterator.prototype, Symbol.toStringTag);
assert.sameValue(typeof desc.get, 'function');
assert.sameValue(typeof desc.set, 'function');
assert.sameValue(desc.value, undefined);
assert.sameValue(desc.writable, undefined);
ptomato marked this conversation as resolved.
Show resolved Hide resolved
@@ -0,0 +1,57 @@
// Copyright (C) 2023 Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set-iteratorprototype-@@tostringtag
description: weird setter
info: |
The value of the [[Get]] attribute is a built-in function that requires no arguments. It performs the following steps when called:
1. Return *"Iterator"*.

The value of the [[Set]] attribute is a built-in function that takes an argument _v_. It performs the following steps when called:
1. Perform ? SetterThatIgnoresPrototypeProperties(%Iterator.prototype%, %Symbol.toStringTag%, _v_).
2. Return *undefined*.
features: [iterator-helpers]
---*/

let IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))

let sentinel = 'a';

let { get, set } = Object.getOwnPropertyDescriptor(Iterator.prototype, Symbol.toStringTag);

assert.sameValue(Iterator.prototype[Symbol.toStringTag], 'Iterator');
assert.sameValue(get.call(), 'Iterator');

// 1. If _this_ is not an Object, then
// 1. Throw a *TypeError* exception.
assert.throws(() => set.call(undefined, ''));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test and the corresponding one for constructor property are broken. The first argument of assert.throws() should be the expected error (i.e. TypeError in this case).

assert.throws(() => set.call(null, ''));
assert.throws(() => set.call(true, ''));

// 1. If _this_ is _home_, then
// 1. NOTE: Throwing here emulates assignment to a non-writable data property on the _home_ object in strict mode code.
// 1. Throw a *TypeError* exception.
assert.throws(() => set.call(IteratorPrototype, ''));
assert.throws(() => IteratorPrototype[Symbol.toStringTag] = '');

assert.sameValue(Iterator.prototype[Symbol.toStringTag], 'Iterator');
assert.sameValue(get.call(), 'Iterator');

// 1. If _desc_ is *undefined*, then
// 1. Perform ? CreateDataPropertyOrThrow(_this_, _p_, _v_).
let FakeGeneratorPrototype = Object.create(IteratorPrototype);
Object.freeze(IteratorPrototype);
FakeGeneratorPrototype[Symbol.toStringTag] = sentinel;
assert.sameValue(FakeGeneratorPrototype[Symbol.toStringTag], sentinel);

assert.sameValue(Iterator.prototype[Symbol.toStringTag], 'Iterator');
assert.sameValue(get.call(), 'Iterator');

// 1. Else,
// 1. Perform ? Set(_this_, _p_, _v_, *true*).
let o = { [Symbol.toStringTag]: sentinel + 'a' };
set.call(o, sentinel);
assert.sameValue(o[Symbol.toStringTag], sentinel);

assert.sameValue(Iterator.prototype[Symbol.toStringTag], 'Iterator');
assert.sameValue(get.call(), 'Iterator');
18 changes: 18 additions & 0 deletions test/built-ins/Iterator/prototype/constructor/prop-desc.js
@@ -0,0 +1,18 @@
// Copyright (C) 2023 Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-iteratorprototype.constructor
description: Property descriptor
info: |
`Iterator.prototype.constructor` is an accessor property with attributes { [[Enumerable]]: *false*, [[Configurable]]: *true* }
features: [iterator-helpers]
includes: [propertyHelper.js]
---*/
verifyConfigurable(Iterator.prototype, 'constructor');
verifyNotEnumerable(Iterator.prototype, 'constructor');

let desc = Object.getOwnPropertyDescriptor(Iterator.prototype, 'constructor');
assert.sameValue(typeof desc.get, 'function');
assert.sameValue(typeof desc.set, 'function');
assert.sameValue(desc.value, undefined);
assert.sameValue(desc.writable, undefined);
57 changes: 57 additions & 0 deletions test/built-ins/Iterator/prototype/constructor/weird-setter.js
@@ -0,0 +1,57 @@
// Copyright (C) 2023 Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set-iteratorprototype-constructor
description: weird setter
info: |
The value of the [[Get]] attribute is a built-in function that requires no arguments. It performs the following steps when called:
1. Return %Iterator%.

The value of the [[Set]] attribute is a built-in function that takes an argument _v_. It performs the following steps when called:
1. Perform ? SetterThatIgnoresPrototypeProperties(%Iterator.prototype%, *"constructor"*, _v_).
2. Return *undefined*.
features: [iterator-helpers]
---*/

let IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))

let sentinel = {};

let { get, set } = Object.getOwnPropertyDescriptor(Iterator.prototype, 'constructor');

assert.sameValue(Iterator.prototype.constructor, Iterator);
assert.sameValue(get.call(), Iterator);

// 1. If _this_ is not an Object, then
// 1. Throw a *TypeError* exception.
assert.throws(() => set.call(undefined, ''));
assert.throws(() => set.call(null, ''));
assert.throws(() => set.call(true, ''));

// 1. If _this_ is _home_, then
// 1. NOTE: Throwing here emulates assignment to a non-writable data property on the _home_ object in strict mode code.
// 1. Throw a *TypeError* exception.
assert.throws(() => set.call(IteratorPrototype, ''));
assert.throws(() => IteratorPrototype.constructor = '');

assert.sameValue(Iterator.prototype.constructor, Iterator);
assert.sameValue(get.call(), Iterator);

// 1. If _desc_ is *undefined*, then
// 1. Perform ? CreateDataPropertyOrThrow(_this_, _p_, _v_).
let FakeGeneratorPrototype = Object.create(IteratorPrototype);
Object.freeze(IteratorPrototype);
FakeGeneratorPrototype.constructor = sentinel;
assert.sameValue(FakeGeneratorPrototype.constructor, sentinel);

assert.sameValue(Iterator.prototype.constructor, Iterator);
assert.sameValue(get.call(), Iterator);

// 1. Else,
// 1. Perform ? Set(_this_, _p_, _v_, *true*).
let o = { constructor: sentinel + 'a' };
set.call(o, sentinel);
assert.sameValue(o.constructor, sentinel);

assert.sameValue(Iterator.prototype.constructor, Iterator);
assert.sameValue(get.call(), Iterator);