Skip to content

Commit

Permalink
[Breaking] 2018/2019: GetIterator: Add hint parameter
Browse files Browse the repository at this point in the history
BREAKING CHANGE: This is backwards incompatible, as the `hint` parameter is added between the `obj` and `method` parameters.
  • Loading branch information
ExE-Boss authored and ljharb committed Nov 4, 2019
1 parent ddbba60 commit b967be4
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 34 deletions.
4 changes: 2 additions & 2 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,6 @@
2018/DeletePropertyOrThrow.js spackled linguist-generated=true
2018/FromPropertyDescriptor.js spackled linguist-generated=true
2018/Get.js spackled linguist-generated=true
2018/GetIterator.js spackled linguist-generated=true
2018/GetMethod.js spackled linguist-generated=true
2018/GetOwnPropertyKeys.js spackled linguist-generated=true
2018/GetPrototypeFromConstructor.js spackled linguist-generated=true
Expand All @@ -302,7 +301,6 @@
2018/IsPromise.js spackled linguist-generated=true
2018/IsPropertyKey.js spackled linguist-generated=true
2018/IsRegExp.js spackled linguist-generated=true
2018/IterableToList.js spackled linguist-generated=true
2018/IteratorClose.js spackled linguist-generated=true
2018/IteratorComplete.js spackled linguist-generated=true
2018/IteratorNext.js spackled linguist-generated=true
Expand Down Expand Up @@ -519,6 +517,7 @@
2020/EnumerableOwnPropertyNames.js spackled linguist-generated=true
2020/FromPropertyDescriptor.js spackled linguist-generated=true
2020/Get.js spackled linguist-generated=true
2020/GetIterator.js spackled linguist-generated=true
2020/GetMethod.js spackled linguist-generated=true
2020/GetOwnPropertyKeys.js spackled linguist-generated=true
2020/GetPrototypeFromConstructor.js spackled linguist-generated=true
Expand All @@ -543,6 +542,7 @@
2020/IsPropertyKey.js spackled linguist-generated=true
2020/IsRegExp.js spackled linguist-generated=true
2020/IsStringPrefix.js spackled linguist-generated=true
2020/IterableToList.js spackled linguist-generated=true
2020/IteratorClose.js spackled linguist-generated=true
2020/IteratorComplete.js spackled linguist-generated=true
2020/IteratorNext.js spackled linguist-generated=true
Expand Down
45 changes: 36 additions & 9 deletions 2018/GetIterator.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
var GetIntrinsic = require('../GetIntrinsic');

var $TypeError = GetIntrinsic('%TypeError%');
var $asyncIterator = GetIntrinsic('%Symbol.asyncIterator%', true);

var inspect = require('object-inspect');
var hasSymbols = require('has-symbols')();

var getIteratorMethod = require('../helpers/getIteratorMethod');
var AdvanceStringIndex = require('./AdvanceStringIndex');
Expand All @@ -11,25 +15,48 @@ var GetMethod = require('./GetMethod');
var IsArray = require('./IsArray');
var Type = require('./Type');

// https://ecma-international.org/ecma-262/6.0/#sec-getiterator

module.exports = function GetIterator(obj, method) {
var actualMethod = method;
// https://ecma-international.org/ecma-262/9.0/#sec-getiterator
module.exports = function GetIterator(obj, hint, method) {
var actualHint = hint;
if (arguments.length < 2) {
actualMethod = getIteratorMethod(
{
actualHint = 'sync';
}
if (actualHint !== 'sync' && actualHint !== 'async') {
throw new $TypeError("Assertion failed: `hint` must be one of 'sync' or 'async', got " + inspect(hint));
}
var actualMethod = method;
if (arguments.length < 3) {
if (actualHint === 'async') {
if (hasSymbols && $asyncIterator) {
actualMethod = GetMethod(obj, $asyncIterator);
}
if (actualMethod === undefined) {
throw new $TypeError("async from sync iterators aren't currently supported");
}
} else {
actualMethod = getIteratorMethod({
AdvanceStringIndex: AdvanceStringIndex,
GetMethod: GetMethod,
IsArray: IsArray,
Type: Type
},
obj
);
}, obj);
}
}

var iterator = Call(actualMethod, obj);
if (Type(iterator) !== 'Object') {
throw new $TypeError('iterator must return an object');
}

return iterator;

// TODO: This should return an IteratorRecord
/*
var nextMethod = GetV(iterator, 'next');
return {
'[[Iterator]]': iterator,
'[[NextMethod]]': nextMethod,
'[[Done]]': false
};
*/
};
4 changes: 2 additions & 2 deletions 2018/IterableToList.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ var GetIterator = require('./GetIterator');
var IteratorStep = require('./IteratorStep');
var IteratorValue = require('./IteratorValue');

// https://www.ecma-international.org/ecma-262/8.0/#sec-iterabletolist
// https://www.ecma-international.org/ecma-262/9.0/#sec-iterabletolist

module.exports = function IterableToList(items, method) {
var iterator = GetIterator(items, method);
var iterator = GetIterator(items, 'sync', method);
var values = [];
var next = true;
while (next) {
Expand Down
45 changes: 36 additions & 9 deletions 2019/GetIterator.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions 2019/IterableToList.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 7 additions & 10 deletions 2020/GetIterator.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions test/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -4000,6 +4000,56 @@ var es2018 = function ES2018(ES, ops, expectedMissing, skips) {
t.end();
});

test('GetIterator', function (t) {
try {
ES.GetIterator({}, null);
} catch (e) {
t.ok(e.message.indexOf("Assertion failed: `hint` must be one of 'sync' or 'async'" >= 0));
}

var arr = [1, 2];
testIterator(t, ES.GetIterator(arr), arr);

testIterator(t, ES.GetIterator('abc'), 'abc'.split(''));

t.test('Symbol.iterator', { skip: !v.hasSymbols }, function (st) {
var m = new Map();
m.set(1, 'a');
m.set(2, 'b');

testIterator(st, ES.GetIterator(m), [[1, 'a'], [2, 'b']]);

st.end();
});

t.test('Symbol.asyncIterator', { skip: !v.hasSymbols || !Symbol.asyncIterator }, function (st) {
try {
ES.GetIterator(arr, 'async');
} catch (e) {
st.ok(e.message.indexOf("async from sync iterators aren't currently supported") >= 0);
}

/** @type {AsyncIterator<any>} */
var it = {
next: function () {
return Promise.resolve({
done: true
});
}
};
var obj = {};
obj[Symbol.asyncIterator] = function () {
return it;
};

st.equal(ES.GetIterator(obj, 'async'), it);

st.end();
});

t.end();
});

test('PromiseResolve', function (t) {
t.test('Promises unsupported', { skip: typeof Promise === 'function' }, function (st) {
st['throws'](
Expand Down

0 comments on commit b967be4

Please sign in to comment.