diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..62b6a21
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,62 @@
+{
+ "root": true,
+
+ "extends": "@ljharb",
+
+ "globals": {
+ "Iterator": false,
+ },
+
+ "rules": {
+ "array-bracket-newline": 0,
+ "func-name-matching": 0,
+ "id-length": 0,
+ "max-lines-per-function": 0,
+ "multiline-comment-style": 0,
+ "new-cap": [2, {
+ "capIsNewExceptions": [
+ "Call",
+ "CreateIteratorFromClosure",
+ "CreateIterResultObject",
+ "GeneratorResume",
+ "GeneratorResumeAbrupt",
+ "GeneratorStart",
+ "GeneratorValidate",
+ "Get",
+ "GetIntrinsic",
+ "GetIterator",
+ "GetIteratorDirect",
+ "GetIteratorFlattenable",
+ "GetMethod",
+ "IsCallable",
+ "IteratorClose",
+ "IteratorComplete",
+ "IteratorNext",
+ "IteratorStep",
+ "IteratorValue",
+ "NormalCompletion",
+ "OrdinaryHasInstance",
+ "OrdinaryObjectCreate",
+ "PromiseResolve",
+ "ThrowCompletion",
+ "ToBoolean",
+ "ToIntegerOrInfinity",
+ "ToNumber",
+ "ToObject",
+ "Type",
+ ],
+ }],
+ "no-negated-condition": 1,
+ "object-curly-newline": 0,
+ "sort-keys": 0,
+ },
+
+ "overrides": [
+ {
+ "files": "test/**",
+ "rules": {
+ "max-params": 0,
+ },
+ },
+ ],
+}
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..168ae6a
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,12 @@
+# These are supported funding model platforms
+
+github: [ljharb]
+patreon: # Replace with a single Patreon username
+open_collective: # Replace with a single Open Collective username
+ko_fi: # Replace with a single Ko-fi username
+tidelift: npm/iterator-helpers
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+liberapay: # Replace with a single Liberapay username
+issuehunt: # Replace with a single IssueHunt username
+otechie: # Replace with a single Otechie username
+custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
diff --git a/.github/workflows/node-aught.yml b/.github/workflows/node-aught.yml
new file mode 100644
index 0000000..f3cddd8
--- /dev/null
+++ b/.github/workflows/node-aught.yml
@@ -0,0 +1,18 @@
+name: 'Tests: node.js < 10'
+
+on: [pull_request, push]
+
+jobs:
+ tests:
+ uses: ljharb/actions/.github/workflows/node.yml@main
+ with:
+ range: '< 10'
+ type: minors
+ command: npm run tests-only
+
+ node:
+ name: 'node < 10'
+ needs: [tests]
+ runs-on: ubuntu-latest
+ steps:
+ - run: 'echo tests completed'
diff --git a/.github/workflows/node-pretest.yml b/.github/workflows/node-pretest.yml
new file mode 100644
index 0000000..765edf7
--- /dev/null
+++ b/.github/workflows/node-pretest.yml
@@ -0,0 +1,7 @@
+name: 'Tests: pretest/posttest'
+
+on: [pull_request, push]
+
+jobs:
+ tests:
+ uses: ljharb/actions/.github/workflows/pretest.yml@main
diff --git a/.github/workflows/node-tens.yml b/.github/workflows/node-tens.yml
new file mode 100644
index 0000000..b49ceb1
--- /dev/null
+++ b/.github/workflows/node-tens.yml
@@ -0,0 +1,18 @@
+name: 'Tests: node.js >= 10'
+
+on: [pull_request, push]
+
+jobs:
+ tests:
+ uses: ljharb/actions/.github/workflows/node.yml@main
+ with:
+ range: '>= 10'
+ type: minors
+ command: npm run tests-only
+
+ node:
+ name: 'node >= 10'
+ needs: [tests]
+ runs-on: ubuntu-latest
+ steps:
+ - run: 'echo tests completed'
diff --git a/.github/workflows/rebase.yml b/.github/workflows/rebase.yml
new file mode 100644
index 0000000..b9e1712
--- /dev/null
+++ b/.github/workflows/rebase.yml
@@ -0,0 +1,9 @@
+name: Automatic Rebase
+
+on: [pull_request_target]
+
+jobs:
+ _:
+ uses: ljharb/actions/.github/workflows/rebase.yml@main
+ secrets:
+ token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/require-allow-edits.yml b/.github/workflows/require-allow-edits.yml
new file mode 100644
index 0000000..7b842f8
--- /dev/null
+++ b/.github/workflows/require-allow-edits.yml
@@ -0,0 +1,12 @@
+name: Require “Allow Edits”
+
+on: [pull_request_target]
+
+jobs:
+ _:
+ name: "Require “Allow Edits”"
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: ljharb/require-allow-edits@main
diff --git a/.gitignore b/.gitignore
index 52ab08e..335819f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -107,3 +107,5 @@ dist
npm-shrinkwrap.json
package-lock.json
yarn.lock
+
+.npmignore
diff --git a/.npmrc b/.npmrc
index 43c97e7..eacea13 100644
--- a/.npmrc
+++ b/.npmrc
@@ -1 +1,3 @@
package-lock=false
+allow-same-version=true
+message=v%s
diff --git a/.nycrc b/.nycrc
new file mode 100644
index 0000000..1826526
--- /dev/null
+++ b/.nycrc
@@ -0,0 +1,13 @@
+{
+ "all": true,
+ "check-coverage": false,
+ "reporter": ["text-summary", "text", "html", "json"],
+ "lines": 86,
+ "statements": 85.93,
+ "functions": 82.43,
+ "branches": 76.06,
+ "exclude": [
+ "coverage",
+ "test"
+ ]
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..03a962f
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,6 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
diff --git a/Iterator.from/auto.js b/Iterator.from/auto.js
new file mode 100644
index 0000000..8ebf606
--- /dev/null
+++ b/Iterator.from/auto.js
@@ -0,0 +1,3 @@
+'use strict';
+
+require('./shim')();
diff --git a/Iterator.from/implementation.js b/Iterator.from/implementation.js
new file mode 100644
index 0000000..5bfb3ac
--- /dev/null
+++ b/Iterator.from/implementation.js
@@ -0,0 +1,34 @@
+'use strict';
+
+var OrdinaryHasInstance = require('es-abstract/2022/OrdinaryHasInstance');
+var OrdinaryObjectCreate = require('es-abstract/2022/OrdinaryObjectCreate');
+var ToObject = require('es-abstract/2022/ToObject');
+var Type = require('es-abstract/2022/Type');
+
+var GetIteratorFlattenable = require('../aos/GetIteratorFlattenable');
+
+var $Iterator = require('../Iterator/polyfill')();
+var $WrapForValidIteratorPrototype = require('../WrapForValidIteratorPrototype');
+
+var SLOT = require('internal-slot');
+
+module.exports = function from(O) {
+ if (Type(O) === 'String') {
+ // eslint-disable-next-line no-param-reassign
+ O = ToObject(O); // step 1
+ }
+
+ var iteratorRecord = GetIteratorFlattenable(O, 'sync'); // step 2
+
+ var hasInstance = OrdinaryHasInstance($Iterator, iteratorRecord['[[Iterator]]']); // step 3
+
+ if (hasInstance) { // step 4
+ return iteratorRecord['[[Iterator]]']; // step 4.a
+ }
+
+ var wrapper = OrdinaryObjectCreate($WrapForValidIteratorPrototype); // , ['[[Iterated]]']); // step 5
+
+ SLOT.set(wrapper, '[[Iterated]]', iteratorRecord); // step 6
+
+ return wrapper; // step 7
+};
diff --git a/Iterator.from/index.js b/Iterator.from/index.js
new file mode 100644
index 0000000..4c50b07
--- /dev/null
+++ b/Iterator.from/index.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var callBind = require('call-bind');
+var define = require('define-properties');
+
+var implementation = require('./implementation');
+var getPolyfill = require('./polyfill');
+var shim = require('./shim');
+
+var bound = callBind(getPolyfill(), null);
+
+define(bound, {
+ getPolyfill: getPolyfill,
+ implementation: implementation,
+ shim: shim
+});
+
+module.exports = bound;
diff --git a/Iterator.from/polyfill.js b/Iterator.from/polyfill.js
new file mode 100644
index 0000000..2413acf
--- /dev/null
+++ b/Iterator.from/polyfill.js
@@ -0,0 +1,9 @@
+'use strict';
+
+var implementation = require('./implementation');
+
+var $Iterator = require('../Iterator');
+
+module.exports = function getPolyfill() {
+ return typeof $Iterator.from === 'function' ? $Iterator.from : implementation;
+};
diff --git a/Iterator.from/shim.js b/Iterator.from/shim.js
new file mode 100644
index 0000000..6d43cd6
--- /dev/null
+++ b/Iterator.from/shim.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var getPolyfill = require('./polyfill');
+var define = require('define-properties');
+
+var getIteratorPolyfill = require('../Iterator/polyfill');
+
+module.exports = function shimIteratorFrom() {
+ var $Iterator = getIteratorPolyfill();
+ var polyfill = getPolyfill();
+ define(
+ $Iterator,
+ { from: polyfill },
+ { from: function () { return $Iterator.from !== polyfill; } }
+ );
+
+ return polyfill;
+};
diff --git a/Iterator.prototype.constructor/auto.js b/Iterator.prototype.constructor/auto.js
new file mode 100644
index 0000000..8ebf606
--- /dev/null
+++ b/Iterator.prototype.constructor/auto.js
@@ -0,0 +1,3 @@
+'use strict';
+
+require('./shim')();
diff --git a/Iterator.prototype.constructor/implementation.js b/Iterator.prototype.constructor/implementation.js
new file mode 100644
index 0000000..70987b2
--- /dev/null
+++ b/Iterator.prototype.constructor/implementation.js
@@ -0,0 +1,5 @@
+'use strict';
+
+var $Iterator = require('../Iterator/polyfill')();
+
+module.exports = $Iterator;
diff --git a/Iterator.prototype.constructor/index.js b/Iterator.prototype.constructor/index.js
new file mode 100644
index 0000000..a6b0aec
--- /dev/null
+++ b/Iterator.prototype.constructor/index.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var bind = require('function-bind');
+
+var implementation = require('./implementation');
+var getPolyfill = require('./polyfill');
+var shim = require('./shim');
+
+var polyfill = bind.call(getPolyfill());
+
+define(polyfill, {
+ getPolyfill: getPolyfill,
+ implementation: implementation,
+ shim: shim
+});
+
+module.exports = polyfill;
diff --git a/Iterator.prototype.constructor/polyfill.js b/Iterator.prototype.constructor/polyfill.js
new file mode 100644
index 0000000..382fb9b
--- /dev/null
+++ b/Iterator.prototype.constructor/polyfill.js
@@ -0,0 +1,7 @@
+'use strict';
+
+var implementation = require('./implementation');
+
+module.exports = function getPolyfill() {
+ return implementation;
+};
diff --git a/Iterator.prototype.constructor/shim.js b/Iterator.prototype.constructor/shim.js
new file mode 100644
index 0000000..ee35d80
--- /dev/null
+++ b/Iterator.prototype.constructor/shim.js
@@ -0,0 +1,20 @@
+'use strict';
+
+var define = require('define-properties');
+var getPolyfill = require('./polyfill');
+
+var $IteratorPrototype = require('iterator.prototype');
+
+var $Iterator = require('./implementation');
+
+module.exports = function shimIteratorPrototypeCtor() {
+ var polyfill = getPolyfill();
+
+ define(
+ $IteratorPrototype,
+ { constructor: $Iterator },
+ { constructor: function () { return $Iterator.constructor !== polyfill; } }
+ );
+
+ return polyfill;
+};
diff --git a/Iterator.prototype.drop/auto.js b/Iterator.prototype.drop/auto.js
new file mode 100644
index 0000000..8ebf606
--- /dev/null
+++ b/Iterator.prototype.drop/auto.js
@@ -0,0 +1,3 @@
+'use strict';
+
+require('./shim')();
diff --git a/Iterator.prototype.drop/implementation.js b/Iterator.prototype.drop/implementation.js
new file mode 100644
index 0000000..1220dc8
--- /dev/null
+++ b/Iterator.prototype.drop/implementation.js
@@ -0,0 +1,72 @@
+'use strict';
+
+var GetIntrinsic = require('get-intrinsic');
+
+var $RangeError = GetIntrinsic('%RangeError%');
+
+var IteratorClose = require('es-abstract/2022/IteratorClose');
+var IteratorStep = require('es-abstract/2022/IteratorStep');
+var IteratorValue = require('es-abstract/2022/IteratorValue');
+var ToIntegerOrInfinity = require('es-abstract/2022/ToIntegerOrInfinity');
+var ToNumber = require('es-abstract/2022/ToNumber');
+
+var GetIteratorDirect = require('../aos/GetIteratorDirect');
+var CreateIteratorFromClosure = require('../aos/CreateIteratorFromClosure');
+
+var iterHelperProto = require('../IteratorHelperPrototype');
+
+var isNaN = require('es-abstract/helpers/isNaN');
+
+var SLOT = require('internal-slot');
+
+module.exports = function drop(limit) {
+ var iterated = GetIteratorDirect(this); // step 1
+
+ var numLimit = ToNumber(limit); // step 2
+ if (isNaN(numLimit)) {
+ throw new $RangeError('`limit` must be a non-NaN number'); // step 3
+ }
+
+ var integerLimit = ToIntegerOrInfinity(numLimit); // step 4
+ if (integerLimit < 0) {
+ throw new $RangeError('`limit` must be a >= 0'); // step 5
+ }
+
+ var sentinel = {};
+ var remaining = integerLimit; // step 6.a
+ var closure = function () { // step 6
+ var next;
+ while (remaining > 0) { // step 6.b
+ if (remaining !== Infinity) { // step 6.b.i
+ remaining -= 1; // step 6.b.i.1
+ }
+
+ next = IteratorStep(iterated['[[Iterator]]']); // step 6.b.ii
+ if (!next) {
+ // return void undefined; // step 6.b.iii
+ return sentinel;
+ }
+ }
+ // while (true) { // step 6.c
+ next = IteratorStep(iterated['[[Iterator]]']); // step 6.c.i
+ if (!next) {
+ // return void undefined; // step 6.c.ii
+ return sentinel;
+ }
+ try {
+ var value = IteratorValue(next); // step 6.c.iii
+ return value; // step 6.c.iii
+ } catch (e) {
+ // close iterator // step 6.c.icv
+ IteratorClose(
+ iterated['[[Iterator]]'],
+ function () { throw e; }
+ );
+ }
+ // }
+ return void undefined;
+ };
+ SLOT.set(closure, '[[Sentinel]]', sentinel); // for the userland implementation
+
+ return CreateIteratorFromClosure(closure, 'Iterator Helper', iterHelperProto); // step 4
+};
diff --git a/Iterator.prototype.drop/index.js b/Iterator.prototype.drop/index.js
new file mode 100644
index 0000000..751f5fb
--- /dev/null
+++ b/Iterator.prototype.drop/index.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var callBind = require('call-bind');
+
+var implementation = require('./implementation');
+var getPolyfill = require('./polyfill');
+var shim = require('./shim');
+
+var polyfill = callBind(getPolyfill());
+
+define(polyfill, {
+ getPolyfill: getPolyfill,
+ implementation: implementation,
+ shim: shim
+});
+
+module.exports = polyfill;
diff --git a/Iterator.prototype.drop/polyfill.js b/Iterator.prototype.drop/polyfill.js
new file mode 100644
index 0000000..5f56a9c
--- /dev/null
+++ b/Iterator.prototype.drop/polyfill.js
@@ -0,0 +1,9 @@
+'use strict';
+
+var implementation = require('./implementation');
+
+module.exports = function getPolyfill() {
+ return typeof Iterator === 'function' && typeof Iterator.prototype.drop === 'function'
+ ? Iterator.prototype.drop
+ : implementation;
+};
diff --git a/Iterator.prototype.drop/shim.js b/Iterator.prototype.drop/shim.js
new file mode 100644
index 0000000..491d8b7
--- /dev/null
+++ b/Iterator.prototype.drop/shim.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var getPolyfill = require('./polyfill');
+
+var $IteratorPrototype = require('iterator.prototype');
+
+module.exports = function shimIteratorPrototypeDrop() {
+ var polyfill = getPolyfill();
+
+ define(
+ $IteratorPrototype,
+ { drop: polyfill },
+ { drop: function () { return $IteratorPrototype.drop !== polyfill; } }
+ );
+
+ return polyfill;
+};
diff --git a/Iterator.prototype.every/auto.js b/Iterator.prototype.every/auto.js
new file mode 100644
index 0000000..8ebf606
--- /dev/null
+++ b/Iterator.prototype.every/auto.js
@@ -0,0 +1,3 @@
+'use strict';
+
+require('./shim')();
diff --git a/Iterator.prototype.every/implementation.js b/Iterator.prototype.every/implementation.js
new file mode 100644
index 0000000..a257d88
--- /dev/null
+++ b/Iterator.prototype.every/implementation.js
@@ -0,0 +1,51 @@
+'use strict';
+
+var GetIntrinsic = require('get-intrinsic');
+
+var $TypeError = GetIntrinsic('%TypeError%');
+
+var Call = require('es-abstract/2022/Call');
+var IsCallable = require('es-abstract/2022/IsCallable');
+var IteratorClose = require('es-abstract/2022/IteratorClose');
+var IteratorStep = require('es-abstract/2022/IteratorStep');
+var IteratorValue = require('es-abstract/2022/IteratorValue');
+var ToBoolean = require('es-abstract/2022/ToBoolean');
+
+var GetIteratorDirect = require('../aos/GetIteratorDirect');
+
+module.exports = function every(predicate) {
+ var iterated = GetIteratorDirect(this); // step 1
+
+ if (!IsCallable(predicate)) {
+ throw new $TypeError('`predicate` must be a function'); // step 2
+ }
+
+ var counter = 0; // step 3
+
+ // eslint-disable-next-line no-constant-condition
+ while (true) { // step 4
+ var next = IteratorStep(iterated['[[Iterator]]']); // step 4.a
+ if (!next) {
+ return true; // step 4.b
+ }
+ var value = IteratorValue(next); // step 4.c
+ var result;
+ try {
+ result = Call(predicate, void undefined, [value, counter]); // step 4.d
+ } catch (e) {
+ // close iterator // step 4.e
+ IteratorClose(
+ iterated['[[Iterator]]'],
+ function () { throw e; }
+ );
+ } finally {
+ counter += 1; // step 4.g
+ }
+ if (!ToBoolean(result)) {
+ return IteratorClose(
+ iterated['[[Iterator]]'],
+ function () { return false; }
+ ); // step 4.f
+ }
+ }
+};
diff --git a/Iterator.prototype.every/index.js b/Iterator.prototype.every/index.js
new file mode 100644
index 0000000..751f5fb
--- /dev/null
+++ b/Iterator.prototype.every/index.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var callBind = require('call-bind');
+
+var implementation = require('./implementation');
+var getPolyfill = require('./polyfill');
+var shim = require('./shim');
+
+var polyfill = callBind(getPolyfill());
+
+define(polyfill, {
+ getPolyfill: getPolyfill,
+ implementation: implementation,
+ shim: shim
+});
+
+module.exports = polyfill;
diff --git a/Iterator.prototype.every/polyfill.js b/Iterator.prototype.every/polyfill.js
new file mode 100644
index 0000000..db66f3e
--- /dev/null
+++ b/Iterator.prototype.every/polyfill.js
@@ -0,0 +1,9 @@
+'use strict';
+
+var implementation = require('./implementation');
+
+module.exports = function getPolyfill() {
+ return typeof Iterator === 'function' && typeof Iterator.prototype.every === 'function'
+ ? Iterator.prototype.every
+ : implementation;
+};
diff --git a/Iterator.prototype.every/shim.js b/Iterator.prototype.every/shim.js
new file mode 100644
index 0000000..23a6cc0
--- /dev/null
+++ b/Iterator.prototype.every/shim.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var getPolyfill = require('./polyfill');
+
+var $IteratorPrototype = require('iterator.prototype');
+
+module.exports = function shimIteratorPrototypeEvery() {
+ var polyfill = getPolyfill();
+
+ define(
+ $IteratorPrototype,
+ { every: polyfill },
+ { every: function () { return $IteratorPrototype.every !== polyfill; } }
+ );
+
+ return polyfill;
+};
diff --git a/Iterator.prototype.filter/auto.js b/Iterator.prototype.filter/auto.js
new file mode 100644
index 0000000..8ebf606
--- /dev/null
+++ b/Iterator.prototype.filter/auto.js
@@ -0,0 +1,3 @@
+'use strict';
+
+require('./shim')();
diff --git a/Iterator.prototype.filter/implementation.js b/Iterator.prototype.filter/implementation.js
new file mode 100644
index 0000000..73d35c2
--- /dev/null
+++ b/Iterator.prototype.filter/implementation.js
@@ -0,0 +1,58 @@
+'use strict';
+
+var GetIntrinsic = require('get-intrinsic');
+
+var $TypeError = GetIntrinsic('%TypeError%');
+
+var Call = require('es-abstract/2022/Call');
+var IsCallable = require('es-abstract/2022/IsCallable');
+var IteratorClose = require('es-abstract/2022/IteratorClose');
+var IteratorStep = require('es-abstract/2022/IteratorStep');
+var IteratorValue = require('es-abstract/2022/IteratorValue');
+var ToBoolean = require('es-abstract/2022/ToBoolean');
+
+var GetIteratorDirect = require('../aos/GetIteratorDirect');
+var CreateIteratorFromClosure = require('../aos/CreateIteratorFromClosure');
+
+var iterHelperProto = require('../IteratorHelperPrototype');
+
+var SLOT = require('internal-slot');
+
+module.exports = function filter(predicate) {
+ var iterated = GetIteratorDirect(this); // step 1
+
+ if (!IsCallable(predicate)) {
+ throw new $TypeError('`predicate` must be a function'); // step 2
+ }
+
+ var sentinel = {};
+ var closure = function () {
+ var counter = 0; // step 3.a
+ // eslint-disable-next-line no-constant-condition
+ while (true) { // step 3.b
+ var next = IteratorStep(iterated['[[Iterator]]']); // step 3.b.i
+ if (!next) {
+ // return void undefined; // step 3.b.ii
+ return sentinel;
+ }
+ var value = IteratorValue(next); // step 3.b.iii
+ var selected;
+ try {
+ selected = Call(predicate, void undefined, [value, counter]); // step 3.b.iv
+ // yield mapped // step 3.b.vi
+ if (ToBoolean(selected)) {
+ return value;
+ }
+ } catch (e) {
+ // close iterator // step 3.b.v, 3.b.vii
+ IteratorClose(iterated['[[Iterator]]'], true);
+ throw e;
+ } finally {
+ counter += 1; // step 3.b.viii
+ }
+ }
+ };
+ SLOT.set(closure, '[[Sentinel]]', sentinel); // for the userland implementation
+
+ return CreateIteratorFromClosure(closure, 'Iterator Helper', iterHelperProto); // step 4
+};
diff --git a/Iterator.prototype.filter/index.js b/Iterator.prototype.filter/index.js
new file mode 100644
index 0000000..751f5fb
--- /dev/null
+++ b/Iterator.prototype.filter/index.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var callBind = require('call-bind');
+
+var implementation = require('./implementation');
+var getPolyfill = require('./polyfill');
+var shim = require('./shim');
+
+var polyfill = callBind(getPolyfill());
+
+define(polyfill, {
+ getPolyfill: getPolyfill,
+ implementation: implementation,
+ shim: shim
+});
+
+module.exports = polyfill;
diff --git a/Iterator.prototype.filter/polyfill.js b/Iterator.prototype.filter/polyfill.js
new file mode 100644
index 0000000..a5acc9b
--- /dev/null
+++ b/Iterator.prototype.filter/polyfill.js
@@ -0,0 +1,9 @@
+'use strict';
+
+var implementation = require('./implementation');
+
+module.exports = function getPolyfill() {
+ return typeof Iterator === 'function' && typeof Iterator.prototype.filter === 'function'
+ ? Iterator.prototype.filter
+ : implementation;
+};
diff --git a/Iterator.prototype.filter/shim.js b/Iterator.prototype.filter/shim.js
new file mode 100644
index 0000000..146eb31
--- /dev/null
+++ b/Iterator.prototype.filter/shim.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var getPolyfill = require('./polyfill');
+
+var $IteratorPrototype = require('iterator.prototype');
+
+module.exports = function shimIteratorPrototypeFilter() {
+ var polyfill = getPolyfill();
+
+ define(
+ $IteratorPrototype,
+ { filter: polyfill },
+ { filter: function () { return $IteratorPrototype.filter !== polyfill; } }
+ );
+
+ return polyfill;
+};
diff --git a/Iterator.prototype.find/auto.js b/Iterator.prototype.find/auto.js
new file mode 100644
index 0000000..8ebf606
--- /dev/null
+++ b/Iterator.prototype.find/auto.js
@@ -0,0 +1,3 @@
+'use strict';
+
+require('./shim')();
diff --git a/Iterator.prototype.find/implementation.js b/Iterator.prototype.find/implementation.js
new file mode 100644
index 0000000..50006d5
--- /dev/null
+++ b/Iterator.prototype.find/implementation.js
@@ -0,0 +1,51 @@
+'use strict';
+
+var GetIntrinsic = require('get-intrinsic');
+
+var $TypeError = GetIntrinsic('%TypeError%');
+
+var Call = require('es-abstract/2022/Call');
+var IsCallable = require('es-abstract/2022/IsCallable');
+var IteratorClose = require('es-abstract/2022/IteratorClose');
+var IteratorStep = require('es-abstract/2022/IteratorStep');
+var IteratorValue = require('es-abstract/2022/IteratorValue');
+var ToBoolean = require('es-abstract/2022/ToBoolean');
+
+var GetIteratorDirect = require('../aos/GetIteratorDirect');
+
+module.exports = function find(predicate) {
+ var iterated = GetIteratorDirect(this); // step 1
+
+ if (!IsCallable(predicate)) {
+ throw new $TypeError('`predicate` must be a function'); // step 2
+ }
+
+ var counter = 0; // step 3
+
+ // eslint-disable-next-line no-constant-condition
+ while (true) { // step 4
+ var next = IteratorStep(iterated['[[Iterator]]']); // step 4.a
+ if (!next) {
+ return void undefined; // step 4.b
+ }
+ var value = IteratorValue(next); // step 4.c
+ var result;
+ try {
+ result = Call(predicate, void undefined, [value, counter]); // step 4.d
+ } catch (e) {
+ // close iterator // step 4.e
+ IteratorClose(
+ iterated['[[Iterator]]'],
+ function () { throw e; }
+ );
+ } finally {
+ counter += 1; // step 4.g
+ }
+ if (ToBoolean(result)) {
+ return IteratorClose(
+ iterated['[[Iterator]]'],
+ function () { return value; } // eslint-disable-line no-loop-func
+ ); // step 4.f
+ }
+ }
+};
diff --git a/Iterator.prototype.find/index.js b/Iterator.prototype.find/index.js
new file mode 100644
index 0000000..751f5fb
--- /dev/null
+++ b/Iterator.prototype.find/index.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var callBind = require('call-bind');
+
+var implementation = require('./implementation');
+var getPolyfill = require('./polyfill');
+var shim = require('./shim');
+
+var polyfill = callBind(getPolyfill());
+
+define(polyfill, {
+ getPolyfill: getPolyfill,
+ implementation: implementation,
+ shim: shim
+});
+
+module.exports = polyfill;
diff --git a/Iterator.prototype.find/polyfill.js b/Iterator.prototype.find/polyfill.js
new file mode 100644
index 0000000..ce49155
--- /dev/null
+++ b/Iterator.prototype.find/polyfill.js
@@ -0,0 +1,9 @@
+'use strict';
+
+var implementation = require('./implementation');
+
+module.exports = function getPolyfill() {
+ return typeof Iterator === 'function' && typeof Iterator.prototype.find === 'function'
+ ? Iterator.prototype.find
+ : implementation;
+};
diff --git a/Iterator.prototype.find/shim.js b/Iterator.prototype.find/shim.js
new file mode 100644
index 0000000..2582793
--- /dev/null
+++ b/Iterator.prototype.find/shim.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var getPolyfill = require('./polyfill');
+
+var $IteratorPrototype = require('iterator.prototype');
+
+module.exports = function shimIteratorPrototypeFind() {
+ var polyfill = getPolyfill();
+
+ define(
+ $IteratorPrototype,
+ { find: polyfill },
+ { find: function () { return $IteratorPrototype.find !== polyfill; } }
+ );
+
+ return polyfill;
+};
diff --git a/Iterator.prototype.flatMap/auto.js b/Iterator.prototype.flatMap/auto.js
new file mode 100644
index 0000000..8ebf606
--- /dev/null
+++ b/Iterator.prototype.flatMap/auto.js
@@ -0,0 +1,3 @@
+'use strict';
+
+require('./shim')();
diff --git a/Iterator.prototype.flatMap/implementation.js b/Iterator.prototype.flatMap/implementation.js
new file mode 100644
index 0000000..4ac0fe9
--- /dev/null
+++ b/Iterator.prototype.flatMap/implementation.js
@@ -0,0 +1,85 @@
+'use strict';
+
+var GetIntrinsic = require('get-intrinsic');
+
+var $TypeError = GetIntrinsic('%TypeError%');
+
+var Call = require('es-abstract/2022/Call');
+var IsCallable = require('es-abstract/2022/IsCallable');
+var IteratorClose = require('es-abstract/2022/IteratorClose');
+var IteratorStep = require('es-abstract/2022/IteratorStep');
+var IteratorValue = require('es-abstract/2022/IteratorValue');
+
+var GetIteratorDirect = require('../aos/GetIteratorDirect');
+var CreateIteratorFromClosure = require('../aos/CreateIteratorFromClosure');
+
+var GetIteratorFlattenable = require('../aos/GetIteratorFlattenable');
+var iterHelperProto = require('../IteratorHelperPrototype');
+
+var SLOT = require('internal-slot');
+
+module.exports = function flatMap(mapper) {
+ var iterated = GetIteratorDirect(this); // step 1
+
+ if (!IsCallable(mapper)) {
+ throw new $TypeError('`mapper` must be a function'); // step 2
+ }
+
+ var sentinel = {};
+ var counter = 0; // step 3.a
+ var closure = function () {
+ // while (true) { // step 3.b
+ var next = IteratorStep(iterated['[[Iterator]]']); // step 3.b.i
+ if (!next) {
+ // return void undefined; // step 3.b.ii
+ return sentinel;
+ }
+ var value = IteratorValue(next); // step 3.b.iii
+ var mapped;
+ var innerIterator;
+ try {
+ try {
+ mapped = Call(mapper, void undefined, [value, counter]); // step 3.b.iv
+ // yield mapped // step 3.b.vi
+ innerIterator = GetIteratorFlattenable(mapped, 'sync'); // step 3.b.vi
+ } catch (e) {
+ IteratorClose(
+ iterated['[[Iterator]]'],
+ function () { throw e; }
+ ); // steps 3.b.v, 3.b.vii
+ }
+ var innerAlive = true; // step 3.b.viii
+ while (innerAlive) { // step 3.b.ix
+ try {
+ var innerNext = IteratorStep(innerIterator['[[Iterator]]']); // step 3.b.ix.1
+ } catch (e) {
+ IteratorClose(
+ iterated['[[Iterator]]'],
+ function () { throw e; }
+ ); // step 3.b.ix.2
+ }
+ if (!innerNext) {
+ innerAlive = false; // step 3.b.ix.3.a
+ } else { // step 3.b.ix.4
+ var innerValue;
+ try {
+ innerValue = IteratorValue(innerNext); // step 3.b.ix.4.a
+ } catch (e) {
+ IteratorClose(
+ iterated['[[Iterator]]'],
+ function () { throw e; }
+ ); // step 3.b.ix.4.b
+ }
+ return innerValue; // step 3.b.ix.4.c
+ }
+ }
+ } finally {
+ counter += 1; // step 3.b.x
+ }
+ // }
+ return void undefined;
+ };
+ SLOT.set(closure, '[[Sentinel]]', sentinel); // for the userland implementation
+
+ return CreateIteratorFromClosure(closure, 'Iterator Helper', iterHelperProto); // step 4
+};
diff --git a/Iterator.prototype.flatMap/index.js b/Iterator.prototype.flatMap/index.js
new file mode 100644
index 0000000..751f5fb
--- /dev/null
+++ b/Iterator.prototype.flatMap/index.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var callBind = require('call-bind');
+
+var implementation = require('./implementation');
+var getPolyfill = require('./polyfill');
+var shim = require('./shim');
+
+var polyfill = callBind(getPolyfill());
+
+define(polyfill, {
+ getPolyfill: getPolyfill,
+ implementation: implementation,
+ shim: shim
+});
+
+module.exports = polyfill;
diff --git a/Iterator.prototype.flatMap/polyfill.js b/Iterator.prototype.flatMap/polyfill.js
new file mode 100644
index 0000000..7a636db
--- /dev/null
+++ b/Iterator.prototype.flatMap/polyfill.js
@@ -0,0 +1,9 @@
+'use strict';
+
+var implementation = require('./implementation');
+
+module.exports = function getPolyfill() {
+ return typeof Iterator === 'function' && typeof Iterator.prototype.flatMap === 'function'
+ ? Iterator.prototype.flatMap
+ : implementation;
+};
diff --git a/Iterator.prototype.flatMap/shim.js b/Iterator.prototype.flatMap/shim.js
new file mode 100644
index 0000000..44017a9
--- /dev/null
+++ b/Iterator.prototype.flatMap/shim.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var getPolyfill = require('./polyfill');
+
+var $IteratorPrototype = require('iterator.prototype');
+
+module.exports = function shimIteratorPrototypeFlatMap() {
+ var polyfill = getPolyfill();
+
+ define(
+ $IteratorPrototype,
+ { flatMap: polyfill },
+ { flatMap: function () { return $IteratorPrototype.flatMap !== polyfill; } }
+ );
+
+ return polyfill;
+};
diff --git a/Iterator.prototype.forEach/auto.js b/Iterator.prototype.forEach/auto.js
new file mode 100644
index 0000000..8ebf606
--- /dev/null
+++ b/Iterator.prototype.forEach/auto.js
@@ -0,0 +1,3 @@
+'use strict';
+
+require('./shim')();
diff --git a/Iterator.prototype.forEach/implementation.js b/Iterator.prototype.forEach/implementation.js
new file mode 100644
index 0000000..bc36151
--- /dev/null
+++ b/Iterator.prototype.forEach/implementation.js
@@ -0,0 +1,43 @@
+'use strict';
+
+var GetIntrinsic = require('get-intrinsic');
+
+var $TypeError = GetIntrinsic('%TypeError%');
+
+var Call = require('es-abstract/2022/Call');
+var IsCallable = require('es-abstract/2022/IsCallable');
+var IteratorClose = require('es-abstract/2022/IteratorClose');
+var IteratorStep = require('es-abstract/2022/IteratorStep');
+var IteratorValue = require('es-abstract/2022/IteratorValue');
+
+var GetIteratorDirect = require('../aos/GetIteratorDirect');
+
+module.exports = function forEach(fn) {
+ var iterated = GetIteratorDirect(this); // step 1
+
+ if (!IsCallable(fn)) {
+ throw new $TypeError('`fn` must be a function'); // step 2
+ }
+
+ var counter = 0; // step 3
+
+ // eslint-disable-next-line no-constant-condition
+ while (true) { // step 4
+ var next = IteratorStep(iterated['[[Iterator]]']); // step 4.a
+ if (!next) {
+ return void undefined; // step 4.b
+ }
+ var value = IteratorValue(next); // step 4.c
+ try {
+ Call(fn, void undefined, [value, counter]); // step 4.d
+ } catch (e) {
+ IteratorClose(
+ iterated['[[Iterator]]'],
+ function () { throw e; }
+ ); // steps 4.e
+ throw e;
+ } finally {
+ counter += 1; // step 4.f
+ }
+ }
+};
diff --git a/Iterator.prototype.forEach/index.js b/Iterator.prototype.forEach/index.js
new file mode 100644
index 0000000..751f5fb
--- /dev/null
+++ b/Iterator.prototype.forEach/index.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var callBind = require('call-bind');
+
+var implementation = require('./implementation');
+var getPolyfill = require('./polyfill');
+var shim = require('./shim');
+
+var polyfill = callBind(getPolyfill());
+
+define(polyfill, {
+ getPolyfill: getPolyfill,
+ implementation: implementation,
+ shim: shim
+});
+
+module.exports = polyfill;
diff --git a/Iterator.prototype.forEach/polyfill.js b/Iterator.prototype.forEach/polyfill.js
new file mode 100644
index 0000000..ad11ec7
--- /dev/null
+++ b/Iterator.prototype.forEach/polyfill.js
@@ -0,0 +1,9 @@
+'use strict';
+
+var implementation = require('./implementation');
+
+module.exports = function getPolyfill() {
+ return typeof Iterator === 'function' && typeof Iterator.prototype.forEach === 'function'
+ ? Iterator.prototype.forEach
+ : implementation;
+};
diff --git a/Iterator.prototype.forEach/shim.js b/Iterator.prototype.forEach/shim.js
new file mode 100644
index 0000000..6078502
--- /dev/null
+++ b/Iterator.prototype.forEach/shim.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var getPolyfill = require('./polyfill');
+
+var $IteratorPrototype = require('iterator.prototype');
+
+module.exports = function shimIteratorPrototypeForEach() {
+ var polyfill = getPolyfill();
+
+ define(
+ $IteratorPrototype,
+ { forEach: polyfill },
+ { forEach: function () { return $IteratorPrototype.forEach !== polyfill; } }
+ );
+
+ return polyfill;
+};
diff --git a/Iterator.prototype.map/auto.js b/Iterator.prototype.map/auto.js
new file mode 100644
index 0000000..8ebf606
--- /dev/null
+++ b/Iterator.prototype.map/auto.js
@@ -0,0 +1,3 @@
+'use strict';
+
+require('./shim')();
diff --git a/Iterator.prototype.map/implementation.js b/Iterator.prototype.map/implementation.js
new file mode 100644
index 0000000..acf53f0
--- /dev/null
+++ b/Iterator.prototype.map/implementation.js
@@ -0,0 +1,57 @@
+'use strict';
+
+var GetIntrinsic = require('get-intrinsic');
+
+var $TypeError = GetIntrinsic('%TypeError%');
+
+var Call = require('es-abstract/2022/Call');
+var IsCallable = require('es-abstract/2022/IsCallable');
+var IteratorClose = require('es-abstract/2022/IteratorClose');
+var IteratorStep = require('es-abstract/2022/IteratorStep');
+var IteratorValue = require('es-abstract/2022/IteratorValue');
+
+var GetIteratorDirect = require('../aos/GetIteratorDirect');
+var CreateIteratorFromClosure = require('../aos/CreateIteratorFromClosure');
+
+var iterHelperProto = require('../IteratorHelperPrototype');
+
+var SLOT = require('internal-slot');
+
+module.exports = function map(mapper) {
+ var iterated = GetIteratorDirect(this); // step 1
+
+ if (!IsCallable(mapper)) {
+ throw new $TypeError('`mapper` must be a function'); // step 2
+ }
+
+ var sentinel = {};
+ var closure = function () {
+ var counter = 0; // step 3.a
+ // while (true) { // step 3.b
+ var next = IteratorStep(iterated['[[Iterator]]']); // step 3.b.i
+ if (!next) {
+ // return void undefined; // step 3.b.ii
+ return sentinel;
+ }
+ var value = IteratorValue(next); // step 3.b.iii
+ var mapped;
+ try {
+ mapped = Call(mapper, void undefined, [value, counter]); // step 3.b.iv
+ // yield mapped // step 3.b.vi
+ return mapped;
+ } catch (e) {
+ // close iterator // step 3.b.v, 3.b.vii
+ IteratorClose(
+ iterated['[[Iterator]]'],
+ function () { throw e; }
+ );
+ throw e;
+ } finally {
+ counter += 1; // step 3.b.viii
+ }
+ // }
+ };
+ SLOT.set(closure, '[[Sentinel]]', sentinel); // for the userland implementation
+
+ return CreateIteratorFromClosure(closure, 'Iterator Helper', iterHelperProto); // step 4
+};
diff --git a/Iterator.prototype.map/index.js b/Iterator.prototype.map/index.js
new file mode 100644
index 0000000..751f5fb
--- /dev/null
+++ b/Iterator.prototype.map/index.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var callBind = require('call-bind');
+
+var implementation = require('./implementation');
+var getPolyfill = require('./polyfill');
+var shim = require('./shim');
+
+var polyfill = callBind(getPolyfill());
+
+define(polyfill, {
+ getPolyfill: getPolyfill,
+ implementation: implementation,
+ shim: shim
+});
+
+module.exports = polyfill;
diff --git a/Iterator.prototype.map/polyfill.js b/Iterator.prototype.map/polyfill.js
new file mode 100644
index 0000000..0ee18c6
--- /dev/null
+++ b/Iterator.prototype.map/polyfill.js
@@ -0,0 +1,9 @@
+'use strict';
+
+var implementation = require('./implementation');
+
+module.exports = function getPolyfill() {
+ return typeof Iterator === 'function' && typeof Iterator.prototype.map === 'function'
+ ? Iterator.prototype.map
+ : implementation;
+};
diff --git a/Iterator.prototype.map/shim.js b/Iterator.prototype.map/shim.js
new file mode 100644
index 0000000..ad9b0c0
--- /dev/null
+++ b/Iterator.prototype.map/shim.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var getPolyfill = require('./polyfill');
+
+var $IteratorPrototype = require('iterator.prototype');
+
+module.exports = function shimIteratorPrototypeMap() {
+ var polyfill = getPolyfill();
+
+ define(
+ $IteratorPrototype,
+ { map: polyfill },
+ { map: function () { return $IteratorPrototype.map !== polyfill; } }
+ );
+
+ return polyfill;
+};
diff --git a/Iterator.prototype.reduce/auto.js b/Iterator.prototype.reduce/auto.js
new file mode 100644
index 0000000..8ebf606
--- /dev/null
+++ b/Iterator.prototype.reduce/auto.js
@@ -0,0 +1,3 @@
+'use strict';
+
+require('./shim')();
diff --git a/Iterator.prototype.reduce/implementation.js b/Iterator.prototype.reduce/implementation.js
new file mode 100644
index 0000000..4089a9d
--- /dev/null
+++ b/Iterator.prototype.reduce/implementation.js
@@ -0,0 +1,56 @@
+'use strict';
+
+var GetIntrinsic = require('get-intrinsic');
+
+var $TypeError = GetIntrinsic('%TypeError%');
+
+var Call = require('es-abstract/2022/Call');
+var IsCallable = require('es-abstract/2022/IsCallable');
+var IteratorClose = require('es-abstract/2022/IteratorClose');
+var IteratorStep = require('es-abstract/2022/IteratorStep');
+var IteratorValue = require('es-abstract/2022/IteratorValue');
+
+var GetIteratorDirect = require('../aos/GetIteratorDirect');
+
+module.exports = function reduce(reducer) {
+ var iterated = GetIteratorDirect(this); // step 1
+
+ if (!IsCallable(reducer)) {
+ throw new $TypeError('`reducer` must be a function'); // step 2
+ }
+
+ var accumulator;
+ var counter;
+ var next;
+ if (arguments.length < 2) { // step 3
+ next = IteratorStep(iterated['[[Iterator]]']); // step 3.a
+ if (!next) {
+ throw new $TypeError('Reduce of empty iterator with no initial value'); // step 3.b
+ }
+ accumulator = IteratorValue(next); // step 3.c
+ counter = 1;
+ } else { // step 4
+ accumulator = arguments[1]; // step 4.a
+ counter = 0;
+ }
+
+ // eslint-disable-next-line no-constant-condition
+ while (true) { // step 5
+ next = IteratorStep(iterated['[[Iterator]]']); // step 5.a
+ if (!next) {
+ return accumulator; // step 5.b
+ }
+ var value = IteratorValue(next); // step 5.c
+ try {
+ var result = Call(reducer, void undefined, [accumulator, value, counter]); // step 5.d
+ accumulator = result; // step 5.f
+ } catch (e) {
+ // close iterator // step 5.e
+ IteratorClose(
+ iterated['[[Iterator]]'],
+ function () { throw e; }
+ );
+ }
+ counter += 1; // step 5.g
+ }
+};
diff --git a/Iterator.prototype.reduce/index.js b/Iterator.prototype.reduce/index.js
new file mode 100644
index 0000000..751f5fb
--- /dev/null
+++ b/Iterator.prototype.reduce/index.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var callBind = require('call-bind');
+
+var implementation = require('./implementation');
+var getPolyfill = require('./polyfill');
+var shim = require('./shim');
+
+var polyfill = callBind(getPolyfill());
+
+define(polyfill, {
+ getPolyfill: getPolyfill,
+ implementation: implementation,
+ shim: shim
+});
+
+module.exports = polyfill;
diff --git a/Iterator.prototype.reduce/polyfill.js b/Iterator.prototype.reduce/polyfill.js
new file mode 100644
index 0000000..9597e1a
--- /dev/null
+++ b/Iterator.prototype.reduce/polyfill.js
@@ -0,0 +1,9 @@
+'use strict';
+
+var implementation = require('./implementation');
+
+module.exports = function getPolyfill() {
+ return typeof Iterator === 'function' && typeof Iterator.prototype.reduce === 'function'
+ ? Iterator.prototype.reduce
+ : implementation;
+};
diff --git a/Iterator.prototype.reduce/shim.js b/Iterator.prototype.reduce/shim.js
new file mode 100644
index 0000000..fda3776
--- /dev/null
+++ b/Iterator.prototype.reduce/shim.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var getPolyfill = require('./polyfill');
+
+var $IteratorPrototype = require('iterator.prototype');
+
+module.exports = function shimIteratorPrototypeReduce() {
+ var polyfill = getPolyfill();
+
+ define(
+ $IteratorPrototype,
+ { reduce: polyfill },
+ { reduce: function () { return $IteratorPrototype.reduce !== polyfill; } }
+ );
+
+ return polyfill;
+};
diff --git a/Iterator.prototype.some/auto.js b/Iterator.prototype.some/auto.js
new file mode 100644
index 0000000..8ebf606
--- /dev/null
+++ b/Iterator.prototype.some/auto.js
@@ -0,0 +1,3 @@
+'use strict';
+
+require('./shim')();
diff --git a/Iterator.prototype.some/implementation.js b/Iterator.prototype.some/implementation.js
new file mode 100644
index 0000000..6a008de
--- /dev/null
+++ b/Iterator.prototype.some/implementation.js
@@ -0,0 +1,51 @@
+'use strict';
+
+var GetIntrinsic = require('get-intrinsic');
+
+var $TypeError = GetIntrinsic('%TypeError%');
+
+var Call = require('es-abstract/2022/Call');
+var IsCallable = require('es-abstract/2022/IsCallable');
+var IteratorClose = require('es-abstract/2022/IteratorClose');
+var IteratorStep = require('es-abstract/2022/IteratorStep');
+var IteratorValue = require('es-abstract/2022/IteratorValue');
+var ToBoolean = require('es-abstract/2022/ToBoolean');
+
+var GetIteratorDirect = require('../aos/GetIteratorDirect');
+
+module.exports = function some(predicate) {
+ var iterated = GetIteratorDirect(this); // step 1
+
+ if (!IsCallable(predicate)) {
+ throw new $TypeError('`predicate` must be a function'); // step 2
+ }
+
+ var counter = 0; // step 3
+
+ // eslint-disable-next-line no-constant-condition
+ while (true) { // step 4
+ var next = IteratorStep(iterated['[[Iterator]]']); // step 4.a
+ if (!next) {
+ return false; // step 4.b
+ }
+ var value = IteratorValue(next); // step 4.c
+ var result;
+ try {
+ result = Call(predicate, void undefined, [value, counter]); // step 4.d
+ } catch (e) {
+ // close iterator // step 4.e
+ IteratorClose(
+ iterated['[[Iterator]]'],
+ function () { throw e; }
+ );
+ } finally {
+ counter += 1; // step 4.g
+ }
+ if (ToBoolean(result)) {
+ return IteratorClose(
+ iterated['[[Iterator]]'],
+ function () { return true; }
+ ); // step 4.f
+ }
+ }
+};
diff --git a/Iterator.prototype.some/index.js b/Iterator.prototype.some/index.js
new file mode 100644
index 0000000..751f5fb
--- /dev/null
+++ b/Iterator.prototype.some/index.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var callBind = require('call-bind');
+
+var implementation = require('./implementation');
+var getPolyfill = require('./polyfill');
+var shim = require('./shim');
+
+var polyfill = callBind(getPolyfill());
+
+define(polyfill, {
+ getPolyfill: getPolyfill,
+ implementation: implementation,
+ shim: shim
+});
+
+module.exports = polyfill;
diff --git a/Iterator.prototype.some/polyfill.js b/Iterator.prototype.some/polyfill.js
new file mode 100644
index 0000000..2e4c7af
--- /dev/null
+++ b/Iterator.prototype.some/polyfill.js
@@ -0,0 +1,9 @@
+'use strict';
+
+var implementation = require('./implementation');
+
+module.exports = function getPolyfill() {
+ return typeof Iterator === 'function' && typeof Iterator.prototype.some === 'function'
+ ? Iterator.prototype.some
+ : implementation;
+};
diff --git a/Iterator.prototype.some/shim.js b/Iterator.prototype.some/shim.js
new file mode 100644
index 0000000..61f41d6
--- /dev/null
+++ b/Iterator.prototype.some/shim.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var getPolyfill = require('./polyfill');
+
+var $IteratorPrototype = require('iterator.prototype');
+
+module.exports = function shimIteratorPrototypeSome() {
+ var polyfill = getPolyfill();
+
+ define(
+ $IteratorPrototype,
+ { some: polyfill },
+ { some: function () { return $IteratorPrototype.some !== polyfill; } }
+ );
+
+ return polyfill;
+};
diff --git a/Iterator.prototype.take/auto.js b/Iterator.prototype.take/auto.js
new file mode 100644
index 0000000..8ebf606
--- /dev/null
+++ b/Iterator.prototype.take/auto.js
@@ -0,0 +1,3 @@
+'use strict';
+
+require('./shim')();
diff --git a/Iterator.prototype.take/implementation.js b/Iterator.prototype.take/implementation.js
new file mode 100644
index 0000000..dff6444
--- /dev/null
+++ b/Iterator.prototype.take/implementation.js
@@ -0,0 +1,62 @@
+'use strict';
+
+var GetIntrinsic = require('get-intrinsic');
+
+var $RangeError = GetIntrinsic('%RangeError%');
+
+var IteratorClose = require('es-abstract/2022/IteratorClose');
+var IteratorStep = require('es-abstract/2022/IteratorStep');
+var IteratorValue = require('es-abstract/2022/IteratorValue');
+var ToIntegerOrInfinity = require('es-abstract/2022/ToIntegerOrInfinity');
+var ToNumber = require('es-abstract/2022/ToNumber');
+
+var GetIteratorDirect = require('../aos/GetIteratorDirect');
+var CreateIteratorFromClosure = require('../aos/CreateIteratorFromClosure');
+
+var iterHelperProto = require('../IteratorHelperPrototype');
+
+var isNaN = require('es-abstract/helpers/isNaN');
+
+var SLOT = require('internal-slot');
+
+module.exports = function take(limit) {
+ var iterated = GetIteratorDirect(this); // step 1
+
+ var numLimit = ToNumber(limit); // step 2
+ if (isNaN(numLimit)) {
+ throw new $RangeError('`limit` must be a non-NaN number'); // step 3
+ }
+
+ var integerLimit = ToIntegerOrInfinity(numLimit); // step 4
+ if (integerLimit < 0) {
+ throw new $RangeError('`limit` must be a >= 0'); // step 5
+ }
+
+ var sentinel = {};
+ var remaining = integerLimit; // step 6.a
+ var closure = function () { // step 6
+ // while (true) { // step 6.b
+ if (remaining === 0) { // step 6.b.i
+ return IteratorClose( // step 6.b.i.1
+ iterated,
+ function () { return sentinel; }
+ );
+ }
+ if (remaining !== Infinity) { // step 6.b.ii
+ remaining -= 1; // step 6.b.ii.1
+ }
+
+ var next = IteratorStep(iterated['[[Iterator]]']); // step 6.b.iii
+ if (!next) {
+ // return void undefined; // step 6.b.iv
+ return sentinel;
+ }
+
+ var value = IteratorValue(next); // step 3.b.iii
+ return value; // step 3.b.iv
+ // }
+ };
+ SLOT.set(closure, '[[Sentinel]]', sentinel); // for the userland implementation
+
+ return CreateIteratorFromClosure(closure, 'Iterator Helper', iterHelperProto); // step 4
+};
diff --git a/Iterator.prototype.take/index.js b/Iterator.prototype.take/index.js
new file mode 100644
index 0000000..751f5fb
--- /dev/null
+++ b/Iterator.prototype.take/index.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var callBind = require('call-bind');
+
+var implementation = require('./implementation');
+var getPolyfill = require('./polyfill');
+var shim = require('./shim');
+
+var polyfill = callBind(getPolyfill());
+
+define(polyfill, {
+ getPolyfill: getPolyfill,
+ implementation: implementation,
+ shim: shim
+});
+
+module.exports = polyfill;
diff --git a/Iterator.prototype.take/polyfill.js b/Iterator.prototype.take/polyfill.js
new file mode 100644
index 0000000..3d37a44
--- /dev/null
+++ b/Iterator.prototype.take/polyfill.js
@@ -0,0 +1,9 @@
+'use strict';
+
+var implementation = require('./implementation');
+
+module.exports = function getPolyfill() {
+ return typeof Iterator === 'function' && typeof Iterator.prototype.take === 'function'
+ ? Iterator.prototype.take
+ : implementation;
+};
diff --git a/Iterator.prototype.take/shim.js b/Iterator.prototype.take/shim.js
new file mode 100644
index 0000000..50cf667
--- /dev/null
+++ b/Iterator.prototype.take/shim.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var getPolyfill = require('./polyfill');
+
+var $IteratorPrototype = require('iterator.prototype');
+
+module.exports = function shimIteratorPrototypeTake() {
+ var polyfill = getPolyfill();
+
+ define(
+ $IteratorPrototype,
+ { take: polyfill },
+ { take: function () { return $IteratorPrototype.take !== polyfill; } }
+ );
+
+ return polyfill;
+};
diff --git a/Iterator.prototype.toArray/auto.js b/Iterator.prototype.toArray/auto.js
new file mode 100644
index 0000000..8ebf606
--- /dev/null
+++ b/Iterator.prototype.toArray/auto.js
@@ -0,0 +1,3 @@
+'use strict';
+
+require('./shim')();
diff --git a/Iterator.prototype.toArray/implementation.js b/Iterator.prototype.toArray/implementation.js
new file mode 100644
index 0000000..eb0e26f
--- /dev/null
+++ b/Iterator.prototype.toArray/implementation.js
@@ -0,0 +1,26 @@
+'use strict';
+
+var IteratorStep = require('es-abstract/2022/IteratorStep');
+var IteratorValue = require('es-abstract/2022/IteratorValue');
+
+var GetIteratorDirect = require('../aos/GetIteratorDirect');
+
+var callBound = require('call-bind/callBound');
+
+var $push = callBound('Array.prototype.push');
+
+module.exports = function toArray() {
+ var iterated = GetIteratorDirect(this); // step 1
+
+ var items = []; // step 2
+
+ // eslint-disable-next-line no-constant-condition
+ while (true) { // step 3
+ var next = IteratorStep(iterated['[[Iterator]]']); // step 3.a
+ if (!next) {
+ return items; // step 3.b
+ }
+ var value = IteratorValue(next); // step 3.c
+ $push(items, value); // step 3.d
+ }
+};
diff --git a/Iterator.prototype.toArray/index.js b/Iterator.prototype.toArray/index.js
new file mode 100644
index 0000000..751f5fb
--- /dev/null
+++ b/Iterator.prototype.toArray/index.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var callBind = require('call-bind');
+
+var implementation = require('./implementation');
+var getPolyfill = require('./polyfill');
+var shim = require('./shim');
+
+var polyfill = callBind(getPolyfill());
+
+define(polyfill, {
+ getPolyfill: getPolyfill,
+ implementation: implementation,
+ shim: shim
+});
+
+module.exports = polyfill;
diff --git a/Iterator.prototype.toArray/polyfill.js b/Iterator.prototype.toArray/polyfill.js
new file mode 100644
index 0000000..5bb92ba
--- /dev/null
+++ b/Iterator.prototype.toArray/polyfill.js
@@ -0,0 +1,9 @@
+'use strict';
+
+var implementation = require('./implementation');
+
+module.exports = function getPolyfill() {
+ return typeof Iterator === 'function' && typeof Iterator.prototype.toArray === 'function'
+ ? Iterator.prototype.toArray
+ : implementation;
+};
diff --git a/Iterator.prototype.toArray/shim.js b/Iterator.prototype.toArray/shim.js
new file mode 100644
index 0000000..a8b5cf1
--- /dev/null
+++ b/Iterator.prototype.toArray/shim.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var getPolyfill = require('./polyfill');
+
+var $IteratorPrototype = require('iterator.prototype');
+
+module.exports = function shimIteratorPrototypeToArray() {
+ var polyfill = getPolyfill();
+
+ define(
+ $IteratorPrototype,
+ { toArray: polyfill },
+ { toArray: function () { return $IteratorPrototype.toArray !== polyfill; } }
+ );
+
+ return polyfill;
+};
diff --git a/Iterator/auto.js b/Iterator/auto.js
new file mode 100644
index 0000000..8ebf606
--- /dev/null
+++ b/Iterator/auto.js
@@ -0,0 +1,3 @@
+'use strict';
+
+require('./shim')();
diff --git a/Iterator/implementation.js b/Iterator/implementation.js
new file mode 100644
index 0000000..79decab
--- /dev/null
+++ b/Iterator/implementation.js
@@ -0,0 +1,11 @@
+'use strict';
+
+var iterProto = require('iterator.prototype');
+
+var $Iterator = typeof Iterator === 'function' ? Iterator : function Iterator() {};
+
+if ($Iterator.prototype !== iterProto) {
+ $Iterator.prototype = iterProto;
+}
+
+module.exports = $Iterator;
diff --git a/Iterator/index.js b/Iterator/index.js
new file mode 100644
index 0000000..751f5fb
--- /dev/null
+++ b/Iterator/index.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var callBind = require('call-bind');
+
+var implementation = require('./implementation');
+var getPolyfill = require('./polyfill');
+var shim = require('./shim');
+
+var polyfill = callBind(getPolyfill());
+
+define(polyfill, {
+ getPolyfill: getPolyfill,
+ implementation: implementation,
+ shim: shim
+});
+
+module.exports = polyfill;
diff --git a/Iterator/polyfill.js b/Iterator/polyfill.js
new file mode 100644
index 0000000..e89c026
--- /dev/null
+++ b/Iterator/polyfill.js
@@ -0,0 +1,8 @@
+'use strict';
+
+var globalThis = require('globalthis')();
+var implementation = require('./implementation');
+
+module.exports = function getPolyfill() {
+ return typeof globalThis.Iterator === 'function' ? globalThis.Iterator : implementation;
+};
diff --git a/Iterator/shim.js b/Iterator/shim.js
new file mode 100644
index 0000000..be51a07
--- /dev/null
+++ b/Iterator/shim.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var define = require('define-properties');
+var globalThis = require('globalthis')();
+
+var getPolyfill = require('./polyfill');
+
+module.exports = function shimIterator() {
+ var polyfill = getPolyfill();
+
+ define(
+ globalThis,
+ { Iterator: polyfill },
+ { Iterator: function () { return Iterator !== polyfill; } }
+ );
+
+ return polyfill;
+};
diff --git a/IteratorHelperPrototype/index.js b/IteratorHelperPrototype/index.js
new file mode 100644
index 0000000..bb18102
--- /dev/null
+++ b/IteratorHelperPrototype/index.js
@@ -0,0 +1,39 @@
+'use strict';
+
+var setToStringTag = require('es-set-tostringtag');
+var hasProto = require('has-proto')();
+
+var CompletionRecord = require('es-abstract/2022/CompletionRecord');
+var GeneratorResume = require('../aos/GeneratorResume');
+var GeneratorResumeAbrupt = require('../aos/GeneratorResumeAbrupt');
+
+var iterProto = require('iterator.prototype');
+
+var implementation;
+if (hasProto) {
+ implementation = {
+ __proto__: iterProto,
+ next: function next() {
+ return GeneratorResume(this, void undefined, 'Iterator Helper');
+ },
+ 'return': function () {
+ var C = new CompletionRecord('return', void undefined); // step 1
+ return GeneratorResumeAbrupt(this, C, 'Iterator Helper');
+ }
+ };
+ setToStringTag(implementation, 'Iterator Helper');
+} else {
+ var IteratorHelper = function IteratorHelper() {};
+ IteratorHelper.prototype = iterProto;
+ implementation = new IteratorHelper();
+ delete implementation.constructor;
+ implementation.next = function next() {
+ return GeneratorResume(this, void undefined, 'Iterator Helper');
+ };
+ implementation['return'] = function () {
+ var C = function () {}; // step 1
+ return GeneratorResumeAbrupt(this, C, 'Iterator Helper');
+ };
+}
+
+module.exports = implementation;
diff --git a/README.md b/README.md
index 3ebe7ef..f986698 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,87 @@
-# iterator-helpers
-An ESnext spec-compliant iterator helpers shim/polyfill/replacement that works as far down as ES3.
+# es-iterator-helpers [![Version Badge][npm-version-svg]][package-url]
+
+[![github actions][actions-image]][actions-url]
+[![coverage][codecov-image]][codecov-url]
+[![License][license-image]][license-url]
+[![Downloads][downloads-image]][downloads-url]
+
+[![npm badge][npm-badge-png]][package-url]
+
+An ESnext spec-compliant sync iterator helpers shim/polyfill/replacement that works as far down as ES3.
+
+This package implements the [es-shim API](https://github.com/es-shims/api) “multi” interface. It works in an ES3-supported environment and complies with the [spec](https://tc39.es/ecma262/#sec-additional-properties-of-the-string.prototype-object).
+
+Because the `Iterator.prototype` methods depend on a receiver (the `this` value), the main export in each subdirectory takes the string to operate on as the first argument.
+
+The main export of the package itself is simply an array of the available directory names. It’s sole intended use is for build tooling and testing.
+
+## Supported things
+
+ - [`Iterator` constructor](https://tc39.es/proposal-iterator-helpers/#sec-iterator-constructor)
+ - [`Iterator.from`](https://tc39.es/proposal-iterator-helpers/#sec-iterator.from)
+ - [`Iterator.prototype.constructor`](https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.constructor)
+ - [`Iterator.prototype.drop`](https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.drop)
+ - [`Iterator.prototype.every`](https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.every)
+ - [`Iterator.prototype.filter`](https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.filter)
+ - [`Iterator.prototype.find`](https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.find)
+ - [`Iterator.prototype.flatMap`](https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.flatmap)
+ - [`Iterator.prototype.forEach`](https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.foreach)
+ - [`Iterator.prototype.map`](https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.map)
+ - [`Iterator.prototype.reduce`](https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.reduce)
+ - [`Iterator.prototype.some`](https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.some)
+ - [`Iterator.prototype.take`](https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.take)
+ - [`Iterator.prototype.toArray`](https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.toarray)
+
+## Getting started
+
+```sh
+npm install --save es-iterator-helpers
+```
+
+## Usage/Examples
+
+```js
+const map = require('es-iterator-helpers/Iterator.prototype.map');
+const toArray = require('es-iterator-helpers/Iterator.prototype.toArray');
+const assert = require('assert');
+
+const iterator = [1, 2, 3].values();
+
+const mapped = map(iterator, (x) => x + 10);
+assert.deepEqual(
+ mapped.next(),
+ {
+ done: false,
+ value: 11,
+ }
+);
+assert.deepEqual(
+ toArray(mapped),
+ [12, 13]
+);
+```
+
+```js
+require('./auto'); // shim all of the methods
+
+require('./Iterator.prototype.map/auto'); // shim the “map” method
+```
+
+## Tests
+Simply clone the repo, `npm install`, and run `npm test`
+
+[package-url]: https://npmjs.org/package/es-iterator-helpers
+[npm-version-svg]: https://versionbadg.es/es-shims/iterator-helpers.svg
+[deps-svg]: https://david-dm.org/es-shims/iterator-helpers.svg
+[deps-url]: https://david-dm.org/es-shims/iterator-helpers
+[dev-deps-svg]: https://david-dm.org/es-shims/iterator-helpers/dev-status.svg
+[dev-deps-url]: https://david-dm.org/es-shims/iterator-helpers#info=devDependencies
+[npm-badge-png]: https://nodei.co/npm/es-iterator-helpers.png?downloads=true&stars=true
+[license-image]: https://img.shields.io/npm/l/es-iterator-helpers.svg
+[license-url]: LICENSE
+[downloads-image]: https://img.shields.io/npm/dm/es-iterator-helpers.svg
+[downloads-url]: https://npm-stat.com/charts.html?package=es-iterator-helpers
+[codecov-image]: https://codecov.io/gh/es-shims/iterator-helpers/branch/main/graphs/badge.svg
+[codecov-url]: https://app.codecov.io/gh/es-shims/iterator-helpers/
+[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/es-shims/iterator-helpers
+[actions-url]: https://github.com/es-shims/iterator-helpers/actions
diff --git a/WrapForValidIteratorPrototype/index.js b/WrapForValidIteratorPrototype/index.js
new file mode 100644
index 0000000..fac3992
--- /dev/null
+++ b/WrapForValidIteratorPrototype/index.js
@@ -0,0 +1,48 @@
+'use strict';
+
+var GetIntrinsic = require('get-intrinsic');
+
+var $TypeError = GetIntrinsic('%TypeError%');
+
+var Call = require('es-abstract/2022/Call');
+var CreateIterResultObject = require('es-abstract/2022/CreateIterResultObject');
+var GetMethod = require('es-abstract/2022/GetMethod');
+var Type = require('es-abstract/2022/Type');
+
+var SLOT = require('internal-slot');
+var iterProto = require('iterator.prototype');
+
+// https://tc39.es/proposal-iterator-helpers/#sec-wrapforvaliditeratorprototype-object
+
+module.exports = /* GetIntrinsic('%WrapForValidIteratorPrototype%', true) || */ {
+ __proto__: iterProto,
+ next: function next() {
+ var O = this; // step 1
+
+ // RequireInternalSlot(O, [[Iterated]]); // step 2
+ SLOT.assert(O, '[[Iterated]]');
+
+ var iteratorRecord = SLOT.get(O, '[[Iterated]]'); // step 3
+
+ return Call(iteratorRecord['[[NextMethod]]'], iteratorRecord['[[Iterator]]']); // step 4
+ },
+ 'return': function () {
+ var O = this; // step 1
+
+ // RequireInternalSlot(O, [[Iterated]]); // step 2
+ SLOT.assert(O, '[[Iterated]]');
+
+ var iterator = SLOT.get(O, '[[Iterated]]')['[[Iterator]]']; // step 3
+
+ if (Type(iterator) !== 'Object') {
+ throw new $TypeError('iterator must be an Object'); // step 4
+ }
+
+ var returnMethod = GetMethod(iterator, 'return'); // step 5
+
+ if (typeof returnMethod === 'undefined') { // step 6
+ return CreateIterResultObject(undefined, true); // step 6.a
+ }
+ return Call(returnMethod, iterator); // step 7
+ }
+};
diff --git a/aos/CreateIteratorFromClosure.js b/aos/CreateIteratorFromClosure.js
new file mode 100644
index 0000000..3f0a6eb
--- /dev/null
+++ b/aos/CreateIteratorFromClosure.js
@@ -0,0 +1,27 @@
+'use strict';
+
+var GetIntrinsic = require('get-intrinsic');
+
+var $TypeError = GetIntrinsic('%TypeError%');
+
+var IsCallable = require('es-abstract/2022/IsCallable');
+var OrdinaryObjectCreate = require('es-abstract/2022/OrdinaryObjectCreate');
+
+var GeneratorStart = require('./GeneratorStart');
+
+var SLOT = require('internal-slot');
+
+module.exports = function CreateIteratorFromClosure(closure, brand, proto) {
+ if (!IsCallable(closure)) {
+ throw new $TypeError('`closure` must be a function');
+ }
+ var generator = OrdinaryObjectCreate(proto, ['[[GeneratorContext]]', '[[GeneratorBrand]]', '[[GeneratorState]]']); // steps 3, 5
+ SLOT.set(generator, '[[GeneratorBrand]]', brand); // step 4
+
+ SLOT.assert(closure, '[[Sentinel]]'); // our userland slot
+ SLOT.set(generator, '[[Sentinel]]'); // our userland slot
+
+ GeneratorStart(generator, closure); // step 13
+
+ return generator; // step 15
+};
diff --git a/aos/GeneratorResume.js b/aos/GeneratorResume.js
new file mode 100644
index 0000000..96522b7
--- /dev/null
+++ b/aos/GeneratorResume.js
@@ -0,0 +1,30 @@
+'use strict';
+
+var GetIntrinsic = require('get-intrinsic');
+
+var $TypeError = GetIntrinsic('%TypeError%');
+
+var CreateIterResultObject = require('es-abstract/2022/CreateIterResultObject');
+
+var GeneratorValidate = require('./GeneratorValidate');
+
+var SLOT = require('internal-slot');
+
+module.exports = function GeneratorResume(generator, value, generatorBrand) {
+ var state = GeneratorValidate(generator, generatorBrand); // step 1
+ if (state === 'completed') {
+ return CreateIterResultObject(void undefined, true); // step 2
+ }
+
+ if (state !== 'suspendedStart' && state !== 'suspendedYield') {
+ throw new $TypeError('Assertion failed: generator state is unexpected: ' + state); // step 3
+ }
+
+ var genContext = SLOT.get(generator, '[[GeneratorContext]]');
+
+ SLOT.set(generator, '[[GeneratorState]]', 'executing'); // step 7
+
+ var result = genContext(value); // steps 5-6, 8-10
+
+ return result;
+};
diff --git a/aos/GeneratorResumeAbrupt.js b/aos/GeneratorResumeAbrupt.js
new file mode 100644
index 0000000..d703a3a
--- /dev/null
+++ b/aos/GeneratorResumeAbrupt.js
@@ -0,0 +1,44 @@
+'use strict';
+
+var GetIntrinsic = require('get-intrinsic');
+
+var $TypeError = GetIntrinsic('%TypeError%');
+
+var CompletionRecord = require('es-abstract/2022/CompletionRecord');
+var CreateIterResultObject = require('es-abstract/2022/CreateIterResultObject');
+
+var GeneratorValidate = require('./GeneratorValidate');
+
+var SLOT = require('internal-slot');
+
+module.exports = function GeneratorResumeAbrupt(generator, abruptCompletion, generatorBrand) {
+ if (!(abruptCompletion instanceof CompletionRecord)) {
+ throw new $TypeError('Assertion failed: abruptCompletion must be a Completion Record');
+ }
+
+ var state = GeneratorValidate(generator, generatorBrand); // step 1
+
+ if (state === 'suspendedStart') { // step 2
+ SLOT.set(generator, '[[GeneratorState]]', 'completed'); // step 3.a
+ SLOT.set(generator, '[[GeneratorContext]]', null); // step 3.b
+ state = 'completed'; // step 3.c
+ }
+
+ var value = abruptCompletion.value();
+
+ if (state === 'completed') { // step 3
+ return CreateIterResultObject(value, true); // steps 3.a-b
+ }
+
+ if (state !== 'suspendedYield') {
+ throw new $TypeError('Assertion failed: generator state is unexpected: ' + state); // step 4
+ }
+
+ var genContext = SLOT.get(generator, '[[GeneratorContext]]'); // step 5
+
+ SLOT.set(generator, '[[GeneratorState]]', 'executing'); // step 8
+
+ var result = genContext(value); // steps 6-7, 8-11
+
+ return result; // step 12
+};
diff --git a/aos/GeneratorStart.js b/aos/GeneratorStart.js
new file mode 100644
index 0000000..da4341d
--- /dev/null
+++ b/aos/GeneratorStart.js
@@ -0,0 +1,45 @@
+'use strict';
+
+var GetIntrinsic = require('get-intrinsic');
+
+var $TypeError = GetIntrinsic('%TypeError%');
+
+var CreateIterResultObject = require('es-abstract/2022/CreateIterResultObject');
+var IsCallable = require('es-abstract/2022/IsCallable');
+var Type = require('es-abstract/2022/Type');
+
+var SLOT = require('internal-slot');
+
+module.exports = function GeneratorStart(generator, closure) {
+ SLOT.assert(generator, '[[GeneratorState]]');
+ SLOT.assert(generator, '[[GeneratorContext]]');
+ SLOT.assert(generator, '[[GeneratorBrand]]');
+ SLOT.assert(generator, '[[Sentinel]]'); // our userland slot
+
+ if (!IsCallable(closure) || closure.length !== 0) {
+ throw new $TypeError('`closure` must be a function that takes no arguments');
+ }
+
+ var sentinel = SLOT.get(closure, '[[Sentinel]]');
+ if (Type(sentinel) !== 'Object') {
+ throw new $TypeError('`closure.[[Sentinel]]` must be an object');
+ }
+ SLOT.set(generator, '[[GeneratorContext]]', function () { // steps 2-5
+ try {
+ var result = closure();
+ if (result === sentinel) {
+ SLOT.set(generator, '[[GeneratorState]]', 'completed');
+ SLOT.set(generator, '[[GeneratorContext]]', null);
+ return CreateIterResultObject(void undefined, true);
+ }
+ SLOT.set(generator, '[[GeneratorState]]', 'suspendedYield');
+ return CreateIterResultObject(result, false);
+ } catch (e) {
+ SLOT.set(generator, '[[GeneratorState]]', 'completed');
+ SLOT.set(generator, '[[GeneratorContext]]', null);
+ throw e;
+ }
+ });
+
+ SLOT.set(generator, '[[GeneratorState]]', 'suspendedStart'); // step 6
+};
diff --git a/aos/GeneratorValidate.js b/aos/GeneratorValidate.js
new file mode 100644
index 0000000..e02b1c3
--- /dev/null
+++ b/aos/GeneratorValidate.js
@@ -0,0 +1,24 @@
+'use strict';
+
+var GetIntrinsic = require('get-intrinsic');
+
+var $TypeError = GetIntrinsic('%TypeError%');
+
+var SLOT = require('internal-slot');
+
+module.exports = function GeneratorValidate(generator, generatorBrand) {
+ SLOT.assert(generator, '[[GeneratorState]]'); // step 1
+ SLOT.assert(generator, '[[GeneratorBrand]]'); // step 2
+
+ var brand = SLOT.get(generator, '[[GeneratorBrand]]');
+ if (brand !== generatorBrand) {
+ throw new $TypeError('Assertion failed: generator brand is unexpected: ' + brand);
+ }
+ SLOT.assert(generator, '[[GeneratorContext]]'); // step 4
+ var state = SLOT.get(generator, '[[GeneratorState]]'); // step 5
+ if (state === 'executing') {
+ throw new $TypeError('generator is executing');
+ }
+
+ return state; // step 7
+};
diff --git a/aos/GetIteratorDirect.js b/aos/GetIteratorDirect.js
new file mode 100644
index 0000000..c010ee4
--- /dev/null
+++ b/aos/GetIteratorDirect.js
@@ -0,0 +1,25 @@
+'use strict';
+
+var GetIntrinsic = require('get-intrinsic');
+
+var $TypeError = GetIntrinsic('%TypeError%');
+
+var Get = require('es-abstract/2022/Get');
+var IsCallable = require('es-abstract/2022/IsCallable');
+var Type = require('es-abstract/2022/Type');
+
+module.exports = function GetIteratorDirect(obj) {
+ if (Type(obj) !== 'Object') {
+ throw new $TypeError('`obj` must be an Object'); // step 1
+ }
+
+ var nextMethod = Get(obj, 'next'); // step 2
+
+ if (!IsCallable(nextMethod)) {
+ throw new $TypeError('`nextMethod` must be a function'); // step 3
+ }
+
+ var iteratorRecord = { '[[Iterator]]': obj, '[[NextMethod]]': nextMethod, '[[Done]]': false }; // step 4
+
+ return iteratorRecord; // step 5
+};
diff --git a/aos/GetIteratorFlattenable.js b/aos/GetIteratorFlattenable.js
new file mode 100644
index 0000000..edc1417
--- /dev/null
+++ b/aos/GetIteratorFlattenable.js
@@ -0,0 +1,62 @@
+'use strict';
+
+var GetIntrinsic = require('get-intrinsic');
+
+var $TypeError = GetIntrinsic('%TypeError%');
+
+var Call = require('es-abstract/2022/Call');
+// var CreateAsyncFromSyncIterator = require('es-abstract/2022/CreateAsyncFromSyncIterator');
+var Get = require('es-abstract/2022/Get');
+var GetIterator = require('es-abstract/2022/GetIterator');
+var IsCallable = require('es-abstract/2022/IsCallable');
+var Type = require('es-abstract/2022/Type');
+
+var hasSymbols = require('has-symbols/shams')();
+
+module.exports = function GetIteratorFlattenable(obj, hint) {
+ if (Type(obj) !== 'Object') {
+ throw new $TypeError('obj must be an Object'); // step 1
+ }
+
+ var alreadyAsync = false; // step 2
+
+ var method = void undefined; // step 3
+
+ if (hint === 'async') { // step 4
+ method = hasSymbols && Symbol.asyncIterator && obj[Symbol.asyncIterator]; // step 4.a
+ alreadyAsync = true; // step 4.b
+ }
+
+ if (!IsCallable(method)) { // step 5
+ // method = Get(obj, Symbol.iterator); // step 5.a
+ method = function () {
+ return GetIterator(obj);
+ };
+ alreadyAsync = false; // step 5.b
+ }
+
+ var iterator;
+ if (!IsCallable(method)) { // step 6
+ iterator = obj; // step 6.a
+ alreadyAsync = true; // step 6.b
+ } else { // step 7
+ iterator = Call(method, obj); // step 7.a
+ }
+
+ if (Type(iterator) !== 'Object') {
+ throw new $TypeError('iterator must be an Object'); // step 8
+ }
+ var nextMethod = Get(iterator, 'next'); // step 9
+
+ if (!IsCallable(nextMethod)) {
+ throw new $TypeError('nextMethod must be a function'); // step 10
+ }
+
+ var iteratorRecord = { '[[Iterator]]': iterator, '[[NextMethod]]': nextMethod, '[[Done]]': false }; // step 11
+
+ if (hint === 'async' && !alreadyAsync) { // step 12
+ // return CreateAsyncFromSyncIterator(iteratorRecord); // step 12.a
+ }
+
+ return iteratorRecord;
+};
diff --git a/auto.js b/auto.js
new file mode 100644
index 0000000..8ebf606
--- /dev/null
+++ b/auto.js
@@ -0,0 +1,3 @@
+'use strict';
+
+require('./shim')();
diff --git a/index.json b/index.json
new file mode 100644
index 0000000..b1b029c
--- /dev/null
+++ b/index.json
@@ -0,0 +1,16 @@
+[
+ "Iterator",
+ "Iterator.from",
+ "Iterator.prototype.constructor",
+ "Iterator.prototype.drop",
+ "Iterator.prototype.every",
+ "Iterator.prototype.filter",
+ "Iterator.prototype.find",
+ "Iterator.prototype.flatMap",
+ "Iterator.prototype.forEach",
+ "Iterator.prototype.map",
+ "Iterator.prototype.reduce",
+ "Iterator.prototype.some",
+ "Iterator.prototype.take",
+ "Iterator.prototype.toArray"
+]
diff --git a/package.json b/package.json
index c24f7aa..606090e 100644
--- a/package.json
+++ b/package.json
@@ -1,14 +1,97 @@
{
- "name": "iterator-helpers",
+ "name": "es-iterator-helpers",
"version": "0.0.0",
"description": "An ESnext spec-compliant iterator helpers shim/polyfill/replacement that works as far down as ES3.",
- "main": "index.js",
+ "main": "index.json",
"exports": {
- ".": "./index.js",
+ ".": "./index.json",
+ "./auto": "./auto.js",
+ "./shim": "./shim.js",
+ "./Iterator": "./Iterator/index.js",
+ "./Iterator/auto": "./Iterator/auto.js",
+ "./Iterator/polyfill": "./Iterator/polyfill.js",
+ "./Iterator/implementation": "./Iterator/implementation.js",
+ "./Iterator/shim": "./Iterator/shim.js",
+ "./Iterator.from": "./Iterator.from/index.js",
+ "./Iterator.from/auto": "./Iterator.from/auto.js",
+ "./Iterator.from/polyfill": "./Iterator.from/polyfill.js",
+ "./Iterator.from/implementation": "./Iterator.from/implementation.js",
+ "./Iterator.from/shim": "./Iterator.from/shim.js",
+ "./Iterator.prototype.constructor": "./Iterator.prototype.constructor/index.js",
+ "./Iterator.prototype.constructor/auto": "./Iterator.prototype.constructor/auto.js",
+ "./Iterator.prototype.constructor/polyfill": "./Iterator.prototype.constructor/polyfill.js",
+ "./Iterator.prototype.constructor/implementation": "./Iterator.prototype.constructor/implementation.js",
+ "./Iterator.prototype.constructor/shim": "./Iterator.prototype.constructor/shim.js",
+ "./Iterator.prototype.map": "./Iterator.prototype.map/index.js",
+ "./Iterator.prototype.map/auto": "./Iterator.prototype.map/auto.js",
+ "./Iterator.prototype.map/polyfill": "./Iterator.prototype.map/polyfill.js",
+ "./Iterator.prototype.map/implementation": "./Iterator.prototype.map/implementation.js",
+ "./Iterator.prototype.map/shim": "./Iterator.prototype.map/shim.js",
+ "./Iterator.prototype.filter": "./Iterator.prototype.filter/index.js",
+ "./Iterator.prototype.filter/auto": "./Iterator.prototype.filter/auto.js",
+ "./Iterator.prototype.filter/polyfill": "./Iterator.prototype.filter/polyfill.js",
+ "./Iterator.prototype.filter/implementation": "./Iterator.prototype.filter/implementation.js",
+ "./Iterator.prototype.filter/shim": "./Iterator.prototype.filter/shim.js",
+ "./Iterator.prototype.take": "./Iterator.prototype.take/index.js",
+ "./Iterator.prototype.take/auto": "./Iterator.prototype.take/auto.js",
+ "./Iterator.prototype.take/polyfill": "./Iterator.prototype.take/polyfill.js",
+ "./Iterator.prototype.take/implementation": "./Iterator.prototype.take/implementation.js",
+ "./Iterator.prototype.take/shim": "./Iterator.prototype.take/shim.js",
+ "./Iterator.prototype.drop": "./Iterator.prototype.drop/index.js",
+ "./Iterator.prototype.drop/auto": "./Iterator.prototype.drop/auto.js",
+ "./Iterator.prototype.drop/polyfill": "./Iterator.prototype.drop/polyfill.js",
+ "./Iterator.prototype.drop/implementation": "./Iterator.prototype.drop/implementation.js",
+ "./Iterator.prototype.drop/shim": "./Iterator.prototype.drop/shim.js",
+ "./Iterator.prototype.flatMap": "./Iterator.prototype.flatMap/index.js",
+ "./Iterator.prototype.flatMap/auto": "./Iterator.prototype.flatMap/auto.js",
+ "./Iterator.prototype.flatMap/polyfill": "./Iterator.prototype.flatMap/polyfill.js",
+ "./Iterator.prototype.flatMap/implementation": "./Iterator.prototype.flatMap/implementation.js",
+ "./Iterator.prototype.flatMap/shim": "./Iterator.prototype.flatMap/shim.js",
+ "./Iterator.prototype.reduce": "./Iterator.prototype.reduce/index.js",
+ "./Iterator.prototype.reduce/auto": "./Iterator.prototype.reduce/auto.js",
+ "./Iterator.prototype.reduce/polyfill": "./Iterator.prototype.reduce/polyfill.js",
+ "./Iterator.prototype.reduce/implementation": "./Iterator.prototype.reduce/implementation.js",
+ "./Iterator.prototype.reduce/shim": "./Iterator.prototype.reduce/shim.js",
+ "./Iterator.prototype.toArray": "./Iterator.prototype.toArray/index.js",
+ "./Iterator.prototype.toArray/auto": "./Iterator.prototype.toArray/auto.js",
+ "./Iterator.prototype.toArray/polyfill": "./Iterator.prototype.toArray/polyfill.js",
+ "./Iterator.prototype.toArray/implementation": "./Iterator.prototype.toArray/implementation.js",
+ "./Iterator.prototype.toArray/shim": "./Iterator.prototype.toArray/shim.js",
+ "./Iterator.prototype.forEach": "./Iterator.prototype.forEach/index.js",
+ "./Iterator.prototype.forEach/auto": "./Iterator.prototype.forEach/auto.js",
+ "./Iterator.prototype.forEach/polyfill": "./Iterator.prototype.forEach/polyfill.js",
+ "./Iterator.prototype.forEach/implementation": "./Iterator.prototype.forEach/implementation.js",
+ "./Iterator.prototype.forEach/shim": "./Iterator.prototype.forEach/shim.js",
+ "./Iterator.prototype.some": "./Iterator.prototype.some/index.js",
+ "./Iterator.prototype.some/auto": "./Iterator.prototype.some/auto.js",
+ "./Iterator.prototype.some/polyfill": "./Iterator.prototype.some/polyfill.js",
+ "./Iterator.prototype.some/implementation": "./Iterator.prototype.some/implementation.js",
+ "./Iterator.prototype.some/shim": "./Iterator.prototype.some/shim.js",
+ "./Iterator.prototype.every": "./Iterator.prototype.every/index.js",
+ "./Iterator.prototype.every/auto": "./Iterator.prototype.every/auto.js",
+ "./Iterator.prototype.every/polyfill": "./Iterator.prototype.every/polyfill.js",
+ "./Iterator.prototype.every/implementation": "./Iterator.prototype.every/implementation.js",
+ "./Iterator.prototype.every/shim": "./Iterator.prototype.every/shim.js",
+ "./Iterator.prototype.find": "./Iterator.prototype.find/index.js",
+ "./Iterator.prototype.find/auto": "./Iterator.prototype.find/auto.js",
+ "./Iterator.prototype.find/polyfill": "./Iterator.prototype.find/polyfill.js",
+ "./Iterator.prototype.find/implementation": "./Iterator.prototype.find/implementation.js",
+ "./Iterator.prototype.find/shim": "./Iterator.prototype.find/shim.js",
"./package.json": "./package.json"
},
"scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
+ "prepack": "npmignore --auto --commentLines=autogenerated",
+ "prepublishOnly": "safe-publish-latest",
+ "prepublish": "not-in-publish || npm run prepublishOnly",
+ "prelint": "es-shim-api --bound --multi --ignore-dirs=WrapForValidIteratorPrototype,IteratorHelperPrototype",
+ "lint": "eslint --ext=js,mjs .",
+ "postlint": "evalmd README.md",
+ "pretest": "npm run lint",
+ "test": "npm run tests-only",
+ "tests-only": "nyc tape 'test/**/*.js'",
+ "posttest": "aud --production",
+ "version": "auto-changelog && git add CHANGELOG.md",
+ "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\""
},
"repository": {
"type": "git",
@@ -22,7 +105,6 @@
"es-shims",
"es-shim API",
"Iterator",
- "AsyncIterator",
"helpers",
"from",
"map",
@@ -32,7 +114,6 @@
"flatMap",
"reduce",
"toArray",
- "toAsync",
"forEach",
"some",
"every",
@@ -43,5 +124,48 @@
"bugs": {
"url": "https://github.com/es-shims/iterator-helpers/issues"
},
- "homepage": "https://github.com/es-shims/iterator-helpers#readme"
+ "homepage": "https://github.com/es-shims/iterator-helpers#readme",
+ "dependencies": {
+ "asynciterator.prototype": "^1.0.0",
+ "es-abstract": "^1.21.1",
+ "es-set-tostringtag": "^2.0.1",
+ "function-bind": "^1.1.1",
+ "globalthis": "^1.0.3",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.4",
+ "iterator.prototype": "^1.1.0"
+ },
+ "devDependencies": {
+ "@es-shims/api": "^2.3.0",
+ "@ljharb/eslint-config": "^21.0.1",
+ "aud": "^2.0.2",
+ "auto-changelog": "^2.4.0",
+ "es-value-fixtures": "^1.4.2",
+ "eslint": "=8.8.0",
+ "evalmd": "^0.0.19",
+ "for-each": "^0.3.3",
+ "functions-have-names": "^1.2.3",
+ "has-strict-mode": "^1.0.1",
+ "in-publish": "^2.0.1",
+ "iterate-iterator": "^1.0.2",
+ "npmignore": "^0.3.0",
+ "nyc": "^10.3.2",
+ "object-inspect": "^1.12.3",
+ "safe-publish-latest": "^2.0.0",
+ "tape": "^5.6.3"
+ },
+ "auto-changelog": {
+ "output": "CHANGELOG.md",
+ "template": "keepachangelog",
+ "unreleased": false,
+ "commitLimit": false,
+ "backfillLimit": false,
+ "hideCredit": true
+ },
+ "publishConfig": {
+ "ignore": [
+ ".github/workflows"
+ ]
+ }
}
diff --git a/shim.js b/shim.js
new file mode 100644
index 0000000..a0a3c27
--- /dev/null
+++ b/shim.js
@@ -0,0 +1,33 @@
+'use strict';
+
+var shimIterator = require('./Iterator/shim');
+var shimIteratorFrom = require('./Iterator.from/shim');
+var shimIteratorCtor = require('./Iterator.prototype.constructor/shim');
+var shimIteratorDrop = require('./Iterator.prototype.drop/shim');
+var shimIteratorEvery = require('./Iterator.prototype.every/shim');
+var shimIteratorFilter = require('./Iterator.prototype.filter/shim');
+var shimIteratorFind = require('./Iterator.prototype.find/shim');
+var shimIteratorFlatMap = require('./Iterator.prototype.flatMap/shim');
+var shimIteratorForEach = require('./Iterator.prototype.forEach/shim');
+var shimIteratorMap = require('./Iterator.prototype.map/shim');
+var shimIteratorReduce = require('./Iterator.prototype.reduce/shim');
+var shimIteratorSome = require('./Iterator.prototype.some/shim');
+var shimIteratorTake = require('./Iterator.prototype.take/shim');
+var shimIteratorToArray = require('./Iterator.prototype.toArray/shim');
+
+module.exports = function shimIteratorHelpers() {
+ shimIterator();
+ shimIteratorFrom();
+ shimIteratorCtor();
+ shimIteratorDrop();
+ shimIteratorEvery();
+ shimIteratorFilter();
+ shimIteratorFind();
+ shimIteratorFlatMap();
+ shimIteratorForEach();
+ shimIteratorMap();
+ shimIteratorReduce();
+ shimIteratorSome();
+ shimIteratorTake();
+ shimIteratorToArray();
+};
diff --git a/test/Iterator.from.js b/test/Iterator.from.js
new file mode 100644
index 0000000..bb5cc0c
--- /dev/null
+++ b/test/Iterator.from.js
@@ -0,0 +1,124 @@
+'use strict';
+
+var defineProperties = require('define-properties');
+var test = require('tape');
+var callBind = require('call-bind');
+var functionsHaveNames = require('functions-have-names')();
+var hasProto = require('has-proto')();
+var forEach = require('for-each');
+var debug = require('object-inspect');
+var v = require('es-value-fixtures');
+var hasSymbols = require('has-symbols/shams')();
+
+var index = require('../Iterator.from');
+var impl = require('../Iterator.from/implementation');
+
+var isEnumerable = Object.prototype.propertyIsEnumerable;
+
+var testIterator = require('./helpers/testIterator');
+
+var $Iterator = require('../Iterator/implementation');
+var iterProto = require('iterator.prototype');
+
+var getCodePoints = function getCodePoints(str) {
+ var chars = [];
+ for (var i = 0; i < str.length; i++) {
+ var c1 = str.charCodeAt(i);
+ if (c1 >= 0xD800 && c1 < 0xDC00 && i + 1 < str.length) {
+ var c2 = str.charCodeAt(i + 1);
+ if (c2 >= 0xDC00 && c2 < 0xE000) {
+ chars.push(str.charAt(i) + str.charAt(i + 1));
+ i += 1;
+ continue; // eslint-disable-line no-continue, no-restricted-syntax
+ }
+ }
+ chars.push(str.charAt(i));
+ }
+ return chars;
+};
+
+module.exports = {
+ tests: function (from, name, t) {
+ forEach(v.primitives.concat(v.objects), function (nonIterator) {
+ if (typeof nonIterator !== 'string') {
+ t['throws'](
+ function () { from(nonIterator); },
+ TypeError,
+ debug(nonIterator) + ' is not an iterable Object'
+ );
+ }
+ });
+
+ t.test('actual iteration', { skip: !hasSymbols }, function (st) {
+ forEach(v.nonFunctions, function (nonFunction) {
+ var badIterable = {};
+ badIterable[Symbol.iterator] = nonFunction;
+ st['throws'](
+ function () { from(badIterable); },
+ TypeError,
+ debug(badIterable) + ' is not a function'
+ );
+ });
+
+ forEach(v.strings, function (string) {
+ var stringIt = from(string);
+ testIterator(stringIt, getCodePoints(string), st, 'string iterator: ' + debug(string));
+ });
+
+ var arrayIt = from([1, 2, 3]);
+ st.equal(typeof arrayIt.next, 'function', 'has a `next` function');
+
+ st.test('__proto__ is Iterator.prototype', { skip: !hasProto }, function (s2t) {
+ var fakeIterator = {
+ __proto__: iterProto,
+ next: function () {}
+ };
+ s2t.ok(fakeIterator instanceof $Iterator, 'is an instanceof Iterator');
+ s2t.equal(typeof fakeIterator.next, 'function', 'fake iterator `.next` is a function');
+ s2t.equal(from(fakeIterator), fakeIterator, 'returns input when it is an instanceof Iterator');
+
+ s2t.end();
+ });
+
+ st.test('real iterators', { skip: !hasSymbols }, function (s2t) {
+ var iter = [][Symbol.iterator]();
+ s2t.equal(from(iter), iter, 'array iterator becomes itself');
+
+ s2t.end();
+ });
+
+ st.end();
+ });
+ },
+ index: function () {
+ test('Iterator.from: index', function (t) {
+ module.exports.tests(index, 'Iterator.from', t);
+
+ t.end();
+ });
+ },
+ implementation: function () {
+ test('Iterator.from: implementation', function (t) {
+ module.exports.tests(callBind(impl, null), 'Iterator.from', t);
+
+ t.end();
+ });
+ },
+ shimmed: function () {
+ test('Iterator.from: shimmed', function (t) {
+ t.test('Function name', { skip: !functionsHaveNames }, function (st) {
+ st.equal(Iterator.from.name, 'from', 'Iterator.from has name "from"');
+ st.end();
+ });
+
+ t.test('enumerability', { skip: !defineProperties.supportsDescriptors }, function (et) {
+ et.equal(false, isEnumerable.call(Iterator, 'from'), 'Iterator.from is not enumerable');
+ et.end();
+ });
+
+ module.exports.tests(callBind(Iterator.from, Iterator), 'Iterator.from', t);
+
+ t.end();
+ });
+ }
+};
diff --git a/test/Iterator.prototype.constructor.js b/test/Iterator.prototype.constructor.js
new file mode 100644
index 0000000..e40db56
--- /dev/null
+++ b/test/Iterator.prototype.constructor.js
@@ -0,0 +1,47 @@
+'use strict';
+
+var defineProperties = require('define-properties');
+var test = require('tape');
+
+var Index = require('../Iterator.prototype.constructor');
+var Impl = require('../Iterator.prototype.constructor/implementation');
+
+var $Iterator = require('../Iterator/polyfill')();
+
+var isEnumerable = Object.prototype.propertyIsEnumerable;
+
+module.exports = {
+ tests: function (t, constructor, name) {
+ t.equal(constructor, $Iterator, name + ' is Iterator');
+ },
+ index: function () {
+ test('Iterator.prototype.constructor: index', function (t) {
+ t.notEqual(Index, $Iterator, 'index is not Iterator itself');
+ t.equal(typeof Index, 'function', 'index is a function');
+
+ t.ok(new Index() instanceof $Iterator, 'new index() instanceof Iterator');
+
+ t.end();
+ });
+ },
+ implementation: function () {
+ test('Iterator.prototype.constructor: implementation', function (t) {
+ t.equal(Impl, $Iterator, 'implementation is Iterator itself');
+ module.exports.tests(t, Impl, 'Iterator.prototype.constructor');
+
+ t.end();
+ });
+ },
+ shimmed: function () {
+ test('Iterator.prototype.constructor: shimmed', function (t) {
+ module.exports.tests(t, Iterator.prototype.constructor, 'Iterator.prototype.constructor');
+
+ t.test('enumerability', { skip: !defineProperties.supportsDescriptors }, function (et) {
+ et.equal(false, isEnumerable.call(Iterator.prototype, 'constructor'), 'Iterator#constructor is not enumerable');
+ et.end();
+ });
+
+ t.end();
+ });
+ }
+};
diff --git a/test/Iterator.prototype.drop.js b/test/Iterator.prototype.drop.js
new file mode 100644
index 0000000..9ccab0a
--- /dev/null
+++ b/test/Iterator.prototype.drop.js
@@ -0,0 +1,95 @@
+'use strict';
+
+var defineProperties = require('define-properties');
+var test = require('tape');
+var callBind = require('call-bind');
+var functionsHaveNames = require('functions-have-names')();
+var hasStrictMode = require('has-strict-mode')();
+var forEach = require('for-each');
+var debug = require('object-inspect');
+var v = require('es-value-fixtures');
+var hasSymbols = require('has-symbols/shams')();
+
+var index = require('../Iterator.prototype.drop');
+var impl = require('../Iterator.prototype.drop/implementation');
+
+var fnName = 'drop';
+
+var isEnumerable = Object.prototype.propertyIsEnumerable;
+
+var testIterator = require('./helpers/testIterator');
+
+module.exports = {
+ tests: function (drop, name, t) {
+ forEach(v.primitives.concat(v.objects), function (nonIterator) {
+ t['throws'](
+ function () { drop(nonIterator); },
+ TypeError,
+ debug(nonIterator) + ' is not an Object with a callable `next` method'
+ );
+
+ var badNext = { next: nonIterator };
+ t['throws'](
+ function () { drop(badNext); },
+ TypeError,
+ debug(badNext) + ' is not an Object with a callable `next` method'
+ );
+ });
+
+ var iterator = [1, 2, 3];
+
+ t.test('actual iteration', { skip: !hasSymbols }, function (st) {
+ st['throws'](
+ function () { drop(iterator[Symbol.iterator](), -3); },
+ RangeError,
+ '-3 is not >= 0'
+ );
+
+ testIterator(iterator[Symbol.iterator](), [1, 2, 3], st, 'original');
+ testIterator(drop(iterator[Symbol.iterator](), 0), [1, 2, 3], st, 'drop 0');
+ testIterator(drop(iterator[Symbol.iterator](), 1), [2, 3], st, 'drop 1');
+ testIterator(drop(iterator[Symbol.iterator](), 2), [3], st, 'drop 2');
+ testIterator(drop(iterator[Symbol.iterator](), 3), [], st, 'drop 3');
+ testIterator(drop(iterator[Symbol.iterator](), Infinity), [], st, 'drop ∞');
+
+ st.end();
+ });
+ },
+ index: function () {
+ test('Iterator.prototype.' + fnName + ': index', function (t) {
+ module.exports.tests(index, 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ implementation: function () {
+ test('Iterator.prototype.' + fnName + ': implementation', function (t) {
+ module.exports.tests(callBind(impl), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ shimmed: function () {
+ test('Iterator.prototype.' + fnName + ': shimmed', function (t) {
+ t.test('Function name', { skip: !functionsHaveNames }, function (st) {
+ st.equal(Iterator.prototype[fnName].name, fnName, 'Iterator#' + fnName + ' has name "' + fnName + '"');
+ st.end();
+ });
+
+ t.test('enumerability', { skip: !defineProperties.supportsDescriptors }, function (et) {
+ et.equal(false, isEnumerable.call(Iterator.prototype, fnName), 'Iterator#' + fnName + ' is not enumerable');
+ et.end();
+ });
+
+ t.test('bad string/this value', { skip: !hasStrictMode }, function (st) {
+ st['throws'](function () { return Iterator.prototype[fnName].call(undefined, 'a'); }, TypeError, 'undefined is not an object');
+ st['throws'](function () { return Iterator.prototype[fnName].call(null, 'a'); }, TypeError, 'null is not an object');
+ st.end();
+ });
+
+ module.exports.tests(callBind(Iterator.prototype[fnName]), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ }
+};
diff --git a/test/Iterator.prototype.every.js b/test/Iterator.prototype.every.js
new file mode 100644
index 0000000..f014920
--- /dev/null
+++ b/test/Iterator.prototype.every.js
@@ -0,0 +1,96 @@
+'use strict';
+
+var defineProperties = require('define-properties');
+var test = require('tape');
+var callBind = require('call-bind');
+var functionsHaveNames = require('functions-have-names')();
+var hasStrictMode = require('has-strict-mode')();
+var forEach = require('for-each');
+var debug = require('object-inspect');
+var v = require('es-value-fixtures');
+var hasSymbols = require('has-symbols/shams')();
+
+var index = require('../Iterator.prototype.every');
+var impl = require('../Iterator.prototype.every/implementation');
+
+var fnName = 'every';
+
+var isEnumerable = Object.prototype.propertyIsEnumerable;
+
+var testIterator = require('./helpers/testIterator');
+
+module.exports = {
+ tests: function (every, name, t) {
+ forEach(v.primitives.concat(v.objects), function (nonIterator) {
+ t['throws'](
+ function () { every(nonIterator); },
+ TypeError,
+ debug(nonIterator) + ' is not an Object with a callable `next` method'
+ );
+
+ var badNext = { next: nonIterator };
+ t['throws'](
+ function () { every(badNext); },
+ TypeError,
+ debug(badNext) + ' is not an Object with a callable `next` method'
+ );
+ });
+
+ forEach(v.nonFunctions, function (nonFunction) {
+ t['throws'](
+ function () { every({ next: function () {} }, nonFunction); },
+ TypeError,
+ debug(nonFunction) + ' is not a function'
+ );
+ });
+
+ t.test('actual iteration', { skip: !hasSymbols }, function (st) {
+ var arr = [1, 2, 3];
+ var iterator = callBind(arr[Symbol.iterator], arr);
+
+ testIterator(iterator(), [1, 2, 3], st, 'original');
+ st.equal(every(iterator(), function () { return false; }), false, 'every for always-false');
+ st.equal(every(iterator(), function () { return true; }), true, 'every for always-true');
+ st.equal(every(iterator(), function (x, i) { return x === 2 && i === 1; }), false, 'every returns false for matching value/index');
+
+ st.end();
+ });
+ },
+ index: function () {
+ test('Iterator.prototype.' + fnName + ': index', function (t) {
+ module.exports.tests(index, 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ implementation: function () {
+ test('Iterator.prototype.' + fnName + ': implementation', function (t) {
+ module.exports.tests(callBind(impl), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ shimmed: function () {
+ test('Iterator.prototype.' + fnName + ': shimmed', function (t) {
+ t.test('Function name', { skip: !functionsHaveNames }, function (st) {
+ st.equal(Iterator.prototype[fnName].name, fnName, 'Iterator#' + fnName + ' has name "' + fnName + '"');
+ st.end();
+ });
+
+ t.test('enumerability', { skip: !defineProperties.supportsDescriptors }, function (et) {
+ et.equal(false, isEnumerable.call(Iterator.prototype, fnName), 'Iterator#' + fnName + ' is not enumerable');
+ et.end();
+ });
+
+ t.test('bad string/this value', { skip: !hasStrictMode }, function (st) {
+ st['throws'](function () { return Iterator.prototype[fnName].call(undefined, 'a'); }, TypeError, 'undefined is not an object');
+ st['throws'](function () { return Iterator.prototype[fnName].call(null, 'a'); }, TypeError, 'null is not an object');
+ st.end();
+ });
+
+ module.exports.tests(callBind(Iterator.prototype[fnName]), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ }
+};
diff --git a/test/Iterator.prototype.filter.js b/test/Iterator.prototype.filter.js
new file mode 100644
index 0000000..1efcc80
--- /dev/null
+++ b/test/Iterator.prototype.filter.js
@@ -0,0 +1,96 @@
+'use strict';
+
+var defineProperties = require('define-properties');
+var test = require('tape');
+var callBind = require('call-bind');
+var functionsHaveNames = require('functions-have-names')();
+var hasStrictMode = require('has-strict-mode')();
+var forEach = require('for-each');
+var debug = require('object-inspect');
+var v = require('es-value-fixtures');
+var hasSymbols = require('has-symbols/shams')();
+
+var index = require('../Iterator.prototype.filter');
+var impl = require('../Iterator.prototype.filter/implementation');
+
+var fnName = 'filter';
+
+var isEnumerable = Object.prototype.propertyIsEnumerable;
+
+var testIterator = require('./helpers/testIterator');
+
+module.exports = {
+ tests: function (filter, name, t) {
+ forEach(v.primitives.concat(v.objects), function (nonIterator) {
+ t['throws'](
+ function () { filter(nonIterator); },
+ TypeError,
+ debug(nonIterator) + ' is not an Object with a callable `next` method'
+ );
+
+ var badNext = { next: nonIterator };
+ t['throws'](
+ function () { filter(badNext); },
+ TypeError,
+ debug(badNext) + ' is not an Object with a callable `next` method'
+ );
+ });
+
+ forEach(v.nonFunctions, function (nonFunction) {
+ t['throws'](
+ function () { filter({ next: function () {} }, nonFunction); },
+ TypeError,
+ debug(nonFunction) + ' is not a function'
+ );
+ });
+
+ t.test('actual iteration', { skip: !hasSymbols }, function (st) {
+ var arr = [1, 2, 3];
+ var iterator = callBind(arr[Symbol.iterator], arr);
+
+ testIterator(iterator(), [1, 2, 3], st, 'original');
+ testIterator(filter(iterator(), function () { return false; }), [], st, 'filter for always-false');
+ testIterator(filter(iterator(), function () { return true; }), [1, 2, 3], st, 'filter for always-true');
+ testIterator(filter(iterator(), function (x, i) { return x === 2 && i === 1; }), [2], st, 'filter returns value for matching value/index');
+
+ st.end();
+ });
+ },
+ index: function () {
+ test('Iterator.prototype.' + fnName + ': index', function (t) {
+ module.exports.tests(index, 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ implementation: function () {
+ test('Iterator.prototype.' + fnName + ': implementation', function (t) {
+ module.exports.tests(callBind(impl), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ shimmed: function () {
+ test('Iterator.prototype.' + fnName + ': shimmed', function (t) {
+ t.test('Function name', { skip: !functionsHaveNames }, function (st) {
+ st.equal(Iterator.prototype[fnName].name, fnName, 'Iterator#' + fnName + ' has name "' + fnName + '"');
+ st.end();
+ });
+
+ t.test('enumerability', { skip: !defineProperties.supportsDescriptors }, function (et) {
+ et.equal(false, isEnumerable.call(Iterator.prototype, fnName), 'Iterator#' + fnName + ' is not enumerable');
+ et.end();
+ });
+
+ t.test('bad string/this value', { skip: !hasStrictMode }, function (st) {
+ st['throws'](function () { return Iterator.prototype[fnName].call(undefined, 'a'); }, TypeError, 'undefined is not an object');
+ st['throws'](function () { return Iterator.prototype[fnName].call(null, 'a'); }, TypeError, 'null is not an object');
+ st.end();
+ });
+
+ module.exports.tests(callBind(Iterator.prototype[fnName]), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ }
+};
diff --git a/test/Iterator.prototype.find.js b/test/Iterator.prototype.find.js
new file mode 100644
index 0000000..503399a
--- /dev/null
+++ b/test/Iterator.prototype.find.js
@@ -0,0 +1,96 @@
+'use strict';
+
+var defineProperties = require('define-properties');
+var test = require('tape');
+var callBind = require('call-bind');
+var functionsHaveNames = require('functions-have-names')();
+var hasStrictMode = require('has-strict-mode')();
+var forEach = require('for-each');
+var debug = require('object-inspect');
+var v = require('es-value-fixtures');
+var hasSymbols = require('has-symbols/shams')();
+
+var index = require('../Iterator.prototype.find');
+var impl = require('../Iterator.prototype.find/implementation');
+
+var fnName = 'find';
+
+var isEnumerable = Object.prototype.propertyIsEnumerable;
+
+var testIterator = require('./helpers/testIterator');
+
+module.exports = {
+ tests: function (find, name, t) {
+ forEach(v.primitives.concat(v.objects), function (nonIterator) {
+ t['throws'](
+ function () { find(nonIterator); },
+ TypeError,
+ debug(nonIterator) + ' is not an Object with a callable `next` method'
+ );
+
+ var badNext = { next: nonIterator };
+ t['throws'](
+ function () { find(badNext); },
+ TypeError,
+ debug(badNext) + ' is not an Object with a callable `next` method'
+ );
+ });
+
+ forEach(v.nonFunctions, function (nonFunction) {
+ t['throws'](
+ function () { find({ next: function () {} }, nonFunction); },
+ TypeError,
+ debug(nonFunction) + ' is not a function'
+ );
+ });
+
+ t.test('actual iteration', { skip: !hasSymbols }, function (st) {
+ var arr = [1, 2, 3];
+ var iterator = callBind(arr[Symbol.iterator], arr);
+
+ testIterator(iterator(), [1, 2, 3], st, 'original');
+ st.equal(find(iterator(), function () { return false; }), undefined, 'find for always-false');
+ st.equal(find(iterator(), function () { return true; }), 1, 'find for always-true');
+ st.equal(find(iterator(), function (x, i) { return x === 2 && i === 1; }), 2, 'find returns value for matching value/index');
+
+ st.end();
+ });
+ },
+ index: function () {
+ test('Iterator.prototype.' + fnName + ': index', function (t) {
+ module.exports.tests(index, 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ implementation: function () {
+ test('Iterator.prototype.' + fnName + ': implementation', function (t) {
+ module.exports.tests(callBind(impl), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ shimmed: function () {
+ test('Iterator.prototype.' + fnName + ': shimmed', function (t) {
+ t.test('Function name', { skip: !functionsHaveNames }, function (st) {
+ st.equal(Iterator.prototype[fnName].name, fnName, 'Iterator#' + fnName + ' has name "' + fnName + '"');
+ st.end();
+ });
+
+ t.test('enumerability', { skip: !defineProperties.supportsDescriptors }, function (et) {
+ et.equal(false, isEnumerable.call(Iterator.prototype, fnName), 'Iterator#' + fnName + ' is not enumerable');
+ et.end();
+ });
+
+ t.test('bad string/this value', { skip: !hasStrictMode }, function (st) {
+ st['throws'](function () { return Iterator.prototype[fnName].call(undefined, 'a'); }, TypeError, 'undefined is not an object');
+ st['throws'](function () { return Iterator.prototype[fnName].call(null, 'a'); }, TypeError, 'null is not an object');
+ st.end();
+ });
+
+ module.exports.tests(callBind(Iterator.prototype[fnName]), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ }
+};
diff --git a/test/Iterator.prototype.flatMap.js b/test/Iterator.prototype.flatMap.js
new file mode 100644
index 0000000..d52424d
--- /dev/null
+++ b/test/Iterator.prototype.flatMap.js
@@ -0,0 +1,106 @@
+'use strict';
+
+var defineProperties = require('define-properties');
+var test = require('tape');
+var callBind = require('call-bind');
+var functionsHaveNames = require('functions-have-names')();
+var hasStrictMode = require('has-strict-mode')();
+var forEach = require('for-each');
+var debug = require('object-inspect');
+var v = require('es-value-fixtures');
+var hasSymbols = require('has-symbols/shams')();
+
+var index = require('../Iterator.prototype.flatMap');
+var impl = require('../Iterator.prototype.flatMap/implementation');
+
+var fnName = 'flatMap';
+
+var isEnumerable = Object.prototype.propertyIsEnumerable;
+
+var testIterator = require('./helpers/testIterator');
+
+module.exports = {
+ tests: function (flatMap, name, t) {
+ forEach(v.primitives.concat(v.objects), function (nonIterator) {
+ t['throws'](
+ function () { flatMap(nonIterator); },
+ TypeError,
+ debug(nonIterator) + ' is not an Object with a callable `next` method'
+ );
+
+ var badNext = { next: nonIterator };
+ t['throws'](
+ function () { flatMap(badNext); },
+ TypeError,
+ debug(badNext) + ' is not an Object with a callable `next` method'
+ );
+ });
+
+ forEach(v.nonFunctions, function (nonFunction) {
+ t['throws'](
+ function () { flatMap({ next: function () {} }, nonFunction); },
+ TypeError,
+ debug(nonFunction) + ' is not a function'
+ );
+ });
+
+ t.test('actual iteration', { skip: !hasSymbols }, function (st) {
+ var arr = [1, 2, 3];
+ var iterator = callBind(arr[Symbol.iterator], arr);
+
+ testIterator(iterator(), [1, 2, 3], st, 'original');
+
+ var nonIterableFlatMap = flatMap(iterator(), function (x) { return x; });
+ st['throws'](
+ function () { nonIterableFlatMap.next(); },
+ TypeError,
+ 'non-iterable return value throws'
+ );
+
+ testIterator(flatMap(iterator(), function (x) { return [x][Symbol.iterator](); }), [1, 2, 3], st, 'identity mapper in array iterator');
+ testIterator(flatMap(iterator(), function (x) { return [2 * x][Symbol.iterator](); }), [2, 4, 6], st, 'doubler mapper in array iterator');
+
+ testIterator(flatMap(iterator(), function (x) { return [[x]][Symbol.iterator](); }), [[1], [2], [3]], st, 'identity mapper in nested array iterator');
+ testIterator(flatMap(iterator(), function (x) { return [[2 * x]][Symbol.iterator](); }), [[2], [4], [6]], st, 'doubler mapper in nested array iterator');
+
+ st.end();
+ });
+ },
+ index: function () {
+ test('Iterator.prototype.' + fnName + ': index', function (t) {
+ module.exports.tests(index, 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ implementation: function () {
+ test('Iterator.prototype.' + fnName + ': implementation', function (t) {
+ module.exports.tests(callBind(impl), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ shimmed: function () {
+ test('Iterator.prototype.' + fnName + ': shimmed', function (t) {
+ t.test('Function name', { skip: !functionsHaveNames }, function (st) {
+ st.equal(Iterator.prototype[fnName].name, fnName, 'Iterator#' + fnName + ' has name "' + fnName + '"');
+ st.end();
+ });
+
+ t.test('enumerability', { skip: !defineProperties.supportsDescriptors }, function (et) {
+ et.equal(false, isEnumerable.call(Iterator.prototype, fnName), 'Iterator#' + fnName + ' is not enumerable');
+ et.end();
+ });
+
+ t.test('bad string/this value', { skip: !hasStrictMode }, function (st) {
+ st['throws'](function () { return Iterator.prototype[fnName].call(undefined, 'a'); }, TypeError, 'undefined is not an object');
+ st['throws'](function () { return Iterator.prototype[fnName].call(null, 'a'); }, TypeError, 'null is not an object');
+ st.end();
+ });
+
+ module.exports.tests(callBind(Iterator.prototype[fnName]), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ }
+};
diff --git a/test/Iterator.prototype.forEach.js b/test/Iterator.prototype.forEach.js
new file mode 100644
index 0000000..326c149
--- /dev/null
+++ b/test/Iterator.prototype.forEach.js
@@ -0,0 +1,114 @@
+'use strict';
+
+var defineProperties = require('define-properties');
+var test = require('tape');
+var callBind = require('call-bind');
+var functionsHaveNames = require('functions-have-names')();
+var hasStrictMode = require('has-strict-mode')();
+var forEachNormal = require('for-each');
+var debug = require('object-inspect');
+var v = require('es-value-fixtures');
+var hasSymbols = require('has-symbols/shams')();
+
+var index = require('../Iterator.prototype.forEach');
+var impl = require('../Iterator.prototype.forEach/implementation');
+
+var fnName = 'forEach';
+
+var isEnumerable = Object.prototype.propertyIsEnumerable;
+
+var testIterator = require('./helpers/testIterator');
+
+module.exports = {
+ tests: function (forEach, name, t) {
+ forEachNormal(v.primitives.concat(v.objects), function (nonIterator) {
+ t['throws'](
+ function () { forEach(nonIterator); },
+ TypeError,
+ debug(nonIterator) + ' is not an Object with a callable `next` method'
+ );
+
+ var badNext = { next: nonIterator };
+ t['throws'](
+ function () { forEach(badNext); },
+ TypeError,
+ debug(badNext) + ' is not an Object with a callable `next` method'
+ );
+ });
+
+ forEachNormal(v.nonFunctions, function (nonFunction) {
+ t['throws'](
+ function () { forEach({ next: function () {} }, nonFunction); },
+ TypeError,
+ debug(nonFunction) + ' is not a function'
+ );
+ });
+
+ t.test('actual iteration', { skip: !hasSymbols }, function (st) {
+ var arr = [1, 2, 3];
+ var iterator = callBind(arr[Symbol.iterator], arr);
+
+ testIterator(iterator(), [1, 2, 3], st, 'original');
+
+ var results = [];
+ var ret = forEach(
+ iterator(),
+ function (x, i) {
+ // eslint-disable-next-line no-invalid-this
+ results.push({ value: x, count: i, 'this': this, args: arguments.length });
+ }
+ );
+
+ st.equal(ret, undefined, 'returns undefined');
+
+ st.deepEqual(
+ results,
+ [
+ { value: 1, count: 0, 'this': undefined, args: 2 },
+ { value: 2, count: 1, 'this': undefined, args: 2 },
+ { value: 3, count: 2, 'this': undefined, args: 2 }
+ ],
+ 'forEach callback receives the expected values'
+ );
+
+ st.end();
+ });
+ },
+ index: function () {
+ test('Iterator.prototype.' + fnName + ': index', function (t) {
+ module.exports.tests(index, 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ implementation: function () {
+ test('Iterator.prototype.' + fnName + ': implementation', function (t) {
+ module.exports.tests(callBind(impl), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ shimmed: function () {
+ test('Iterator.prototype.' + fnName + ': shimmed', function (t) {
+ t.test('Function name', { skip: !functionsHaveNames }, function (st) {
+ st.equal(Iterator.prototype[fnName].name, fnName, 'Iterator#' + fnName + ' has name "' + fnName + '"');
+ st.end();
+ });
+
+ t.test('enumerability', { skip: !defineProperties.supportsDescriptors }, function (et) {
+ et.equal(false, isEnumerable.call(Iterator.prototype, fnName), 'Iterator#' + fnName + ' is not enumerable');
+ et.end();
+ });
+
+ t.test('bad string/this value', { skip: !hasStrictMode }, function (st) {
+ st['throws'](function () { return Iterator.prototype[fnName].call(undefined, 'a'); }, TypeError, 'undefined is not an object');
+ st['throws'](function () { return Iterator.prototype[fnName].call(null, 'a'); }, TypeError, 'null is not an object');
+ st.end();
+ });
+
+ module.exports.tests(callBind(Iterator.prototype[fnName]), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ }
+};
diff --git a/test/Iterator.prototype.map.js b/test/Iterator.prototype.map.js
new file mode 100644
index 0000000..42ef49a
--- /dev/null
+++ b/test/Iterator.prototype.map.js
@@ -0,0 +1,130 @@
+'use strict';
+
+var defineProperties = require('define-properties');
+var test = require('tape');
+var callBind = require('call-bind');
+var functionsHaveNames = require('functions-have-names')();
+var hasStrictMode = require('has-strict-mode')();
+var forEach = require('for-each');
+var debug = require('object-inspect');
+var v = require('es-value-fixtures');
+var hasSymbols = require('has-symbols/shams')();
+
+var index = require('../Iterator.prototype.map');
+var impl = require('../Iterator.prototype.map/implementation');
+
+var fnName = 'map';
+
+var isEnumerable = Object.prototype.propertyIsEnumerable;
+
+var testIterator = require('./helpers/testIterator');
+
+module.exports = {
+ tests: function (map, name, t) {
+ forEach(v.primitives.concat(v.objects), function (nonIterator) {
+ t['throws'](
+ function () { map(nonIterator); },
+ TypeError,
+ debug(nonIterator) + ' is not an Object with a callable `next` method'
+ );
+
+ var badNext = { next: nonIterator };
+ t['throws'](
+ function () { map(badNext); },
+ TypeError,
+ debug(badNext) + ' is not an Object with a callable `next` method'
+ );
+ });
+
+ forEach(v.nonFunctions, function (nonFunction) {
+ t['throws'](
+ function () { map({ next: function () {} }, nonFunction); },
+ TypeError,
+ debug(nonFunction) + ' is not a function'
+ );
+ });
+
+ var sentinel = {};
+ var done = false;
+ var fakeIterator = {
+ next: function () {
+ try {
+ return {
+ done: done,
+ value: sentinel
+ };
+ } finally {
+ done = true;
+ }
+ }
+ };
+ var result = {};
+ testIterator(
+ map(fakeIterator, function (x, i) {
+ result.value = x;
+ result.counter = i;
+ result.receiver = this; // eslint-disable-line no-invalid-this
+ result.args = arguments.length;
+ return fakeIterator;
+ }),
+ [fakeIterator],
+ t,
+ 'fake iterator, mapped, runs as expected'
+ );
+ t.deepEqual(
+ result,
+ { value: sentinel, counter: 0, receiver: undefined, args: 2 },
+ 'callback is called with the correct arguments'
+ );
+
+ t.test('actual iteration', { skip: !hasSymbols }, function (st) {
+ var arr = [1, 2, 3];
+ var iterator = callBind(arr[Symbol.iterator], arr);
+
+ testIterator(iterator(), [1, 2, 3], st, 'original');
+ testIterator(map(iterator(), function (x) { return x; }), [1, 2, 3], st, 'identity mapper');
+ testIterator(map(iterator(), function (x) { return 2 * x; }), [2, 4, 6], st, 'doubler mapper');
+
+ st.end();
+ });
+ },
+ index: function () {
+ test('Iterator.prototype.' + fnName + ': index', function (t) {
+ module.exports.tests(index, 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ implementation: function () {
+ test('Iterator.prototype.' + fnName + ': implementation', function (t) {
+ module.exports.tests(callBind(impl), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ shimmed: function () {
+ test('Iterator.prototype.' + fnName + ': shimmed', function (t) {
+ t.equal(typeof Iterator.prototype[fnName], 'function', 'exists and is a function');
+
+ t.test('Function name', { skip: !functionsHaveNames }, function (st) {
+ st.equal(Iterator.prototype[fnName].name, fnName, 'Iterator#' + fnName + ' has name "' + fnName + '"');
+ st.end();
+ });
+
+ t.test('enumerability', { skip: !defineProperties.supportsDescriptors }, function (et) {
+ et.equal(false, isEnumerable.call(Iterator.prototype, fnName), 'Iterator#' + fnName + ' is not enumerable');
+ et.end();
+ });
+
+ t.test('bad string/this value', { skip: !hasStrictMode }, function (st) {
+ st['throws'](function () { return Iterator.prototype[fnName].call(undefined, 'a'); }, TypeError, 'undefined is not an object');
+ st['throws'](function () { return Iterator.prototype[fnName].call(null, 'a'); }, TypeError, 'null is not an object');
+ st.end();
+ });
+
+ module.exports.tests(callBind(Iterator.prototype[fnName]), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ }
+};
diff --git a/test/Iterator.prototype.reduce.js b/test/Iterator.prototype.reduce.js
new file mode 100644
index 0000000..87e8fac
--- /dev/null
+++ b/test/Iterator.prototype.reduce.js
@@ -0,0 +1,133 @@
+'use strict';
+
+var defineProperties = require('define-properties');
+var test = require('tape');
+var callBind = require('call-bind');
+var functionsHaveNames = require('functions-have-names')();
+var hasStrictMode = require('has-strict-mode')();
+var forEach = require('for-each');
+var debug = require('object-inspect');
+var v = require('es-value-fixtures');
+var hasSymbols = require('has-symbols/shams')();
+
+var index = require('../Iterator.prototype.reduce');
+var impl = require('../Iterator.prototype.reduce/implementation');
+
+var fnName = 'reduce';
+
+var isEnumerable = Object.prototype.propertyIsEnumerable;
+
+var testIterator = require('./helpers/testIterator');
+
+module.exports = {
+ tests: function (reduce, name, t) {
+ forEach(v.primitives.concat(v.objects), function (nonIterator) {
+ t['throws'](
+ function () { reduce(nonIterator); },
+ TypeError,
+ debug(nonIterator) + ' is not an Object with a callable `next` method'
+ );
+
+ var badNext = { next: nonIterator };
+ t['throws'](
+ function () { reduce(badNext); },
+ TypeError,
+ debug(badNext) + ' is not an Object with a callable `next` method'
+ );
+ });
+
+ forEach(v.nonFunctions, function (nonFunction) {
+ t['throws'](
+ function () { reduce({ next: function () {} }, nonFunction); },
+ TypeError,
+ debug(nonFunction) + ' is not a function'
+ );
+ });
+
+ t.test('actual iteration', { skip: !hasSymbols }, function (st) {
+ var arr = [1, 2, 3];
+ var iterator = callBind(arr[Symbol.iterator], arr);
+
+ testIterator(iterator(), [1, 2, 3], st, 'original');
+
+ var results = [];
+ var ret = reduce(
+ iterator(),
+ function (acc, x, i) {
+ // eslint-disable-next-line no-invalid-this
+ results.push({ acc: acc, value: x, count: i, 'this': this, args: arguments.length });
+ return acc + x;
+ }
+ );
+ st.equal(ret, 6, 'returns sum of all numbers');
+ st.deepEqual(
+ results,
+ [
+ { acc: 1, value: 2, count: 1, 'this': undefined, args: 3 },
+ { acc: 3, value: 3, count: 2, 'this': undefined, args: 3 }
+ ],
+ 'reduce callback receives the expected values without initialValue'
+ );
+
+ var results2 = [];
+ var ret2 = reduce(
+ iterator(),
+ function (acc, x, i) {
+ // eslint-disable-next-line no-invalid-this
+ results2.push({ acc: acc, value: x, count: i, 'this': this, args: arguments.length });
+ return acc + x;
+ },
+ 10
+ );
+ st.equal(ret2, 16, 'returns sum of all numbers plus initialValue');
+ st.deepEqual(
+ results2,
+ [
+ { acc: 10, value: 1, count: 0, 'this': undefined, args: 3 },
+ { acc: 11, value: 2, count: 1, 'this': undefined, args: 3 },
+ { acc: 13, value: 3, count: 2, 'this': undefined, args: 3 }
+ ],
+ 'reduce callback receives the expected values with initialValue'
+ );
+
+ st.end();
+ });
+ },
+ index: function () {
+ test('Iterator.prototype.' + fnName + ': index', function (t) {
+ module.exports.tests(index, 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ implementation: function () {
+ test('Iterator.prototype.' + fnName + ': implementation', function (t) {
+ module.exports.tests(callBind(impl), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ shimmed: function () {
+ test('Iterator.prototype.' + fnName + ': shimmed', function (t) {
+ t.test('Function name', { skip: !functionsHaveNames }, function (st) {
+ st.equal(Iterator.prototype[fnName].name, fnName, 'Iterator#' + fnName + ' has name "' + fnName + '"');
+ st.end();
+ });
+
+ t.test('enumerability', { skip: !defineProperties.supportsDescriptors }, function (et) {
+ et.equal(false, isEnumerable.call(Iterator.prototype, fnName), 'Iterator#' + fnName + ' is not enumerable');
+ et.end();
+ });
+
+ t.test('bad string/this value', { skip: !hasStrictMode }, function (st) {
+ st['throws'](function () { return Iterator.prototype[fnName].call(undefined, 'a'); }, TypeError, 'undefined is not an object');
+ st['throws'](function () { return Iterator.prototype[fnName].call(null, 'a'); }, TypeError, 'null is not an object');
+ st.end();
+ });
+
+ module.exports.tests(callBind(Iterator.prototype[fnName]), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ }
+};
diff --git a/test/Iterator.prototype.some.js b/test/Iterator.prototype.some.js
new file mode 100644
index 0000000..6eac58c
--- /dev/null
+++ b/test/Iterator.prototype.some.js
@@ -0,0 +1,96 @@
+'use strict';
+
+var defineProperties = require('define-properties');
+var test = require('tape');
+var callBind = require('call-bind');
+var functionsHaveNames = require('functions-have-names')();
+var hasStrictMode = require('has-strict-mode')();
+var forEach = require('for-each');
+var debug = require('object-inspect');
+var v = require('es-value-fixtures');
+var hasSymbols = require('has-symbols/shams')();
+
+var index = require('../Iterator.prototype.some');
+var impl = require('../Iterator.prototype.some/implementation');
+
+var fnName = 'some';
+
+var isEnumerable = Object.prototype.propertyIsEnumerable;
+
+var testIterator = require('./helpers/testIterator');
+
+module.exports = {
+ tests: function (some, name, t) {
+ forEach(v.primitives.concat(v.objects), function (nonIterator) {
+ t['throws'](
+ function () { some(nonIterator); },
+ TypeError,
+ debug(nonIterator) + ' is not an Object with a callable `next` method'
+ );
+
+ var badNext = { next: nonIterator };
+ t['throws'](
+ function () { some(badNext); },
+ TypeError,
+ debug(badNext) + ' is not an Object with a callable `next` method'
+ );
+ });
+
+ forEach(v.nonFunctions, function (nonFunction) {
+ t['throws'](
+ function () { some({ next: function () {} }, nonFunction); },
+ TypeError,
+ debug(nonFunction) + ' is not a function'
+ );
+ });
+
+ t.test('actual iteration', { skip: !hasSymbols }, function (st) {
+ var arr = [1, 2, 3];
+ var iterator = callBind(arr[Symbol.iterator], arr);
+
+ testIterator(iterator(), [1, 2, 3], st, 'original');
+ st.equal(some(iterator(), function () { return false; }), false, 'some for always-false');
+ st.equal(some(iterator(), function () { return true; }), true, 'some for always-true');
+ st.equal(some(iterator(), function (x, i) { return x === 2 && i === 1; }), true, 'some returns true for matching value/index');
+
+ st.end();
+ });
+ },
+ index: function () {
+ test('Iterator.prototype.' + fnName + ': index', function (t) {
+ module.exports.tests(index, 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ implementation: function () {
+ test('Iterator.prototype.' + fnName + ': implementation', function (t) {
+ module.exports.tests(callBind(impl), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ shimmed: function () {
+ test('Iterator.prototype.' + fnName + ': shimmed', function (t) {
+ t.test('Function name', { skip: !functionsHaveNames }, function (st) {
+ st.equal(Iterator.prototype[fnName].name, fnName, 'Iterator#' + fnName + ' has name "' + fnName + '"');
+ st.end();
+ });
+
+ t.test('enumerability', { skip: !defineProperties.supportsDescriptors }, function (et) {
+ et.equal(false, isEnumerable.call(Iterator.prototype, fnName), 'Iterator#' + fnName + ' is not enumerable');
+ et.end();
+ });
+
+ t.test('bad string/this value', { skip: !hasStrictMode }, function (st) {
+ st['throws'](function () { return Iterator.prototype[fnName].call(undefined, 'a'); }, TypeError, 'undefined is not an object');
+ st['throws'](function () { return Iterator.prototype[fnName].call(null, 'a'); }, TypeError, 'null is not an object');
+ st.end();
+ });
+
+ module.exports.tests(callBind(Iterator.prototype[fnName]), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ }
+};
diff --git a/test/Iterator.prototype.take.js b/test/Iterator.prototype.take.js
new file mode 100644
index 0000000..1670b0f
--- /dev/null
+++ b/test/Iterator.prototype.take.js
@@ -0,0 +1,95 @@
+'use strict';
+
+var defineProperties = require('define-properties');
+var test = require('tape');
+var callBind = require('call-bind');
+var functionsHaveNames = require('functions-have-names')();
+var hasStrictMode = require('has-strict-mode')();
+var forEach = require('for-each');
+var debug = require('object-inspect');
+var v = require('es-value-fixtures');
+var hasSymbols = require('has-symbols/shams')();
+
+var index = require('../Iterator.prototype.take');
+var impl = require('../Iterator.prototype.take/implementation');
+
+var fnName = 'take';
+
+var isEnumerable = Object.prototype.propertyIsEnumerable;
+
+var testIterator = require('./helpers/testIterator');
+
+module.exports = {
+ tests: function (take, name, t) {
+ forEach(v.primitives.concat(v.objects), function (nonIterator) {
+ t['throws'](
+ function () { take(nonIterator); },
+ TypeError,
+ debug(nonIterator) + ' is not an Object with a callable `next` method'
+ );
+
+ var badNext = { next: nonIterator };
+ t['throws'](
+ function () { take(badNext); },
+ TypeError,
+ debug(badNext) + ' is not an Object with a callable `next` method'
+ );
+ });
+
+ var iterator = [1, 2, 3];
+
+ t.test('actual iteration', { skip: !hasSymbols }, function (st) {
+ st['throws'](
+ function () { take(iterator[Symbol.iterator](), -3); },
+ RangeError,
+ '-3 is not >= 0'
+ );
+
+ testIterator(iterator[Symbol.iterator](), [1, 2, 3], st, 'original');
+ testIterator(take(iterator[Symbol.iterator](), 0), [], st, 'take 0');
+ testIterator(take(iterator[Symbol.iterator](), 1), [1], st, 'take 1');
+ testIterator(take(iterator[Symbol.iterator](), 2), [1, 2], st, 'take 2');
+ testIterator(take(iterator[Symbol.iterator](), 3), [1, 2, 3], st, 'take 3');
+ testIterator(take(iterator[Symbol.iterator](), Infinity), [1, 2, 3], st, 'take ∞');
+
+ st.end();
+ });
+ },
+ index: function () {
+ test('Iterator.prototype.' + fnName + ': index', function (t) {
+ module.exports.tests(index, 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ implementation: function () {
+ test('Iterator.prototype.' + fnName + ': implementation', function (t) {
+ module.exports.tests(callBind(impl), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ shimmed: function () {
+ test('Iterator.prototype.' + fnName + ': shimmed', function (t) {
+ t.test('Function name', { skip: !functionsHaveNames }, function (st) {
+ st.equal(Iterator.prototype[fnName].name, fnName, 'Iterator#' + fnName + ' has name "' + fnName + '"');
+ st.end();
+ });
+
+ t.test('enumerability', { skip: !defineProperties.supportsDescriptors }, function (et) {
+ et.equal(false, isEnumerable.call(Iterator.prototype, fnName), 'Iterator#' + fnName + ' is not enumerable');
+ et.end();
+ });
+
+ t.test('bad string/this value', { skip: !hasStrictMode }, function (st) {
+ st['throws'](function () { return Iterator.prototype[fnName].call(undefined, 'a'); }, TypeError, 'undefined is not an object');
+ st['throws'](function () { return Iterator.prototype[fnName].call(null, 'a'); }, TypeError, 'null is not an object');
+ st.end();
+ });
+
+ module.exports.tests(callBind(Iterator.prototype[fnName]), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ }
+};
diff --git a/test/Iterator.prototype.toArray.js b/test/Iterator.prototype.toArray.js
new file mode 100644
index 0000000..2b1be25
--- /dev/null
+++ b/test/Iterator.prototype.toArray.js
@@ -0,0 +1,87 @@
+'use strict';
+
+var defineProperties = require('define-properties');
+var test = require('tape');
+var callBind = require('call-bind');
+var functionsHaveNames = require('functions-have-names')();
+var hasStrictMode = require('has-strict-mode')();
+var forEach = require('for-each');
+var debug = require('object-inspect');
+var v = require('es-value-fixtures');
+var hasSymbols = require('has-symbols/shams')();
+
+var index = require('../Iterator.prototype.toArray');
+var impl = require('../Iterator.prototype.toArray/implementation');
+
+var fnName = 'toArray';
+
+var isEnumerable = Object.prototype.propertyIsEnumerable;
+
+var testIterator = require('./helpers/testIterator');
+
+module.exports = {
+ tests: function (toArray, name, t) {
+ forEach(v.primitives.concat(v.objects), function (nonIterator) {
+ t['throws'](
+ function () { toArray(nonIterator); },
+ TypeError,
+ debug(nonIterator) + ' is not an Object with a callable `next` method'
+ );
+
+ var badNext = { next: nonIterator };
+ t['throws'](
+ function () { toArray(badNext); },
+ TypeError,
+ debug(badNext) + ' is not an Object with a callable `next` method'
+ );
+ });
+
+ t.test('actual iteration', { skip: !hasSymbols }, function (st) {
+ var arr = [1, 2, 3];
+ var iterator = callBind(arr[Symbol.iterator], arr);
+
+ testIterator(iterator(), [1, 2, 3], st, 'original');
+
+ st.deepEqual(toArray(iterator()), [1, 2, 3], 'toArray');
+
+ st.end();
+ });
+ },
+ index: function () {
+ test('Iterator.prototype.' + fnName + ': index', function (t) {
+ module.exports.tests(index, 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ implementation: function () {
+ test('Iterator.prototype.' + fnName + ': implementation', function (t) {
+ module.exports.tests(callBind(impl), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ },
+ shimmed: function () {
+ test('Iterator.prototype.' + fnName + ': shimmed', function (t) {
+ t.test('Function name', { skip: !functionsHaveNames }, function (st) {
+ st.equal(Iterator.prototype[fnName].name, fnName, 'Iterator#' + fnName + ' has name "' + fnName + '"');
+ st.end();
+ });
+
+ t.test('enumerability', { skip: !defineProperties.supportsDescriptors }, function (et) {
+ et.equal(false, isEnumerable.call(Iterator.prototype, fnName), 'Iterator#' + fnName + ' is not enumerable');
+ et.end();
+ });
+
+ t.test('bad string/this value', { skip: !hasStrictMode }, function (st) {
+ st['throws'](function () { return Iterator.prototype[fnName].call(undefined, 'a'); }, TypeError, 'undefined is not an object');
+ st['throws'](function () { return Iterator.prototype[fnName].call(null, 'a'); }, TypeError, 'null is not an object');
+ st.end();
+ });
+
+ module.exports.tests(callBind(Iterator.prototype[fnName]), 'Iterator.prototype.' + fnName, t);
+
+ t.end();
+ });
+ }
+};
diff --git a/test/helpers/testIterator.js b/test/helpers/testIterator.js
new file mode 100644
index 0000000..65051b4
--- /dev/null
+++ b/test/helpers/testIterator.js
@@ -0,0 +1,7 @@
+'use strict';
+
+var iterate = require('iterate-iterator');
+
+module.exports = function testIterator(iterator, expected, t, msg) {
+ t.deepEqual(iterate(iterator), expected, 'iterator yields expected values: ' + msg);
+};
diff --git a/test/implementation.js b/test/implementation.js
new file mode 100644
index 0000000..d3bf160
--- /dev/null
+++ b/test/implementation.js
@@ -0,0 +1,18 @@
+'use strict';
+
+var test = require('tape');
+var forEach = require('for-each');
+
+var shims = require('../');
+
+forEach(shims, function (shim) {
+ var shimTests;
+ try {
+ shimTests = require('./' + shim); // eslint-disable-line global-require
+ } catch (e) {
+ test(shim + ': implementation', { todo: true });
+ }
+ if (shimTests) {
+ shimTests.implementation();
+ }
+});
diff --git a/test/index.js b/test/index.js
new file mode 100644
index 0000000..66bed98
--- /dev/null
+++ b/test/index.js
@@ -0,0 +1,19 @@
+'use strict';
+
+var test = require('tape');
+var forEach = require('for-each');
+
+var shims = require('../');
+
+forEach(shims, function (shim) {
+ var shimTests;
+ try {
+ shimTests = require('./' + shim); // eslint-disable-line global-require
+ } catch (e) {
+ test(shim + ': index', { todo: true });
+ }
+ if (shimTests) {
+ shimTests.index();
+ }
+});
+
diff --git a/test/shimmed.js b/test/shimmed.js
new file mode 100644
index 0000000..8eda2d6
--- /dev/null
+++ b/test/shimmed.js
@@ -0,0 +1,20 @@
+'use strict';
+
+require('../auto');
+
+var test = require('tape');
+var forEach = require('for-each');
+
+var shims = require('../');
+
+forEach(shims, function (shim) {
+ var shimTests;
+ try {
+ shimTests = require('./' + shim); // eslint-disable-line global-require
+ } catch (e) {
+ test(shim + ': shimmed', { todo: true });
+ }
+ if (shimTests) {
+ shimTests.shimmed();
+ }
+});
diff --git a/test/tests.js b/test/tests.js
new file mode 100644
index 0000000..7949f54
--- /dev/null
+++ b/test/tests.js
@@ -0,0 +1,25 @@
+'use strict';
+
+var data = {
+ anchor: { arg: 'bar"baz"', expected: 'foo' },
+ big: 'foo',
+ blink: '',
+ bold: 'foo',
+ fixed: 'foo',
+ fontcolor: { arg: 'blue"red"green', expected: 'foo' },
+ fontsize: { arg: '10"large"small', expected: 'foo' },
+ italics: 'foo',
+ link: { arg: 'url"http://"', expected: 'foo' },
+ small: 'foo',
+ strike: 'foo',
+ sub: 'foo',
+ sup: 'foo'
+};
+
+module.exports = function (method, name, t) {
+ var result = data[name] || {};
+ var expected = typeof result === 'string' ? result : result.expected;
+ var actual = typeof result === 'string' ? method('foo') : method('foo', result.arg);
+
+ t.equal(actual, expected, name + ': got expected result');
+};