mirror of
				https://github.com/tc39/test262.git
				synced 2025-11-03 21:24:30 +01:00 
			
		
		
		
	sourceRevisionAtLastExport: 33f2fb0e53d135f0ee17cfccd9d993eb2a6f47de targetRevisionAtLastExport: 31340cbd9add103f586d501b0c3354b7b182abc0
		
			
				
	
	
		
			766 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			766 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
// Copyright 2017 the V8 project authors. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style license that can be
 | 
						|
// found in the LICENSE file.
 | 
						|
 | 
						|
// Flags: --allow-natives-syntax
 | 
						|
 | 
						|
let testFailed = false;
 | 
						|
let testFailure;
 | 
						|
 | 
						|
function assertThrowsAsync(run, errorType, message) {
 | 
						|
  var actual;
 | 
						|
  var hadValue = false;
 | 
						|
  var hadError = false;
 | 
						|
  var promise = run();
 | 
						|
 | 
						|
  if (typeof promise !== "object" || typeof promise.then !== "function") {
 | 
						|
    throw new MjsUnitAssertionError(
 | 
						|
        "Expected " + run.toString() +
 | 
						|
        " to return a Promise, but it returned " + PrettyPrint(promise));
 | 
						|
  }
 | 
						|
 | 
						|
  promise.then(function(value) { hadValue = true; actual = value; },
 | 
						|
               function(error) { hadError = true; actual = error; });
 | 
						|
 | 
						|
  assertFalse(hadValue || hadError);
 | 
						|
 | 
						|
  %RunMicrotasks();
 | 
						|
 | 
						|
  if (!hadError) {
 | 
						|
    throw new MjsUnitAssertionError(
 | 
						|
        "Expected " + run + "() to throw " + errorType.name +
 | 
						|
        ", but did not throw.");
 | 
						|
  }
 | 
						|
  if (!(actual instanceof errorType))
 | 
						|
    throw new MjsUnitAssertionError(
 | 
						|
        "Expected " + run + "() to throw " + errorType.name +
 | 
						|
        ", but threw '" + actual + "'");
 | 
						|
  if (message !== void 0 && actual.message !== message)
 | 
						|
    throw new MjsUnitAssertionError(
 | 
						|
        "Expected " + run + "() to throw '" + message + "', but threw '" +
 | 
						|
        actual.message + "'");
 | 
						|
};
 | 
						|
 | 
						|
