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

Add initial tests for the "iterator-sequencing" proposal #4326

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
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 @@ -88,6 +88,10 @@ Error.isError
# https://tc39.es/proposal-defer-import-eval
import-defer

# Iterator Sequencing
# https://github.com/tc39/proposal-iterator-sequencing
iterator-sequencing

## Standard language features
#
# Language features that have been included in a published version of the
Expand Down
42 changes: 42 additions & 0 deletions test/built-ins/Iterator/concat/arguments-checked-in-order.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-iterator.concat
description: >
Arguments are validated in order.
info: |
Iterator.concat ( ...items )

1. Let iterables be a new empty List.
2. For each element item of items, do
a. If item is not an Object, throw a TypeError exception.
b. Let method be ? GetMethod(item, %Symbol.iterator%).
...
features: [iterator-sequencing]
---*/

let getIterator = 0;

let iterable1 = {
get [Symbol.iterator]() {
getIterator++;
return function() {
throw new Test262Error();
};
}
};

let iterable2 = {
get [Symbol.iterator]() {
throw new Test262Error();
}
};

assert.sameValue(getIterator, 0);

assert.throws(TypeError, function() {
Iterator.concat(iterable1, null, iterable2);
});

assert.sameValue(getIterator, 1);
49 changes: 49 additions & 0 deletions test/built-ins/Iterator/concat/fresh-iterator-result.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-iterator.concat
description: >
Returns a fresh iterator result object
info: |
Iterator.concat ( ...items )

...
3. Let closure be a new Abstract Closure with no parameters that captures iterables and performs the following steps when called:
a. For each Record iterable of iterables, do
...
v. Repeat, while innerAlive is true,
1. Let innerValue be ? IteratorStepValue(iteratorRecord).
2. If innerValue is done, then
...
3. Else,
a. Let completion be Completion(Yield(innerValue)).
...
features: [iterator-sequencing]
---*/

let oldIterResult = {
done: false,
value: 123,
};

let testIterator = {
next() {
return oldIterResult;
}
};

let iterable = {
[Symbol.iterator]() {
return testIterator;
}
};

let iterator = Iterator.concat(iterable);

let iterResult = iterator.next();

assert.sameValue(iterResult.done, false);
assert.sameValue(iterResult.value, 123);

assert.sameValue(iterResult, oldIterResult);
52 changes: 52 additions & 0 deletions test/built-ins/Iterator/concat/get-iterator-method-only-once.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-iterator.concat
description: >
Gets the iterator method from the input iterables only once.
info: |
Iterator.concat ( ...items )

1. Let iterables be a new empty List.
2. For each element item of items, do
a. If item is not an Object, throw a TypeError exception.
b. Let method be ? GetMethod(item, %Symbol.iterator%).
c. If method is undefined, throw a TypeError exception.
d. Append the Record { [[OpenMethod]]: method, [[Iterable]]: item } to iterables.
...
features: [iterator-sequencing]
includes: [compareArray.js]
---*/

let iteratorGets = 0;
let iteratorCalls = 0;
let array = [1, 2, 3];

class CountingIterable {
get [Symbol.iterator]() {
++iteratorGets;

return function () {
++iteratorCalls;
return array[Symbol.iterator]();
};
}
}

let iterable = new CountingIterable();

assert.sameValue(iteratorGets, 0);
assert.sameValue(iteratorCalls, 0);

let iter = Iterator.concat(iterable);

assert.sameValue(iteratorGets, 1);
assert.sameValue(iteratorCalls, 0);

let result = [...iter];

assert.sameValue(iteratorGets, 1);
assert.sameValue(iteratorCalls, 1);

assert.compareArray(result, array);
27 changes: 27 additions & 0 deletions test/built-ins/Iterator/concat/get-iterator-method-throws.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-iterator.concat
description: >
Error thrown when retrieving the iterator method.
info: |
Iterator.concat ( ...items )

1. Let iterables be a new empty List.
2. For each element item of items, do
a. If item is not an Object, throw a TypeError exception.
b. Let method be ? GetMethod(item, %Symbol.iterator%).
...
features: [iterator-sequencing]
---*/

var iterable = {
get [Symbol.iterator]() {
throw new Test262Error();
}
};

