Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions 4 features.txt
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ nonextensible-applies-to-private
# https://github.com/tc39/proposal-joint-iteration
joint-iteration

# Iterator Join
# https://github.com/tc39/proposal-iterator-join
Iterator.prototype.join

## Standard language features
#
# Language features that have been included in a published version of the
Expand Down
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);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
assert.sameValue(gotNext, false);
assert(!gotNext);

?

Copy link
Copy Markdown
Member Author

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.

assert(calledReturn);
13 changes: 13 additions & 0 deletions 13 test/built-ins/Iterator/prototype/join/contents-nullish.js
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(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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'
);
22 changes: 22 additions & 0 deletions 22 test/built-ins/Iterator/prototype/join/contents-tostring.js
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');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The 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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The 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);
15 changes: 15 additions & 0 deletions 15 test/built-ins/Iterator/prototype/join/descriptor.js
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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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);
16 changes: 16 additions & 0 deletions 16 test/built-ins/Iterator/prototype/join/length.js
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
});
16 changes: 16 additions & 0 deletions 16 test/built-ins/Iterator/prototype/join/name.js
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
});
16 changes: 16 additions & 0 deletions 16 test/built-ins/Iterator/prototype/join/not-a-constructor.js
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();
});
38 changes: 38 additions & 0 deletions 38 test/built-ins/Iterator/prototype/join/receiver-not-object.js
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');
16 changes: 16 additions & 0 deletions 16 test/built-ins/Iterator/prototype/join/results-no-separator.js
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');
26 changes: 26 additions & 0 deletions 26 test/built-ins/Iterator/prototype/join/separator-tostring.js
Comment thread
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');
Morty Proxy This is a proxified and sanitized view of the page, visit original site.