Skip to content
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 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);
assert(calledReturn);
13 changes: 13 additions & 0 deletions 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(),
'one,,two,,three'
);
22 changes: 22 additions & 0 deletions 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');
}
called = true;
return 'value';
},
};

assert.sameValue([coercible, 0, true].values().join(), 'value,0,true');
assert(called);
15 changes: 15 additions & 0 deletions 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.
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 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 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 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 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 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 test/built-ins/Iterator/prototype/join/separator-tostring.js
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');