summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/Iterator/prototype/map
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /js/src/tests/non262/Iterator/prototype/map
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/tests/non262/Iterator/prototype/map')
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/call-next-on-iterator-while-iterating.js24
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/clobber-symbol.js22
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/interleaved-map-calls.js23
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/length.js22
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/map.js28
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/mapper-not-callable-throw.js33
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/mutate-iterator-after-done.js23
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/mutate-iterator.js22
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/name.js19
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/output-at-generator-end.js26
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/pass-lastValue-to-next.js36
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion-in-iteratorValue.js55
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion-in-yield.js62
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion.js54
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/proxy-accesses.js94
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/reenter-map-generator-from-mapper.js15
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/this-not-iterator-throw.js21
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/this-value-array-throws.js14
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/throw-when-iterator-returns-non-object.js24
-rw-r--r--js/src/tests/non262/Iterator/prototype/map/values-pass-through-chained-maps-to-next.js36
20 files changed, 653 insertions, 0 deletions
diff --git a/js/src/tests/non262/Iterator/prototype/map/call-next-on-iterator-while-iterating.js b/js/src/tests/non262/Iterator/prototype/map/call-next-on-iterator-while-iterating.js
new file mode 100644
index 0000000000..a5a10120a0
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/call-next-on-iterator-while-iterating.js
@@ -0,0 +1,24 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator'))
+
+/*---
+esid: pending
+description: Call next on an iterator that is being iterated over.
+info:
+features: [iterator-helpers]
+---*/
+
+const iterator = [1, 2, 3].values()
+const items = [];
+
+for (const item of iterator.map(x => x ** 2)) {
+ const nextItem = iterator.next();
+ items.push(item, nextItem.value);
+}
+
+assertEq(items[0], 1);
+assertEq(items[1], 2);
+assertEq(items[2], 9);
+assertEq(items[3], undefined);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Iterator/prototype/map/clobber-symbol.js b/js/src/tests/non262/Iterator/prototype/map/clobber-symbol.js
new file mode 100644
index 0000000000..8d5b2721e1
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/clobber-symbol.js
@@ -0,0 +1,22 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally
+//
+//
+
+/*---
+esid: pending
+description: %Iterator.prototype%.map works even if the global Symbol has been clobbered..
+info:
+features: [iterator-helpers, Symbol, Symbol.iterator]
+---*/
+
+Symbol = undefined;
+assertThrowsInstanceOf(() => Symbol.iterator, TypeError);
+
+const iterator = [0].values();
+assertEq(
+ iterator.map(x => x + 1).next().value, 1,
+ '`%Iterator.prototype%.map` still works after Symbol has been clobbered'
+);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Iterator/prototype/map/interleaved-map-calls.js b/js/src/tests/non262/Iterator/prototype/map/interleaved-map-calls.js
new file mode 100644
index 0000000000..3253e06192
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/interleaved-map-calls.js
@@ -0,0 +1,23 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator'))
+//
+
+/*---
+esid: pending
+description: Interleaved %Iterator.prototype%.map calls on the same iterator.
+info:
+features: [iterator-helpers]
+---*/
+
+const iterator = [1, 2, 3].values();
+const mapped1 = iterator.map(x => x);
+const mapped2 = iterator.map(x => 0);
+
+assertEq(mapped1.next().value, 1);
+assertEq(mapped2.next().value, 0);
+assertEq(mapped1.next().value, 3);
+
+assertEq(mapped1.next().done, true);
+assertEq(mapped2.next().done, true);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Iterator/prototype/map/length.js b/js/src/tests/non262/Iterator/prototype/map/length.js
new file mode 100644
index 0000000000..d6bc1ca774
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/length.js
@@ -0,0 +1,22 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator'))
+//
+
+/*---
+esid: pending
+description: %Iterator.prototype%.map length value and descriptor.
+info: >
+ 17 ECMAScript Standard Built-in Objects
+includes: [propertyHelper.js]
+features: [Symbol.iterator]
+---*/
+
+assertEq(Iterator.prototype.map.length, 1);
+
+const propertyDescriptor = Reflect.getOwnPropertyDescriptor(Iterator.prototype.map, 'length');
+assertEq(propertyDescriptor.value, 1);
+assertEq(propertyDescriptor.enumerable, false);
+assertEq(propertyDescriptor.writable, false);
+assertEq(propertyDescriptor.configurable, true);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Iterator/prototype/map/map.js b/js/src/tests/non262/Iterator/prototype/map/map.js
new file mode 100644
index 0000000000..2cf5267be7
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/map.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator'))
+
+/*---
+esid: pending
+description: %Iterator.prototype%.map value and descriptor.
+info: >
+ 17 ECMAScript Standard Built-in Objects
+features: [iterator-helpers]
+---*/
+
+const map = Reflect.getOwnPropertyDescriptor(Iterator.prototype, 'map');
+
+assertEq(
+ Iterator.prototype.map, map.value,
+ 'The value of `%Iterator.prototype%.map` is the same as the value in the property descriptor.'
+);
+
+assertEq(
+ typeof map.value, 'function',
+ '%Iterator.prototype%.map is a function.'
+);
+
+assertEq(map.enumerable, false);
+assertEq(map.writable, true);
+assertEq(map.configurable, true);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Iterator/prototype/map/mapper-not-callable-throw.js b/js/src/tests/non262/Iterator/prototype/map/mapper-not-callable-throw.js
new file mode 100644
index 0000000000..334e0fd8f9
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/mapper-not-callable-throw.js
@@ -0,0 +1,33 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator'))
+//
+
+/*---
+esid: pending
+description: Eagerly throw TypeError when `mapper` is not callable.
+info:
+features: [iterator-helpers]
+---*/
+
+assertThrowsInstanceOf(() => Iterator.prototype.map(undefined), TypeError);
+assertThrowsInstanceOf(() => [].values().map(undefined), TypeError);
+
+assertThrowsInstanceOf(() => Iterator.prototype.map(null), TypeError);
+assertThrowsInstanceOf(() => [].values().map(null), TypeError);
+
+assertThrowsInstanceOf(() => Iterator.prototype.map(0), TypeError);
+assertThrowsInstanceOf(() => [].values().map(0), TypeError);
+
+assertThrowsInstanceOf(() => Iterator.prototype.map(false), TypeError);
+assertThrowsInstanceOf(() => [].values().map(false), TypeError);
+
+assertThrowsInstanceOf(() => Iterator.prototype.map({}), TypeError);
+assertThrowsInstanceOf(() => [].values().map({}), TypeError);
+
+assertThrowsInstanceOf(() => Iterator.prototype.map(''), TypeError);
+assertThrowsInstanceOf(() => [].values().map(''), TypeError);
+
+assertThrowsInstanceOf(() => Iterator.prototype.map(Symbol('')), TypeError);
+assertThrowsInstanceOf(() => [].values().map(Symbol('')), TypeError);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Iterator/prototype/map/mutate-iterator-after-done.js b/js/src/tests/non262/Iterator/prototype/map/mutate-iterator-after-done.js
new file mode 100644
index 0000000000..b38158d73a
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/mutate-iterator-after-done.js
@@ -0,0 +1,23 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator'))
+//
+
+/*---
+esid: pending
+description: Mutate an iterator after it has been mapped and returned done.
+info:
+features: [iterator-helpers]
+---*/
+
+const array = [1, 2, 3];
+const iterator = [1, 2, 3].values().map(x => x * 2);
+
+assertEq(iterator.next().value, 2);
+assertEq(iterator.next().value, 4);
+assertEq(iterator.next().value, 6);
+assertEq(iterator.next().done, true);
+
+array.push(4);
+assertEq(iterator.next().done, true);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Iterator/prototype/map/mutate-iterator.js b/js/src/tests/non262/Iterator/prototype/map/mutate-iterator.js
new file mode 100644
index 0000000000..b1cc52fae5
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/mutate-iterator.js
@@ -0,0 +1,22 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator'))
+//
+
+/*---
+esid: pending
+description: Mutate an iterator after it has been mapped.
+info:
+features: [iterator-helpers]
+---*/
+
+const array = [1, 2, 3];
+const iterator = array.values().map(x => x * 2);
+array.push(4);
+
+assertEq(iterator.next().value, 2);
+assertEq(iterator.next().value, 4);
+assertEq(iterator.next().value, 6);
+assertEq(iterator.next().value, 8);
+assertEq(iterator.next().done, true);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Iterator/prototype/map/name.js b/js/src/tests/non262/Iterator/prototype/map/name.js
new file mode 100644
index 0000000000..3ba024d6e7
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/name.js
@@ -0,0 +1,19 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator'))
+/*---
+esid: pending
+description: %Iterator.prototype%.map.name value and descriptor.
+info: >
+ 17 ECMAScript Standard Built-in Objects
+features: [iterator-helpers]
+---*/
+
+assertEq(Iterator.prototype.map.name, 'map');
+
+const propertyDescriptor = Reflect.getOwnPropertyDescriptor(Iterator.prototype.map, 'name');
+assertEq(propertyDescriptor.value, 'map');
+assertEq(propertyDescriptor.enumerable, false);
+assertEq(propertyDescriptor.writable, false);
+assertEq(propertyDescriptor.configurable, true);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Iterator/prototype/map/output-at-generator-end.js b/js/src/tests/non262/Iterator/prototype/map/output-at-generator-end.js
new file mode 100644
index 0000000000..69ef04a7b2
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/output-at-generator-end.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator'))
+//
+
+/*---
+esid: pending
+description: %Iterator.prototype%.map outputs correct value at end of iterator.
+info:
+features: [iterator-helpers]
+---*/
+
+const iterator = [0].values().map(x => x);
+
+const iterRecord = iterator.next();
+assertEq(iterRecord.done, false);
+assertEq(iterRecord.value, 0);
+
+let endRecord = iterator.next();
+assertEq(endRecord.done, true);
+assertEq(endRecord.value, undefined);
+
+endRecord = iterator.next();
+assertEq(endRecord.done, true);
+assertEq(endRecord.value, undefined);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Iterator/prototype/map/pass-lastValue-to-next.js b/js/src/tests/non262/Iterator/prototype/map/pass-lastValue-to-next.js
new file mode 100644
index 0000000000..99ae4face5
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/pass-lastValue-to-next.js
@@ -0,0 +1,36 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator'))
+//
+
+/*---
+esid: pending
+description: %Iterator.prototype%.map passes lastValue to the `next` call.
+info: >
+ Iterator Helpers Proposal 2.1.5.2
+features: [iterator-helpers]
+---*/
+
+const iteratorWhereNextTakesValue = Object.setPrototypeOf({
+ next: function(value) {
+ assertEq(arguments.length, 0);
+
+ if (this.value < 3)
+ return { done: false, value: this.value++ };
+ return { done: true, value: undefined };
+ },
+ value: 0,
+}, Iterator.prototype);
+
+const mappedIterator = iteratorWhereNextTakesValue.map(x => x);
+
+assertEq(mappedIterator.next(1).value, 0);
+
+assertEq(mappedIterator.next(2).value, 1);
+
+assertEq(mappedIterator.next(3).value, 2);
+
+assertEq(mappedIterator.next(4).done, true);
+
+assertEq(mappedIterator.next(5).done, true);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion-in-iteratorValue.js b/js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion-in-iteratorValue.js
new file mode 100644
index 0000000000..f50bd0da10
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion-in-iteratorValue.js
@@ -0,0 +1,55 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator'))
+//
+
+/*---
+esid: pending
+description: %Iterator.prototype%.map does not call return when IteratorValue returns an abrupt completion.
+info: >
+features: [iterator-helpers]
+---*/
+
+const handlerProxy = log => new Proxy({}, {
+ get: (target, key, receiver) => (...args) => {
+ const target = args[0];
+ const item = Reflect[key](...args);
+
+ log.push(`${key}: ${args.filter(x => typeof x != 'object').map(x => x.toString())}`);
+
+ switch (typeof item) {
+ case 'function': return item.bind(new Proxy(target, handlerProxy(log)));
+ case 'object': return new Proxy(item, handlerProxy(log));
+ default: return item;
+ }
+ },
+});
+
+const log = [];
+const iterator = Object.setPrototypeOf({
+ next: function() {
+ throw 'error';
+ return { done: false, value: 0 };
+ },
+ return: function(value) {
+ log.push('close iterator');
+ return { done: true, value };
+ },
+}, Iterator.prototype);
+const iteratorProxy = new Proxy(iterator, handlerProxy(log));
+const mappedProxy = iteratorProxy.map(x => x);
+
+try {
+ mappedProxy.next();
+} catch (exc) {
+ assertEq(exc, 'error');
+}
+
+console.log(log.join('\n'));
+
+assertEq(
+ log.join('\n'),
+`get: map
+get: next`
+);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion-in-yield.js b/js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion-in-yield.js
new file mode 100644
index 0000000000..9eb782e52a
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion-in-yield.js
@@ -0,0 +1,62 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator'))
+//
+
+/*---
+esid: pending
+description: %Iterator.prototype%.map calls return when yield throws.
+info: >
+features: [iterator-helpers]
+---*/
+
+class TestError extends Error {}
+
+class TestIterator extends Iterator {
+ constructor(log) {
+ super();
+ this.log = log;
+ }
+
+ next() {
+ return {done: false, value: 0};
+ }
+
+ return(value) {
+ log.push('close iterator');
+ return {done: true, value};
+ }
+}
+
+const handlerProxy = log => new Proxy({}, {
+ get: (target, key, receiver) => (...args) => {
+ const target = args[0];
+ const item = Reflect[key](...args);
+
+ log.push(`${key}: ${args.filter(x => typeof x != 'object').map(x => x.toString())}`);
+
+ switch (typeof item) {
+ case 'function': return item.bind(new Proxy(target, handlerProxy(log)));
+ case 'object': return new Proxy(item, handlerProxy(log));
+ default: return item;
+ }
+ },
+});
+
+const log = [];
+const iterator = new TestIterator(log);
+const iteratorProxy = new Proxy(iterator, handlerProxy(log));
+const mappedProxy = iteratorProxy.map(x => x);
+
+mappedProxy.next();
+mappedProxy.return();
+mappedProxy.next();
+
+assertEq(
+ log.join('\n'),
+`get: map
+get: next
+get: return
+close iterator`
+);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion.js b/js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion.js
new file mode 100644
index 0000000000..ea0e10bdb4
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion.js
@@ -0,0 +1,54 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator'))
+//
+
+/*---
+esid: pending
+description: %Iterator.prototype%.map accesses specified properties only.
+info: >
+features: [iterator-helpers]
+---*/
+
+const handlerProxy = log => new Proxy({}, {
+ get: (target, key, receiver) => (...args) => {
+ const target = args[0];
+ const item = Reflect[key](...args);
+
+ log.push(`${key}: ${args.filter(x => typeof x != 'object').map(x => x.toString())}`);
+
+ switch (typeof item) {
+ case 'function': return item.bind(new Proxy(target, handlerProxy(log)));
+ case 'object': return new Proxy(item, handlerProxy(log));
+ default: return item;
+ }
+ },
+});
+
+const log = [];
+const iterator = Object.setPrototypeOf({
+ next: function() {
+ return { done: false, value: 0 };
+ },
+ return: function(value) {
+ log.push('close iterator');
+ return { done: true, value };
+ },
+}, Iterator.prototype);
+const iteratorProxy = new Proxy(iterator, handlerProxy(log));
+const mappedProxy = iteratorProxy.map(x => { throw 'error'; });
+
+try {
+ mappedProxy.next();
+} catch (exc) {
+ assertEq(exc, 'error');
+}
+
+assertEq(
+ log.join('\n'),
+`get: map
+get: next
+get: return
+close iterator`
+);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Iterator/prototype/map/proxy-accesses.js b/js/src/tests/non262/Iterator/prototype/map/proxy-accesses.js
new file mode 100644
index 0000000000..ba6dfd7ece
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/proxy-accesses.js
@@ -0,0 +1,94 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator'))
+//
+
+/*---
+esid: pending
+description: %Iterator.prototype%.map accesses specified properties only.
+info: >
+features: [iterator-helpers]
+---*/
+
+const handlerProxy = log => new Proxy({}, {
+ get: (target, key, receiver) => (...args) => {
+ const target = args[0];
+ const item = Reflect[key](...args);
+
+ log.push(`${key}: ${args.filter(x => typeof x != 'object').map(x => x.toString())}`);
+
+ switch (typeof item) {
+ case 'function': return item.bind(new Proxy(target, handlerProxy(log)));
+ case 'object': return new Proxy(item, handlerProxy(log));
+ default: return item;
+ }
+ },
+});
+
+const log = [];
+const iterator = Object.setPrototypeOf({
+ next: function() {
+ if (this.value < 3)
+ return { done: false, value: this.value++ };
+ return { done: true, value: undefined };
+ },
+ value: 0,
+}, Iterator.prototype);
+const iteratorProxy = new Proxy(iterator, handlerProxy(log));
+const mappedProxy = iteratorProxy.map(x => x);
+
+for (const item of mappedProxy) {
+}
+
+assertEq(
+ log.join('\n'),
+`get: map
+get: next
+get: value
+get: value
+getOwnPropertyDescriptor: value
+has: enumerable
+get: enumerable
+has: configurable
+get: configurable
+has: value
+get: value
+has: writable
+get: writable
+has: get
+has: set
+defineProperty: value
+set: value,1
+get: value
+get: value
+getOwnPropertyDescriptor: value
+has: enumerable
+get: enumerable
+has: configurable
+get: configurable
+has: value
+get: value
+has: writable
+get: writable
+has: get
+has: set
+defineProperty: value
+set: value,2
+get: value
+get: value
+getOwnPropertyDescriptor: value
+has: enumerable
+get: enumerable
+has: configurable
+get: configurable
+has: value
+get: value
+has: writable
+get: writable
+has: get
+has: set
+defineProperty: value
+set: value,3
+get: value`
+);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Iterator/prototype/map/reenter-map-generator-from-mapper.js b/js/src/tests/non262/Iterator/prototype/map/reenter-map-generator-from-mapper.js
new file mode 100644
index 0000000000..b7a0d56d5c
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/reenter-map-generator-from-mapper.js
@@ -0,0 +1,15 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator'))
+
+// Re-entering the map() generator from the called mapper fails.
+
+let iterator;
+function mapper(x) {
+ let n = iterator.next();
+ return x;
+}
+iterator = [0].values().map(mapper);
+
+assertThrowsInstanceOf(iterator.next, TypeError);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Iterator/prototype/map/this-not-iterator-throw.js b/js/src/tests/non262/Iterator/prototype/map/this-not-iterator-throw.js
new file mode 100644
index 0000000000..ac250db383
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/this-not-iterator-throw.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator'))
+//
+
+/*---
+esid: pending
+description: Eagerly throw TypeError when `this` is not an iterator.
+info:
+features: [iterator-helpers]
+---*/
+
+const mapper = (x) => x;
+
+assertThrowsInstanceOf(() => Iterator.prototype.map.call(undefined, mapper), TypeError);
+assertThrowsInstanceOf(() => Iterator.prototype.map.call(null, mapper), TypeError);
+assertThrowsInstanceOf(() => Iterator.prototype.map.call(0, mapper), TypeError);
+assertThrowsInstanceOf(() => Iterator.prototype.map.call(false, mapper), TypeError);
+assertThrowsInstanceOf(() => Iterator.prototype.map.call('', mapper), TypeError);
+assertThrowsInstanceOf(() => Iterator.prototype.map.call(new Symbol(''), mapper), TypeError);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Iterator/prototype/map/this-value-array-throws.js b/js/src/tests/non262/Iterator/prototype/map/this-value-array-throws.js
new file mode 100644
index 0000000000..3a13fefc97
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/this-value-array-throws.js
@@ -0,0 +1,14 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator'))
+//
+
+/*---
+esid: pending
+description: TypeError not thrown when `this` is an Array.
+info:
+features: [Symbol.iterator]
+---*/
+
+Iterator.prototype.map.call([], x => x);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Iterator/prototype/map/throw-when-iterator-returns-non-object.js b/js/src/tests/non262/Iterator/prototype/map/throw-when-iterator-returns-non-object.js
new file mode 100644
index 0000000000..287507a2f6
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/throw-when-iterator-returns-non-object.js
@@ -0,0 +1,24 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator'))
+//
+
+/*---
+esid: pending
+description: Throw TypeError if `next` call returns non-object.
+info:
+features: [iterator-helpers]
+---*/
+
+const iterator = returnValue => Object.setPrototypeOf({
+ next: () => returnValue,
+}, Iterator.prototype);
+const mapper = x => x;
+
+assertThrowsInstanceOf(() => iterator(undefined).map(mapper).next(), TypeError);
+assertThrowsInstanceOf(() => iterator(null).map(mapper).next(), TypeError);
+assertThrowsInstanceOf(() => iterator(0).map(mapper).next(), TypeError);
+assertThrowsInstanceOf(() => iterator(false).map(mapper).next(), TypeError);
+assertThrowsInstanceOf(() => iterator('').map(mapper).next(), TypeError);
+assertThrowsInstanceOf(() => iterator(Symbol()).map(mapper).next(), TypeError);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/Iterator/prototype/map/values-pass-through-chained-maps-to-next.js b/js/src/tests/non262/Iterator/prototype/map/values-pass-through-chained-maps-to-next.js
new file mode 100644
index 0000000000..1873017981
--- /dev/null
+++ b/js/src/tests/non262/Iterator/prototype/map/values-pass-through-chained-maps-to-next.js
@@ -0,0 +1,36 @@
+// |reftest| skip-if(!this.hasOwnProperty('Iterator'))
+//
+
+/*---
+esid: pending
+description: Multiple chained %Iterator.prototype%.map calls pass `lastValue` to the iterator's `next` call.
+info: >
+ Iterator Helpers Proposal 2.1.5.2
+features: [iterator-helpers]
+---*/
+
+const iteratorWhereNextTakesValue = Object.setPrototypeOf({
+ next: function(value) {
+ assertEq(arguments.length, 0);
+
+ if (this.value < 3)
+ return { done: false, value: this.value++ };
+ return { done: true, value: undefined };
+ },
+ value: 0,
+}, Iterator.prototype);
+
+const mappedIterator = iteratorWhereNextTakesValue.map(x => 2 * x).map(x => 1 + x);
+
+assertEq(mappedIterator.next(1).value, 1);
+
+assertEq(mappedIterator.next(2).value, 3);
+
+assertEq(mappedIterator.next(3).value, 5);
+
+assertEq(mappedIterator.next(4).done, true);
+
+assertEq(mappedIterator.next(5).done, true);
+
+if (typeof reportCompare == 'function')
+ reportCompare(0, 0);