assert.throws(Test262Error, function() {
Iterator.concat(iterable);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-iterator.concat
description: >
Inner iterators created in order
info: |
Iterator.concat ( ...items )

...
3. Let closure be a new Abstract Closure with no parameters that captures iterables and performs the following steps when called:
a. For each Record iterable of iterables, do
i. Let iter be ? Call(iterable.[[OpenMethod]], iterable.[[Iterable]]).
...
v. Repeat, while innerAlive is true,
...
features: [iterator-sequencing]
includes: [compareArray.js]
---*/

let calledIterator = [];

let iterable1 = {
[Symbol.iterator]() {
calledIterator.push("iterable1");
return [1][Symbol.iterator]();
}
};

let iterable2 = {
[Symbol.iterator]() {
calledIterator.push("iterable2");
return [2][Symbol.iterator]();
}
};

let iterator = Iterator.concat(iterable1, iterable2);

assert.compareArray(calledIterator, []);

let iterResult = iterator.next();
assert.sameValue(iterResult.done, false);
assert.sameValue(iterResult.value, 1);

assert.compareArray(calledIterator, ["iterable1"]);

iterResult = iterator.next();
assert.sameValue(iterResult.done, false);
assert.sameValue(iterResult.value, 2);

assert.compareArray(calledIterator, ["iterable1", "iterable2"]);
15 changes: 15 additions & 0 deletions test/built-ins/Iterator/concat/is-function.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-iterator.concat
description: >
Iterator.concat is a built-in function
features: [iterator-sequencing]
---*/

assert.sameValue(
typeof Iterator.concat,
"function",
"The value of `typeof Iterator.concat` is 'function'"
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (C) 2024 Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-iterator.concat
description: >
Does not throw an error for iterable primitive wrapper objects
info: |
Iterator.concat ( ...items )

1. Let iterables be a new empty List.
2. For each element item of items, do
a. If item is not an Object, throw a TypeError exception.
...
features: [iterator-sequencing]
---*/

let desc = {
value: function() {
return {
next: function() {
return { done: true, value: undefined };
},
};
},
writable: false,
enumerable: false,
configurable: true,
};

Object.defineProperty(Boolean.prototype, Symbol.iterator, desc);
Object.defineProperty(Number.prototype, Symbol.iterator, desc);
Object.defineProperty(BigInt.prototype, Symbol.iterator, desc);
// NOTE: String.prototype already has a Symbol.iterator property
Object.defineProperty(Symbol.prototype, Symbol.iterator, desc);

Iterator.concat(
Object(true),
Object(123),
Object(123n),
Object("test"),
Object(Symbol()),
).next();
23 changes: 23 additions & 0 deletions test/built-ins/Iterator/concat/length.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-iterator.concat
description: >
Iterator.concat has a "length" property whose value is 0.
info: |
ECMAScript Standard Built-in Objects

Unless otherwise specified, the length property of a built-in
Function object has the attributes { [[Writable]]: false, [[Enumerable]]:
false, [[Configurable]]: true }.
features: [iterator-sequencing]
includes: [propertyHelper.js]
---*/

verifyProperty(Iterator.concat, "length", {
value: 0,
writable: false,
enumerable: false,
configurable: true,
});
45 changes: 45 additions & 0 deletions test/built-ins/Iterator/concat/many-arguments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-iterator.concat
description: >
Iterator.concat when called with many arguments.
info: |
Iterator.concat ( ...items )

1. Let iterables be a new empty List.
2. For each element item of items, do
...
3. Let closure be a new Abstract Closure with no parameters that captures iterables and performs the following steps when called:
a. For each Record iterable of iterables, do
...
b. Return ReturnCompletion(undefined).
...
6. Return gen.
features: [iterator-sequencing]
---*/

let iterables = [
[/* empty */],
[1],
[2, 3],
[4, 5, 6],
[7, 8, 9, 10],
];

let iterator = Iterator.concat(...iterables);

let array = [].concat(...iterables);
michaelficarra marked this conversation as resolved.
Show resolved Hide resolved

for (let i = 0; i < array.length; i++) {
let iterResult = iterator.next();

assert.sameValue(iterResult.done, false);
assert.sameValue(iterResult.value, array[i]);
}

let iterResult = iterator.next();

assert.sameValue(iterResult.done, true);
assert.sameValue(iterResult.value, undefined);
30 changes: 30 additions & 0 deletions test/built-ins/Iterator/concat/name.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (C) 2024 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-iterator.concat
description: >
The "name" property of Iterator.concat
info: |
17 ECMAScript Standard Built-in Objects

Every built-in Function object, including constructors, that is not
identified as an anonymous function has a name property whose value is a
String. Unless otherwise specified, this value is the name that is given to
the function in this specification.

...

Unless otherwise specified, the name property of a built-in Function
object, if it exists, has the attributes { [[Writable]]: false,
[[Enumerable]]: false, [[Configurable]]: true }.
features: [iterator-sequencing]
includes: [propertyHelper.js]
---*/

verifyProperty(Iterator.concat, "name", {
value: "concat",
writable: false,
enumerable: false,
configurable: true,
});
Loading
Loading