зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1797724 - Part 5: Use consistent error messages when iterator method returns a non-object. r=mgaudet
This ensures `Array.fromAsync` uses the same error message as `Array.from` and normal iteration (`for-of` and `for-await-of`). This let's us also remove the `GetIterator` self-hosted function. Also renamed `asyncIterator` to `iterator`, because the returned iterator isn't an async iterator. Depends on D160478 Differential Revision: https://phabricator.services.mozilla.com/D160479
This commit is contained in:
Родитель
1c1c8e1864
Коммит
bc9d9090e4
|
@ -871,17 +871,27 @@ function ArrayFromAsync(asyncItems, mapfn = undefined, thisArg = undefined) {
|
|||
// Step 3.h. If usingAsyncIterator is not undefined, then
|
||||
if (usingAsyncIterator !== undefined) {
|
||||
// Step 3.h.i. Set iteratorRecord to ? GetIterator(asyncItems, async, usingAsyncIterator).
|
||||
iteratorRecord = GetIterator(asyncItems, "async", usingAsyncIterator);
|
||||
let iterator = callContentFunction(usingAsyncIterator, asyncItems);
|
||||
|
||||
if (!IsObject(iterator)) {
|
||||
ThrowTypeError(JSMSG_GET_ASYNC_ITER_RETURNED_PRIMITIVE);
|
||||
}
|
||||
|
||||
iteratorRecord = { iterator, nextMethod: iterator.next };
|
||||
} else if (usingSyncIterator !== undefined) {
|
||||
// Step 3.i. Else if usingSyncIterator is not undefined, then
|
||||
// Step 3.i.i. Set iteratorRecord to ? CreateAsyncFromSyncIterator(GetIterator(asyncItems, sync, usingSyncIterator)).
|
||||
let asyncIterator = GetIterator(asyncItems, "sync", usingSyncIterator);
|
||||
let iterator = callContentFunction(usingSyncIterator, asyncItems);
|
||||
|
||||
if (!IsObject(iterator)) {
|
||||
ThrowTypeError(JSMSG_GET_ITER_RETURNED_PRIMITIVE);
|
||||
}
|
||||
|
||||
// SpiderMonkey's CreateAsyncFromSyncIterator doesn't return an iterator record
|
||||
// with named slots; so we need to create our own iterator record.
|
||||
let asyncFromSyncIteratorObject = CreateAsyncFromSyncIterator(
|
||||
asyncIterator.iterator,
|
||||
asyncIterator.nextMethod
|
||||
iterator,
|
||||
iterator.next
|
||||
);
|
||||
|
||||
iteratorRecord = {
|
||||
|
|
|
@ -43,61 +43,6 @@ function IteratorClose(iteratorRecord, value) {
|
|||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* ES2022 draft rev c5f683e61d5dce703650f1c90d2309c46f8c157a
|
||||
*
|
||||
* GetIterator ( obj [ , hint [ , method ] ] )
|
||||
* https://tc39.es/ecma262/#sec-getiterator
|
||||
*
|
||||
*/
|
||||
function GetIterator(obj, hint = undefined, method = undefined) {
|
||||
// Step 1. If hint is not present, set hint to sync.
|
||||
if (hint === undefined) {
|
||||
hint = "sync";
|
||||
}
|
||||
|
||||
// Step 2. If method is not present, then
|
||||
if (method === undefined) {
|
||||
// Step 2.a. If hint is async, then
|
||||
if (hint === "async") {
|
||||
// Step 2.a.i. Set method to ? GetMethod(obj, @@asyncIterator).
|
||||
method = GetMethod(obj, GetBuiltinSymbol("asyncIterator"));
|
||||
// Step 2.a.ii. If method is undefined, then
|
||||
if (method === undefined) {
|
||||
// Step 2.a.ii.1. Let syncMethod be ? GetMethod(obj, @@iterator).
|
||||
let syncMethod = GetMethod(obj, GetBuiltinSymbol("iterator"));
|
||||
// Step 2.a.ii.2. Let syncIteratorRecord be ? GetIterator(obj, sync, syncMethod).
|
||||
let syncIteratorRecord = GetIterator(obj, "sync", syncMethod);
|
||||
// Step 2.a.ii.3. Return CreateAsyncFromSyncIterator(syncIteratorRecord).
|
||||
// (SpiderMonkey extracts the contents of the iterator record for this call.)
|
||||
return CreateAsyncFromSyncIterator(
|
||||
syncIteratorRecord.iterator,
|
||||
syncIteratorRecord.nextMethod
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Step 2.b. Otherwise, set method to ? GetMethod(obj, @@iterator).
|
||||
method = GetMethod(obj, GetBuiltinSymbol("iterator"));
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3. Let iterator be ? Call(method, obj).
|
||||
let iterator = callContentFunction(method, obj);
|
||||
// Step 4. If iterator is not an Object, throw a TypeError exception.
|
||||
if (!IsObject(iterator)) {
|
||||
ThrowTypeError(JSMSG_OBJECT_REQUIRED, iterator);
|
||||
}
|
||||
|
||||
// Step 5. Let nextMethod be ? GetV(iterator, "next").
|
||||
let nextMethod = iterator.next;
|
||||
|
||||
// Step 6. Let iteratorRecord be the Iterator Record { [[Iterator]]: iterator, [[NextMethod]]: nextMethod, [[Done]]: false }.
|
||||
let iteratorRecord = { iterator, nextMethod, done: false };
|
||||
|
||||
// Step 7. Return iteratorRecord.
|
||||
return iteratorRecord;
|
||||
}
|
||||
|
||||
/**
|
||||
* ES2022 draft rev c5f683e61d5dce703650f1c90d2309c46f8c157a
|
||||
*
|
||||
|
|
|
@ -133,5 +133,46 @@ assertEq(done, true);
|
|||
})();
|
||||
|
||||
drainJobQueue();
|
||||
|
||||
(async function() {
|
||||
var badSyncIterator = {
|
||||
[Symbol.iterator](){
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
var badAsyncIterator = {
|
||||
[Symbol.asyncIterator](){
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
async function errorMessage(fn) {
|
||||
try {
|
||||
await fn();
|
||||
} catch (e) {
|
||||
return e.message;
|
||||
}
|
||||
throw new Error("missing error");
|
||||
}
|
||||
|
||||
// Ensure Array.from and Array.fromAsync use consistent error reporting.
|
||||
var expected = await errorMessage(() => Array.from(badSyncIterator));
|
||||
var actual = await errorMessage(() => Array.fromAsync(badSyncIterator));
|
||||
assertEq(actual, expected);
|
||||
|
||||
// Ensure for-of iteration and Array.fromAsync use consistent error reporting.
|
||||
var expected = await errorMessage(() => { for (var _ of badSyncIterator); });
|
||||
var actual = await errorMessage(() => Array.fromAsync(badSyncIterator));
|
||||
assertEq(actual, expected);
|
||||
|
||||
// Ensure await for-of iteration and Array.fromAsync use consistent error reporting.
|
||||
var expected = await errorMessage(async () => { for await (var _ of badAsyncIterator); });
|
||||
var actual = await errorMessage(() => Array.fromAsync(badAsyncIterator));
|
||||
assertEq(actual, expected);
|
||||
})();
|
||||
|
||||
drainJobQueue();
|
||||
|
||||
if (typeof reportCompare === 'function')
|
||||
reportCompare(true, true);
|
Загрузка…
Ссылка в новой задаче