function resolveLater(value) {
 | 
						|
  return new Promise(function(resolve) {
 | 
						|
    Promise.resolve().then(function() {
 | 
						|
      resolve(value);
 | 
						|
    });
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function rejectLater(value) {
 | 
						|
  return new Promise(function(resolve, reject) {
 | 
						|
    Promise.resolve().then(function() {
 | 
						|
      reject(value);
 | 
						|
    });
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
const kNext = 1;
 | 
						|
const kThrow = 2;
 | 
						|
const kReturn = 4;
 | 
						|
const kNextThrows = kNext | 8;
 | 
						|
const kReturnThrows = kReturn | 16;
 | 
						|
const kThrowNormal = kThrow | 32;
 | 
						|
const kNextUnchanged = kNext | 64;
 | 
						|
const kReturnUnchanged = kReturn | 128;
 | 
						|
const kThrowUnchanged = kThrow | 256;
 | 
						|
function sync(array, features, log) {
 | 
						|
  // `log` is a required parameter
 | 
						|
  if (log === void 0) %AbortJS("`log` is undefined");
 | 
						|
 | 
						|
  let i = 0;
 | 
						|
  let methods = {
 | 
						|
    next(sent) {
 | 
						|
      let done = i >= array.length;
 | 
						|
      let value = array[i];
 | 
						|
      log.push({ method: "next", sent, value, done });
 | 
						|
      if ((features & kNextThrows) === kNextThrows) throw sent;
 | 
						|
      if ((features & kNextUnchanged) === kNextUnchanged) return sent;
 | 
						|
      i++;
 | 
						|
      return { value, done };
 | 
						|
    },
 | 
						|
    throw(sent) {
 | 
						|
      let done = i >= array.length;
 | 
						|
      log.push({ method: "throw", sent, done });
 | 
						|
      if ((features & kThrowNormal) === kThrowNormal)
 | 
						|
          return { value: sent, done };
 | 
						|
      if ((features & kThrowUnchanged) === kThrowUnchanged) return sent;
 | 
						|
      throw sent;
 | 
						|
    },
 | 
						|
    return(sent) {
 | 
						|
      let done = true;
 | 
						|
      log.push({ method: "return", sent, done });
 | 
						|
      if ((features & kReturnThrows) === kReturnThrows) throw sent;
 | 
						|
      if ((features & kReturnUnchanged) === kReturnUnchanged) return sent;
 | 
						|
      return { value: sent, done };
 | 
						|
    }
 | 
						|
  };
 | 
						|
  return {
 | 
						|
    [Symbol.iterator]() { return this; },
 | 
						|
    next: (features & kNext) ? methods.next : undefined,
 | 
						|
    throw: (features & kThrow) ? methods.throw : undefined,
 | 
						|
    return: (features & kReturn) ? methods.return : undefined
 | 
						|
  };
 | 
						|
}
 | 
						|
 | 
						|
class MyError extends Error {};
 | 
						|
 | 
						|
(async function AsyncFromSyncWithGenerator() {
 | 
						|
  function* gen() {
 | 
						|
    yield "sync value";
 | 
						|
    try {
 | 
						|
      yield new Promise(function(resolve) {
 | 
						|
        resolve("async value");
 | 
						|
      });
 | 
						|
    } catch (error) {
 | 
						|
      throw error;
 | 
						|
    }
 | 
						|
    assertUnreachable("generator is closed");
 | 
						|
  }
 | 
						|
  let iter = %CreateAsyncFromSyncIterator(gen());
 | 
						|
 | 
						|
  // [Async-from-Sync Iterator] wraps sync iterator values in a Promise
 | 
						|
  let promise = iter.next();
 | 
						|
  assertInstanceof(promise, Promise);
 | 
						|
  let iter_result = await promise;
 | 
						|
  assertEquals({ value: "sync value", done: false }, iter_result);
 | 
						|
 | 
						|
  // [Async-from-Sync Iterator] will wait for resolution of Promise values
 | 
						|
  promise = iter.next();
 | 
						|
  assertInstanceof(promise, Promise);
 | 
						|
  iter_result = await promise;
 | 
						|
  assertEquals({ value: "async value", done: false }, iter_result);
 | 
						|
 | 
						|
  // [Async-from-Sync Iterator].throw delegates to .throw() method of sync
 | 
						|
  // iterator.
 | 
						|
  promise = iter.throw(new MyError("Error#1"));
 | 
						|
  assertInstanceof(promise, Promise);
 | 
						|
  try {
 | 
						|
    await promise;
 | 
						|
    assertUnreachable("promise should be rejected");
 | 
						|
  } catch (e) {
 | 
						|
    // If assertUnreachable failed, rethrow
 | 
						|
    if (e instanceof MjsUnitAssertionError) throw e;
 | 
						|
    assertInstanceof(e, MyError);
 | 
						|
    assertEquals("Error#1", e.message);
 | 
						|
  }
 | 
						|
 | 
						|
  // Generator is closed, subsequent calls to .next() will not resume.
 | 
						|
  promise = iter.next("floof");
 | 
						|
  iter_result = await promise;
 | 
						|
  assertEquals({ value: undefined, done: true }, iter_result);
 | 
						|
 | 
						|
  promise = iter.return("generator closed");
 | 
						|
  assertInstanceof(promise, Promise);
 | 
						|
  iter_result = await promise;
 | 
						|
  assertEquals({ value: "generator closed", done: true }, iter_result);
 | 
						|
 | 
						|
  // .next(), .return() and .throw() delegate to sync iterator methods, without
 | 
						|
  // keeping track of the state of the generator.
 | 
						|
  promise = iter.next("unused");
 | 
						|
  assertInstanceof(promise, Promise);
 | 
						|
  iter_result = await promise;
 | 
						|
  assertEquals({ value: undefined, done: true }, iter_result);
 | 
						|
 | 
						|
  promise = iter.throw(new MyError("Error#2"));
 | 
						|
  assertInstanceof(promise, Promise);
 | 
						|
  try {
 | 
						|
    await promise;
 | 
						|
    assertUnreachable("promise should be rejected");
 | 
						|
  } catch (e) {
 | 
						|
    // If assertUnreachable failed, rethrow
 | 
						|
    if (e instanceof MjsUnitAssertionError) throw e;
 | 
						|
    assertInstanceof(e, MyError);
 | 
						|
    assertEquals("Error#2", e.message);
 | 
						|
  }
 | 
						|
 | 
						|
  promise = iter.return("return-after-completed");
 | 
						|
  assertInstanceof(promise, Promise);
 | 
						|
  iter_result = await promise;
 | 
						|
  assertEquals({ value: "return-after-completed", done: true }, iter_result);
 | 
						|
})().catch(function(error) {
 | 
						|
  testFailed = true;
 | 
						|
  testFailure = error;
 | 
						|
});
 | 
						|
 | 
						|
%RunMicrotasks();
 | 
						|
if (testFailed) {
 | 
						|
  throw testFailure;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
(async function AsyncFromSyncOrderOfOperations() {
 | 
						|
  let log = [];
 | 
						|
  iter = %CreateAsyncFromSyncIterator(sync(["sync-value"], 0, log));
 | 
						|
 | 
						|
  try {
 | 
						|
    await iter.next();
 | 
						|
    assertUnreachable("Iterator.next() method is not optional");
 | 
						|
  } catch (e) {
 | 
						|
    assertInstanceof(e, TypeError);
 | 
						|
    assertEquals([], log);
 | 
						|
  }
 | 
						|
 | 
						|
  log = [];
 | 
						|
  iter = %CreateAsyncFromSyncIterator(sync(["sync-value"], kNext, log));
 | 
						|
  assertEquals({ value: "sync-value", done: false }, await iter.next("a"));
 | 
						|
  assertEquals([
 | 
						|
    {
 | 
						|
      method: "next",
 | 
						|
      sent: "a",
 | 
						|
      value: "sync-value",
 | 
						|
      done: false
 | 
						|
    }
 | 
						|
  ], log);
 | 
						|
 | 
						|
  log = [];
 | 
						|
  let asyncValue = resolveLater("async-value");
 | 
						|
  iter = %CreateAsyncFromSyncIterator(sync([asyncValue], kNext, log));
 | 
						|
  assertEquals({ value: "async-value", done: false }, await iter.next("b"));
 | 
						|
  assertEquals([
 | 
						|
    {
 | 
						|
      method: "next",
 | 
						|
      sent: "b",
 | 
						|
      value: asyncValue,
 | 
						|
      done: false
 | 
						|
    }
 | 
						|
  ], log);
 | 
						|
 | 
						|
  // If [sync_iterator].next() produces a rejected Promise or an exception is
 | 
						|
  // thrown, Promise is rejected with thrown/rejected value.
 | 
						|
  log = [];
 | 
						|
  asyncValue = rejectLater("Boo!");
 | 
						|
  iter = %CreateAsyncFromSyncIterator(sync([asyncValue], kNext, log));
 | 
						|
  try {
 | 
						|
    await iter.next('c');
 | 
						|
    assertUnreachable('Expected `iter.next(\'c\') to throw, but did not throw');
 | 
						|
  } catch (e) {
 | 
						|
    assertEquals("Boo!", e);
 | 
						|
    assertEquals([
 | 
						|
      {
 | 
						|
        method: 'next',
 | 
						|
        sent: 'c',
 | 
						|
        value: asyncValue,
 | 
						|
        done: false
 | 
						|
      }
 | 
						|
    ], log);
 | 
						|
  }
 | 
						|
 | 
						|
  log = [];
 | 
						|
  iter = %CreateAsyncFromSyncIterator(sync(['sync-value'], kNextThrows, log));
 | 
						|
  try {
 | 
						|
    await iter.next('Boo!');
 | 
						|
    assertUnreachable('Expected `iter.next(\'c\') to throw, but did not throw');
 | 
						|
  } catch (e) {
 | 
						|
    assertEquals("Boo!", e);
 | 
						|
    assertEquals([
 | 
						|
      {
 | 
						|
        method: 'next',
 | 
						|
        sent: 'Boo!',
 | 
						|
        value: 'sync-value',
 | 
						|
        done: false
 | 
						|
      }
 | 
						|
    ], log);
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  // [Async-from-Sync Iterator].next() will be rejected with a TypeError if
 | 
						|
  // Type([sync_iterator].next()) is not Object.
 | 
						|
  log = [];
 | 
						|
  iter = %CreateAsyncFromSyncIterator(sync(['sync-value'], kNextUnchanged,
 | 
						|
                                      log));
 | 
						|
  try {
 | 
						|
    await iter.next('not-a-JSReceiver');
 | 
						|
    assertUnreachable('Expected `iter.next(\'not-a-JSReceiver\')` to ' +
 | 
						|
                      'throw, but did not throw')
 | 
						|
  } catch (e) {
 | 
						|
    assertEquals(e.constructor, TypeError);
 | 
						|
  }
 | 
						|
 | 
						|
  assertEquals([
 | 
						|
    {
 | 
						|
      method: 'next',
 | 
						|
      sent: 'not-a-JSReceiver',
 | 
						|
      value: 'sync-value',
 | 
						|
      done: false
 | 
						|
    }
 | 
						|
  ], log);
 | 
						|
 | 
						|
  // If [sync_iterator] does not have a .return() method, return a Promise
 | 
						|
  // resolved with the value `{ value: <<sent value>>, done: true }`.
 | 
						|
  log = [];
 | 
						|
  iter = %CreateAsyncFromSyncIterator(sync(['sync-return'], kNext, log));
 | 
						|
  assertEquals({
 | 
						|
    value: 'd',
 | 
						|
    done: true
 | 
						|
  }, await iter.return('d'));
 | 
						|
 | 
						|
  // [Async-from-Sync Iterator] merely delegates, and does not keep track of
 | 
						|
  // whether [sync_iterator] is completed or not.
 | 
						|
  assertEquals({
 | 
						|
    value: 'sync-return',
 | 
						|
    done: false
 | 
						|
  }, await iter.next('e'));
 | 
						|
 | 
						|
  assertEquals([
 | 
						|
    {
 | 
						|
      method: 'next',
 | 
						|
      sent: 'e',
 | 
						|
      value: 'sync-return',
 | 
						|
      done: false
 | 
						|
    }
 | 
						|
  ], log);
 | 
						|
 | 
						|
  // If [sync_iterator] does have a .return() method, return a Promise
 | 
						|
  // fulfilled with the iterator result of [sync_iterator].return().
 | 
						|
  log = [];
 | 
						|
  iter = %CreateAsyncFromSyncIterator(sync(['sync-return'],
 | 
						|
                                      kNext|kReturn, log));
 | 
						|
  assertEquals({
 | 
						|
    value: 'f',
 | 
						|
    done: true
 | 
						|
  }, await iter.return('f'));
 | 
						|
 | 
						|
  // [Async-from-Sync Iterator] merely delegates, and does not keep track of
 | 
						|
  // whether [sync_iterator] is completed or not.
 | 
						|
  assertEquals({
 | 
						|
    value: 'sync-return',
 | 
						|
    done: false
 | 
						|
  }, await iter.next('g'));
 | 
						|
 | 
						|
  assertEquals([
 | 
						|
    {
 | 
						|
      method: 'return',
 | 
						|
      sent: 'f',
 | 
						|
      done: true
 | 
						|
    },
 | 
						|
    {
 | 
						|
      method: 'next',
 | 
						|
      sent: 'g',
 | 
						|
      value: 'sync-return',
 | 
						|
      done: false
 | 
						|
    }
 | 
						|
  ], log);
 | 
						|
 | 
						|
  // If [sync_iterator].return() produces a rejected Promise or an exception is
 | 
						|
  // thrown, Promise is rejected with thrown/rejected value.
 | 
						|
  log = [];
 | 
						|
  iter = %CreateAsyncFromSyncIterator(sync(['sync-value'], kNext|kReturnThrows,
 | 
						|
                                      log));
 | 
						|
  try {
 | 
						|
    await iter.return('Boo!!');
 | 
						|
    assertUnreachable('Expected `iter.return(\'Boo!!\')` to throw, but did ' +
 | 
						|
                      'not throw');
 | 
						|
  } catch (e) {
 | 
						|
    assertEquals("Boo!!", e);
 | 
						|
  }
 | 
						|
 | 
						|
  // [Async-from-Sync Iterator] merely delegates, and does not keep track of
 | 
						|
  // whether [sync_iterator] is completed or not.
 | 
						|
  assertEquals({ value: 'sync-value', done: false }, await iter.next('h'));
 | 
						|
  assertEquals([
 | 
						|
    {
 | 
						|
      method: 'return',
 | 
						|
      sent: 'Boo!!',
 | 
						|
      done: true
 | 
						|
    },
 | 
						|
    {
 | 
						|
      method: 'next',
 | 
						|
      sent: 'h',
 | 
						|
      value: 'sync-value',
 | 
						|
      done: false
 | 
						|
    }
 | 
						|
  ], log);
 | 
						|
 | 
						|
 | 
						|
  log = [];
 | 
						|
  iter = %CreateAsyncFromSyncIterator(sync(['sync-value'], kNext|kReturn, log));
 | 
						|
 | 
						|
  let rejection = Promise.reject('Boo!!');
 | 
						|
  try {
 | 
						|
    await iter.return(rejection);
 | 
						|
    assertUnreachable('Expected `iter.return(Promise.reject(\'Boo!!\'))` to ' +
 | 
						|
                      'throw, but did not throw');
 | 
						|
  } catch (e) {
 | 
						|
    assertEquals('Boo!!', e);
 | 
						|
  }
 | 
						|
 | 
						|
  // [Async-from-Sync Iterator] merely delegates, and does not keep track of
 | 
						|
  // whether [sync_iterator] is completed or not.
 | 
						|
  assertEquals({ value: 'sync-value', done: false }, await iter.next('i'));
 | 
						|
  assertEquals([
 | 
						|
    {
 | 
						|
      method: 'return',
 | 
						|
      sent: rejection,
 | 
						|
      done: true
 | 
						|
    },
 | 
						|
    {
 | 
						|
      method: 'next',
 | 
						|
      sent: 'i',
 | 
						|
      value: 'sync-value',
 | 
						|
      done: false
 | 
						|
    }
 | 
						|
  ], log);
 | 
						|
 | 
						|
  // [Async-from-Sync Iterator].return() will be rejected with a TypeError if
 | 
						|
  // Type([sync_iterator].return()) is not Object.
 | 
						|
  log = [];
 | 
						|
  iter = %CreateAsyncFromSyncIterator(sync(['sync-value'],
 | 
						|
                                      kNext|kReturnUnchanged, log));
 | 
						|
  try {
 | 
						|
    await iter.return('not-a-JSReceiver');
 | 
						|
    assertUnreachable('Expected `iter.return(\'not-a-JSReceiver\')` to ' +
 | 
						|
                      'throw, but did not throw')
 | 
						|
  } catch (e) {
 | 
						|
    assertEquals(e.constructor, TypeError);
 | 
						|
  }
 | 
						|
 | 
						|
  // [Async-from-Sync Iterator] merely delegates, and does not keep track of
 | 
						|
  // whether [sync_iterator] is completed or not.
 | 
						|
  assertEquals({ value: 'sync-value', done: false }, await iter.next('j'));
 | 
						|
  assertEquals([
 | 
						|
    {
 | 
						|
      method: 'return',
 | 
						|
      sent: 'not-a-JSReceiver',
 | 
						|
      done: true
 | 
						|
    },
 | 
						|
    {
 | 
						|
      method: 'next',
 | 
						|
      sent: 'j',
 | 
						|
      value: 'sync-value',
 | 
						|
      done: false
 | 
						|
    }
 | 
						|
  ], log);
 | 
						|
 | 
						|
  // If [sync_iterator] does not have a .throw method, return a Promise rejected
 | 
						|
  // with the sent value.
 | 
						|
  log = [];
 | 
						|
  iter = %CreateAsyncFromSyncIterator(sync(['sync-value'], kNext, log));
 | 
						|
  try {
 | 
						|
    await iter.throw('Boo!!');
 | 
						|
    assertUnreachable('Expected iter.throw(\'Boo!!\') to throw, but did not ' +
 | 
						|
                      'throw');
 | 
						|
  } catch (e) {
 | 
						|
    assertEquals('Boo!!', e);
 | 
						|
  }
 | 
						|
 | 
						|
  // [Async-from-Sync Iterator] merely delegates, and does not keep track of
 | 
						|
  // whether [sync_iterator] is completed or not.
 | 
						|
  assertEquals({ value: 'sync-value', done: false }, await iter.next('k'));
 | 
						|
  assertEquals([
 | 
						|
    {
 | 
						|
      method: 'next',
 | 
						|
      sent: 'k',
 | 
						|
      value: 'sync-value',
 | 
						|
      done: false
 | 
						|
    }
 | 
						|
  ], log);
 | 
						|
 | 
						|
 | 
						|
  log = [];
 | 
						|
  iter = %CreateAsyncFromSyncIterator(sync(['sync-value'], kNext|kThrow, log));
 | 
						|
  try {
 | 
						|
    await iter.throw('Boo!!');
 | 
						|
    assertUnreachable('Expected iter.throw(\'Boo!!\') to throw, but did not ' +
 | 
						|
                      'throw');
 | 
						|
  } catch (e) {
 | 
						|
    assertEquals('Boo!!', e);
 | 
						|
  }
 | 
						|
 | 
						|
  // [Async-from-Sync Iterator] merely delegates, and does not keep track of
 | 
						|
  // whether [sync_iterator] is completed or not.
 | 
						|
  assertEquals({ value: 'sync-value', done: false }, await iter.next('l'));
 | 
						|
  assertEquals([
 | 
						|
    {
 | 
						|
      method: 'throw',
 | 
						|
      sent: 'Boo!!',
 | 
						|
      done: false
 | 
						|
    },
 | 
						|
    {
 | 
						|
      method: 'next',
 | 
						|
      sent: 'l',
 | 
						|
      value: 'sync-value',
 | 
						|
      done: false
 | 
						|
    }
 | 
						|
  ], log);
 | 
						|
 | 
						|
  // If [sync_iterator].throw() returns a resolved Promise or a Completion
 | 
						|
  // with [[Type]] "normal" or "return", return a resolved Promise
 | 
						|
  log = [];
 | 
						|
  iter = %CreateAsyncFromSyncIterator(sync(['sync-value'], kNext|kThrowNormal,
 | 
						|
                                      log));
 | 
						|
  assertEquals({
 | 
						|
    value: 'Boo!!',
 | 
						|
    done: false
 | 
						|
  }, await iter.throw('Boo!!'));
 | 
						|
 | 
						|
  // [Async-from-Sync Iterator] merely delegates, and does not keep track of
 | 
						|
  // whether [sync_iterator] is completed or not.
 | 
						|
  assertEquals({ value: 'sync-value', done: false }, await iter.next('m'));
 | 
						|
  assertEquals([
 | 
						|
    {
 | 
						|
      method: 'throw',
 | 
						|
      sent: 'Boo!!',
 | 
						|
      done: false
 | 
						|
    },
 | 
						|
    {
 | 
						|
      method: 'next',
 | 
						|
      sent: 'm',
 | 
						|
      value: 'sync-value',
 | 
						|
      done: false
 | 
						|
    }
 | 
						|
  ], log);
 | 
						|
 | 
						|
  // [Async-from-Sync Iterator].throw() will be rejected with a TypeError if
 | 
						|
  // Type([sync_iterator].throw()) is not Object.
 | 
						|
  log = [];
 | 
						|
  iter = %CreateAsyncFromSyncIterator(sync(['sync-value'],
 | 
						|
                                      kNext|kThrowUnchanged, log));
 | 
						|
  try {
 | 
						|
    await iter.throw('not-a-JSReceiver');
 | 
						|
    assertUnreachable('Expected `iter.throw(\'not-a-JSReceiver\')` to ' +
 | 
						|
                      'throw, but did not throw')
 | 
						|
  } catch (e) {
 | 
						|
    assertEquals(e.constructor, TypeError);
 | 
						|
  }
 | 
						|
 | 
						|
  // [Async-from-Sync Iterator] merely delegates, and does not keep track of
 | 
						|
  // whether [sync_iterator] is completed or not.
 | 
						|
  assertEquals({ value: 'sync-value', done: false }, await iter.next('n'));
 | 
						|
  assertEquals([
 | 
						|
    {
 | 
						|
      method: 'throw',
 | 
						|
      sent: 'not-a-JSReceiver',
 | 
						|
      done: false
 | 
						|
    },
 | 
						|
    {
 | 
						|
      method: 'next',
 | 
						|
      sent: 'n',
 | 
						|
      value: 'sync-value',
 | 
						|
      done: false
 | 
						|
    }
 | 
						|
  ], log);
 | 
						|
 | 
						|
  // Let nextValue be IteratorValue(nextResult).
 | 
						|
  // IfAbruptRejectPromise(nextValue, promiseCapability).)
 | 
						|
  iter = %CreateAsyncFromSyncIterator({
 | 
						|
    next() { return { get value() { throw "BadValue!" }, done: false }; }
 | 
						|
  });
 | 
						|
  try {
 | 
						|
    await iter.next();
 | 
						|
    assertUnreachable('Expected `iter.next()` to throw, but did not throw');
 | 
						|
  } catch (e) {
 | 
						|
    assertEquals('BadValue!', e);
 | 
						|
  }
 | 
						|
 | 
						|
  // Let nextDone be IteratorComplete(nextResult).
 | 
						|
  // IfAbruptRejectPromise(nextDone, promiseCapability).
 | 
						|
  iter = %CreateAsyncFromSyncIterator({
 | 
						|
    next() { return { value: undefined, get done() { throw "BadValue!" } }; }
 | 
						|
  });
 | 
						|
  try {
 | 
						|
    await iter.next();
 | 
						|
    assertUnreachable('Expected `iter.next()` to throw, but did not throw');
 | 
						|
  } catch (e) {
 | 
						|
    assertEquals('BadValue!', e);
 | 
						|
  }
 | 
						|
 | 
						|
  // IfAbruptRejectPromise(returnResult, promiseCapability).
 | 
						|
  // Let returnValue be IteratorValue(returnResult).
 | 
						|
  iter = %CreateAsyncFromSyncIterator({
 | 
						|
    return() { return { get value() { throw "BadValue!" }, done: false }; }
 | 
						|
  });
 | 
						|
  try {
 | 
						|
    await iter.return();
 | 
						|
    assertUnreachable('Expected `iter.return()` to throw, but did not throw');
 | 
						|
  } catch (e) {
 | 
						|
    assertEquals('BadValue!', e);
 | 
						|
  }
 | 
						|
 | 
						|
  // IfAbruptRejectPromise(returnValue, promiseCapability).
 | 
						|
  // Let returnDone be IteratorComplete(returnResult).
 | 
						|
  iter = %CreateAsyncFromSyncIterator({
 | 
						|
    return() { return { value: undefined, get done() { throw "BadValue!" } }; }
 | 
						|
  });
 | 
						|
  try {
 | 
						|
    await iter.return();
 | 
						|
    assertUnreachable('Expected `iter.return()` to throw, but did not throw');
 | 
						|
  } catch (e) {
 | 
						|
    assertEquals('BadValue!', e);
 | 
						|
  }
 | 
						|
 | 
						|
  // IfAbruptRejectPromise(throwResult, promiseCapability).
 | 
						|
  // Let throwValue be IteratorValue(throwResult).
 | 
						|
  iter = %CreateAsyncFromSyncIterator({
 | 
						|
    throw() { return { get value() { throw "BadValue!" }, done: false }; }
 | 
						|
  });
 | 
						|
  try {
 | 
						|
    await iter.throw();
 | 
						|
    assertUnreachable('Expected `iter.throw()` to throw, but did not throw');
 | 
						|
  } catch (e) {
 | 
						|
    assertEquals('BadValue!', e);
 | 
						|
  }
 | 
						|
 | 
						|
  // IfAbruptRejectPromise(throwValue, promiseCapability).
 | 
						|
  // Let throwDone be IteratorComplete(throwResult).
 | 
						|
  iter = %CreateAsyncFromSyncIterator({
 | 
						|
    throw() { return { value: undefined, get done() { throw "BadValue!" } }; }
 | 
						|
  });
 | 
						|
  try {
 | 
						|
    await iter.throw();
 | 
						|
    assertUnreachable('Expected `iter.throw()` to throw, but did not throw');
 | 
						|
  } catch (e) {
 | 
						|
    assertEquals('BadValue!', e);
 | 
						|
  }
 | 
						|
})().catch(function(error) {
 | 
						|
  testFailed = true;
 | 
						|
  testFailure = error;
 | 
						|
});
 | 
						|
 | 
						|
%RunMicrotasks();
 | 
						|
if (testFailed) {
 | 
						|
  throw testFailure;
 | 
						|
}
 | 
						|
 | 
						|
(function ExtractedAsyncFromSyncIteratorMethods() {
 | 
						|
  // TODO(ishell, caitp): Rewrite the test without using function.caller.
 | 
						|
  // According to ES#sec-built-in-function-objects all built-in functions
 | 
						|
  // must be strict. And ES#sec-forbidden-extensions states that the value of
 | 
						|
  // a function.caller must not be a strict function.
 | 
						|
  return;
 | 
						|
  // Async-from-Sync iterator methods can be extracted via function.caller.
 | 
						|
  // TODO(caitp): test extracted `throw` method using yield* in async generator.
 | 
						|
  let extractor = [0, 1, 2, 3, 4,5,6,7,8,9];
 | 
						|
  let extractedNext;
 | 
						|
  let extractedReturn;
 | 
						|
 | 
						|
  extractor[Symbol.iterator] = function() {
 | 
						|
    let it = [][Symbol.iterator].call(extractor);
 | 
						|
    let origNext = it.next, origThrow = it.throw, origReturn = it.return;
 | 
						|
    function extractNext() {
 | 
						|
      extractedNext = extractNext.caller;
 | 
						|
      return origNext;
 | 
						|
    }
 | 
						|
    function extractReturn() {
 | 
						|
      extractedReturn = extractReturn.caller;
 | 
						|
      return origReturn;
 | 
						|
    }
 | 
						|
    Object.defineProperties(it, {
 | 
						|
      "next": { get: extractNext, configurable: true },
 | 
						|
      "return": { get: extractReturn, configurable: true }
 | 
						|
    });
 | 
						|
    return it;
 | 
						|
  };
 | 
						|
 | 
						|
  async function f() {
 | 
						|
    let i;
 | 
						|
    let it = extractor[Symbol.iterator]();
 | 
						|
    for await (let x of it) break;
 | 
						|
    for await (let x of it) return "x";
 | 
						|
  }
 | 
						|
 | 
						|
  // Cycle through `f` to extract iterator methods
 | 
						|
  f().catch(function() { %AbortJS("No error should have occurred"); });
 | 
						|
  %RunMicrotasks();
 | 
						|
 | 
						|
  assertEquals(typeof extractedNext, "function");
 | 
						|
  assertThrowsAsync(() => extractedNext.call(undefined), TypeError);
 | 
						|
  assertThrowsAsync(() => extractedNext.call(1), TypeError);
 | 
						|
 | 
						|
  assertEquals(typeof extractedReturn, "function");
 | 
						|
  assertThrowsAsync(() => extractedReturn.call(undefined), TypeError);
 | 
						|
  assertThrowsAsync(() => extractedReturn.call(1), TypeError);
 | 
						|
})();
 | 
						|
 | 
						|
(function AsyncFromSyncIteratorOrdering() {
 | 
						|
  let i = 0;
 | 
						|
  let log = [];
 | 
						|
  function r(value, done) {
 | 
						|
    let number = (++i);
 | 
						|
    return {
 | 
						|
      get value() {
 | 
						|
        log.push("get iterResult #" + number + ".value");
 | 
						|
        return {
 | 
						|
          get then() {
 | 
						|
            log.push("get nextValue#" + number + ".then");
 | 
						|
            return (r) => {
 | 
						|
              log.push("call nextValue#" + number + ".then");
 | 
						|
              r(value);
 | 
						|
            }
 | 
						|
          }
 | 
						|
        };
 | 
						|
      },
 | 
						|
      get done() {
 | 
						|
        log.push("get iterResult #" + number + ".done");
 | 
						|
        return done;
 | 
						|
      }
 | 
						|
    };
 | 
						|
  }
 | 
						|
  var results = [r("value1", false), r("value2", false), r("value3", true),
 | 
						|
                 r("value4", false)];
 | 
						|
 | 
						|
  var iter = {
 | 
						|
    get [Symbol.asyncIterator]() {
 | 
						|
      log.push("get syncIterable[@@asyncIterator]");
 | 
						|
      return null;
 | 
						|
    },
 | 
						|
 | 
						|
    get [Symbol.iterator]() {
 | 
						|
      log.push("get syncIterable[@@iterator]");
 | 
						|
      return (...args) => {
 | 
						|
        log.push("call syncIterable[@@iterator](" + args.join(", ") + ")");
 | 
						|
        return this;
 | 
						|
      }
 | 
						|
    },
 | 
						|
    next_: 0,
 | 
						|
    get next() {
 | 
						|
      log.push("get syncIterable.next");
 | 
						|
      return (...args) => {
 | 
						|
        let i = this.next_++;
 | 
						|
        log.push("call syncIterable.next(" + args.join(", ") + ")");
 | 
						|
        return results[i];
 | 
						|
      }
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  async function iterate(iterable) {
 | 
						|
    log.push("before");
 | 
						|
    for await (let x of iterable) {
 | 
						|
      log.push("got value " + x);
 | 
						|
    }
 | 
						|
    log.push("after");
 | 
						|
 | 
						|
    return log;
 | 
						|
  }
 | 
						|
 | 
						|
  iterate(iter).then(log => {
 | 
						|
    assertEquals([
 | 
						|
      "before",
 | 
						|
      "get syncIterable[@@asyncIterator]",
 | 
						|
      "get syncIterable[@@iterator]",
 | 
						|
      "call syncIterable[@@iterator]()",
 | 
						|
      "get syncIterable.next",
 | 
						|
      "call syncIterable.next()",
 | 
						|
      "get iterResult #1.done",
 | 
						|
      "get iterResult #1.value",
 | 
						|
      "get nextValue#1.then",
 | 
						|
      "call nextValue#1.then",
 | 
						|
      "got value value1",
 | 
						|
      "call syncIterable.next()",
 | 
						|
      "get iterResult #2.done",
 | 
						|
      "get iterResult #2.value",
 | 
						|
      "get nextValue#2.then",
 | 
						|
      "call nextValue#2.then",
 | 
						|
      "got value value2",
 | 
						|
      "call syncIterable.next()",
 | 
						|
      "get iterResult #3.done",
 | 
						|
      "get iterResult #3.value",
 | 
						|
      "get nextValue#3.then",
 | 
						|
      "call nextValue#3.then",
 | 
						|
      "after"
 | 
						|
    ], log)
 | 
						|
  }).catch(x => %AbortJS(String(x)));
 | 
						|
})();
 |