-
Notifications
You must be signed in to change notification settings - Fork 548
tests for Iterator.prototype.join #4768
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
base: main
Are you sure you want to change the base?
Changes from all commits
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 |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| // Copyright (C) 2025 Kevin Gibbons. All rights reserved. | ||
| // This code is governed by the BSD license found in the LICENSE file. | ||
|
|
||
| /*--- | ||
| esid: sec-iterator.prototype.join | ||
| description: Iterator.prototype.join closes its receiver if coercing a value from the iterator throws. | ||
| features: [Iterator.prototype.join] | ||
| ---*/ | ||
|
|
||
| var throwy = { | ||
| toString: function () { | ||
| throw new Test262Error(); | ||
| }, | ||
| }; | ||
|
|
||
| var calledNextCount = 0; | ||
| var calledReturn = false; | ||
| var it = { | ||
| next: function () { | ||
| ++calledNextCount; | ||
| if (calledNextCount > 1) { | ||
| return { done: true, value: undefined }; | ||
| } | ||
| return { done: false, value: throwy }; | ||
| }, | ||
| return: function () { | ||
| calledReturn = true; | ||
| }, | ||
| }; | ||
|
|
||
| assert.throws(Test262Error, function () { | ||
| Iterator.prototype.join.call(it); | ||
| }); | ||
|
|
||
| assert.sameValue(calledNextCount, 1); | ||
| assert(calledReturn); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| // Copyright (C) 2025 Kevin Gibbons. All rights reserved. | ||
| // This code is governed by the BSD license found in the LICENSE file. | ||
|
|
||
| /*--- | ||
| esid: sec-iterator.prototype.join | ||
| description: Iterator.prototype.join closes its receiver if coercing the separator throws. | ||
| features: [Iterator.prototype.join] | ||
| ---*/ | ||
|
|
||
| var throwy = { | ||
| toString: function () { | ||
| throw new Test262Error(); | ||
| }, | ||
| }; | ||
|
|
||
| var gotNext = false; | ||
| var calledReturn = false; | ||
| var it = { | ||
| get next() { | ||
| // we use a variable instead of simply throwing because throwing is expected in this test | ||
| gotNext = true; | ||
| }, | ||
| return: function () { | ||
| calledReturn = true; | ||
| }, | ||
| }; | ||
|
|
||
| assert.throws(Test262Error, function () { | ||
| Iterator.prototype.join.call(it, throwy); | ||
| }); | ||
|
|
||
| assert.sameValue(gotNext, false); | ||
| assert(calledReturn); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| // Copyright (C) 2025 Kevin Gibbons. All rights reserved. | ||
| // This code is governed by the BSD license found in the LICENSE file. | ||
|
|
||
| /*--- | ||
| esid: sec-iterator.prototype.join | ||
| description: Iterator.prototype.join formats nullish iterator contents as an empty string. | ||
| features: [Iterator.prototype.join] | ||
| ---*/ | ||
|
|
||
| assert.sameValue( | ||
| ['one', null, 'two', undefined, 'three'].values().join(), | ||
|
Contributor
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. optional: Might be good to test a nullish value as the last value of the iterator, as well. |
||
| 'one,,two,,three' | ||
| ); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| // Copyright (C) 2025 Kevin Gibbons. All rights reserved. | ||
| // This code is governed by the BSD license found in the LICENSE file. | ||
|
|
||
| /*--- | ||
| esid: sec-iterator.prototype.join | ||
| description: Iterator.prototype.join coerces non-nullish iterator contents to string. | ||
| features: [Iterator.prototype.join] | ||
| ---*/ | ||
|
|
||
| var called = false; | ||
| var coercible = { | ||
| toString: function () { | ||
| if (called) { | ||
| throw new Test262Error('toString should be called exactly once'); | ||
|
Member
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. To assert exactly-once behaviour, I would just use a counter and assert on the counter at the end.
Member
Author
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. That is also a valid way to do it but I'm happy with this as-is. |
||
| } | ||
| called = true; | ||
| return 'value'; | ||
| }, | ||
| }; | ||
|
|
||
| assert.sameValue([coercible, 0, true].values().join(), 'value,0,true'); | ||
| assert(called); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| // Copyright (C) 2025 Kevin Gibbons. All rights reserved. | ||
| // This code is governed by the BSD license found in the LICENSE file. | ||
|
|
||
| /*--- | ||
| esid: sec-iterator.prototype.join | ||
| description: Iterator.prototype.join has default data property attributes. | ||
| includes: [propertyHelper.js] | ||
| features: [Iterator.prototype.join] | ||
| ---*/ | ||
|
|
||
| verifyProperty(Iterator.prototype, 'join', { | ||
| enumerable: false, | ||
| writable: true, | ||
| configurable: true | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // Copyright (C) 2025 Kevin Gibbons. All rights reserved. | ||
| // This code is governed by the BSD license found in the LICENSE file. | ||
|
|
||
| /*--- | ||
| esid: sec-iterator.prototype.join | ||
| description: Iterator.prototype.join does not close its receiver if the iterator itself throws. | ||
| features: [Iterator.prototype.join] | ||
| ---*/ | ||
|
|
||
| var gotReturn = false; | ||
| var it = { | ||
| next: function () { | ||
| throw new Test262Error(); | ||
| }, | ||
| get return() { | ||
| gotReturn = true; | ||
| }, | ||
| }; | ||
|
|
||
| assert.throws(Test262Error, function () { | ||
| Iterator.prototype.join.call(it); | ||
| }); | ||
|
|
||
| assert.sameValue(gotReturn, false); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| // Copyright (C) 2025 Kevin Gibbons. All rights reserved. | ||
| // This code is governed by the BSD license found in the LICENSE file. | ||
|
|
||
| /*--- | ||
| esid: sec-iterator.prototype.join | ||
| description: Iterator.prototype.join does not close its receiver if the iterator is exhausted. | ||
| features: [Iterator.prototype.join] | ||
| ---*/ | ||
|
|
||
| var calledNextCount = 0; | ||
| var gotReturn = false; | ||
| var it = { | ||
| next: function () { | ||
| ++calledNextCount; | ||
| if (calledNextCount > 2) { | ||
| return { done: true, value: undefined }; | ||
| } | ||
| return { done: false, value: 'ES' }; | ||
| }, | ||
| get return() { | ||
| gotReturn = true; | ||
| }, | ||
| }; | ||
|
|
||
| assert.sameValue(Iterator.prototype.join.call(it), 'ES,ES'); | ||
|
|
||
| assert.sameValue(calledNextCount, 3); | ||
|
|
||
| assert.sameValue(gotReturn, false); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // Copyright (C) 2025 Kevin Gibbons. All rights reserved. | ||
| // This code is governed by the BSD license found in the LICENSE file. | ||
|
|
||
| /*--- | ||
| esid: sec-iterator.prototype.join | ||
| description: Iterator.prototype.join does not close its receiver if the iterator itself throws. | ||
|
Contributor
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. Description is for another file |
||
| features: [Iterator.prototype.join] | ||
| ---*/ | ||
|
|
||
| var gotReturn = false; | ||
| var it = { | ||
| next: function () { | ||
| return null; | ||
| }, | ||
| get return() { | ||
| gotReturn = true; | ||
| }, | ||
| }; | ||
|
|
||
| assert.throws(TypeError, function () { | ||
| Iterator.prototype.join.call(it); | ||
| }); | ||
|
|
||
| assert.sameValue(gotReturn, false); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| // Copyright (C) 2025 Kevin Gibbons. All rights reserved. | ||
| // This code is governed by the BSD license found in the LICENSE file. | ||
|
|
||
| /*--- | ||
| esid: sec-iterator.prototype.join | ||
| description: Iterator.prototype.join.length is 1. | ||
| includes: [propertyHelper.js] | ||
| features: [Iterator.prototype.join] | ||
| ---*/ | ||
|
|
||
| verifyProperty(Iterator.prototype.join, 'length', { | ||
| value: 1, | ||
| enumerable: false, | ||
| writable: false, | ||
| configurable: true | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| // Copyright (C) 2025 Kevin Gibbons. All rights reserved. | ||
| // This code is governed by the BSD license found in the LICENSE file. | ||
|
|
||
| /*--- | ||
| esid: sec-iterator.prototype.join | ||
| description: Iterator.prototype.join.name is "join". | ||
| includes: [propertyHelper.js] | ||
| features: [Iterator.prototype.join] | ||
| ---*/ | ||
|
|
||
| verifyProperty(Iterator.prototype.join, 'name', { | ||
| value: 'join', | ||
| enumerable: false, | ||
| writable: false, | ||
| configurable: true | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| // Copyright (C) 2025 Kevin Gibbons. All rights reserved. | ||
| // This code is governed by the BSD license found in the LICENSE file. | ||
|
|
||
| /*--- | ||
| esid: sec-iterator.prototype.join | ||
| description: Iterator.prototype.join is not a constructor | ||
| includes: [isConstructor.js] | ||
| features: [Iterator.prototype.join, Reflect.construct] | ||
| ---*/ | ||
|
|
||
| assert(!isConstructor(Iterator.prototype.join), "Iterator.prototype.join should not be a constructor"); | ||
|
|
||
| assert.throws(TypeError, function() { | ||
| var iterator = [].values(); | ||
| new iterator.join(); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| // Copyright (C) 2025 Kevin Gibbons. All rights reserved. | ||
| // This code is governed by the BSD license found in the LICENSE file. | ||
|
|
||
| /*--- | ||
| esid: sec-iterator.prototype.join | ||
| description: Iterator.prototype.join throws if the receiver is not an object. | ||
| features: [Iterator.prototype.join] | ||
| ---*/ | ||
|
|
||
| var it = [].values(); | ||
|
|
||
| assert.throws(TypeError, function () { | ||
| it.join.call(undefined); | ||
| }); | ||
|
|
||
| assert.throws(TypeError, function () { | ||
| it.join.call(null); | ||
| }); | ||
|
|
||
| assert.throws(TypeError, function () { | ||
| it.join.call(false); | ||
| }); | ||
|
|
||
| assert.throws(TypeError, function () { | ||
| it.join.call(0); | ||
| }); | ||
|
|
||
| assert.throws(TypeError, function () { | ||
| it.join.call(0n); | ||
| }); | ||
|
|
||
| assert.throws(TypeError, function () { | ||
| it.join.call(""); | ||
| }); | ||
|
|
||
| assert.throws(TypeError, function () { | ||
| it.join.call(Symbol()); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| // Copyright (C) 2025 Kevin Gibbons. All rights reserved. | ||
| // This code is governed by the BSD license found in the LICENSE file. | ||
|
|
||
| /*--- | ||
| esid: sec-iterator.prototype.join | ||
| description: Iterator.prototype.join allows empty string as separator. | ||
| features: [Iterator.prototype.join] | ||
| ---*/ | ||
|
|
||
| assert.sameValue([].values().join(''), ''); | ||
|
|
||
| assert.sameValue(['one'].values().join(''), 'one'); | ||
|
|
||
| assert.sameValue(['one', 'two'].values().join(''), 'onetwo'); | ||
|
|
||
| assert.sameValue(['one', 'two', 'three'].values().join(''), 'onetwothree'); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| // Copyright (C) 2025 Kevin Gibbons. All rights reserved. | ||
| // This code is governed by the BSD license found in the LICENSE file. | ||
|
|
||
| /*--- | ||
| esid: sec-iterator.prototype.join | ||
| description: Iterator.prototype.join joins using a comma if no separator is passed. | ||
| features: [Iterator.prototype.join] | ||
| ---*/ | ||
|
|
||
| assert.sameValue([].values().join(), ''); | ||
|
|
||
| assert.sameValue(['one'].values().join(), 'one'); | ||
|
|
||
| assert.sameValue(['one', 'two'].values().join(), 'one,two'); | ||
|
|
||
| assert.sameValue(['one', 'two', 'three'].values().join(), 'one,two,three'); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| // Copyright (C) 2025 Kevin Gibbons. All rights reserved. | ||
| // This code is governed by the BSD license found in the LICENSE file. | ||
|
|
||
| /*--- | ||
| esid: sec-iterator.prototype.join | ||
| description: Iterator.prototype.join joins using the passed separator. | ||
| features: [Iterator.prototype.join] | ||
| ---*/ | ||
|
|
||
| assert.sameValue([].values().join('&&'), ''); | ||
|
|
||
| assert.sameValue(['one'].values().join('&&'), 'one'); | ||
|
|
||
| assert.sameValue(['one', 'two'].values().join('&&'), 'one&&two'); | ||
|
|
||
| assert.sameValue(['one', 'two', 'three'].values().join('&&'), 'one&&two&&three'); |
|
bakkot marked this conversation as resolved.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| // Copyright (C) 2025 Kevin Gibbons. All rights reserved. | ||
| // This code is governed by the BSD license found in the LICENSE file. | ||
|
|
||
| /*--- | ||
| esid: sec-iterator.prototype.join | ||
| description: Iterator.prototype.join coerces the passed separator to a string. | ||
| features: [Iterator.prototype.join] | ||
| ---*/ | ||
|
|
||
| var called = false; | ||
| var coercible = { | ||
| toString: function () { | ||
| if (called) { | ||
| throw new Test262Error('toString should be called exactly once'); | ||
| } | ||
| called = true; | ||
| return '&&'; | ||
| }, | ||
| }; | ||
|
|
||
| assert.sameValue(['one', 'two', 'three'].values().join(coercible), 'one&&two&&three'); | ||
| assert(called); | ||
|
|
||
| assert.sameValue(['one', 'two', 'three'].values().join(undefined), 'one,two,three'); | ||
|
|
||
| assert.sameValue(['one', 'two', 'three'].values().join(null), 'onenulltwonullthree'); |
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.
?
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.
Arguably this is more readable in terms of the failures you get. Certainly it is not worse. In any case I don't think it's worth changing.