summaryrefslogtreecommitdiffstats
path: root/js/src/tests/test262/language/statements/for-await-of/ticks-with-async-iter-resolved-promise-and-constructor-lookup-two.js
blob: d584a0b824459e703c61a24a38a379b476ef1951 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// |reftest| async
// Copyright (C) 2019 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-runtime-semantics-forin-div-ofbodyevaluation-lhs-stmt-iterator-lhskind-labelset
description: >
  Ensure the number of ticks and Promise constructor lookups is correct with custom async iterator.
info: |
  13.7.5.13 Runtime Semantics: ForIn/OfBodyEvaluation ( lhs, stmt, iteratorRecord, iterationKind,
                                                        lhsKind, labelSet [ , iteratorKind ] )
  25.6.4.5.1 PromiseResolve
  6.2.3.1 Await

includes: [compareArray.js]
flags: [async]
features: [async-iteration]
---*/

// The expected event log.
var expected = [
  // Before entering loop.
  "pre",

  // Await
  // -> PromiseResolve
  "constructor",

  // Await promise resolved.
  "tick 1",

  // In loop body.
  "loop",

  // Await
  // -> PromiseResolve
  "constructor",

  // Await promise resolved
  "tick 2",

  // After exiting loop.
  "post",
];

// The actual event log.
var actual = [];

// Custom async iterator returning the result of the synchronous iterator wrapped in a Promise.
function toAsyncIterator(iterable) {
  return {
    [Symbol.asyncIterator]() {
      var iter = iterable[Symbol.iterator]();
      return {
        next() {
          return Promise.resolve(iter.next());
        }
      };
    }
  };
}

// Test function using for-await with a single, already resolved Promise.
async function f() {
  var p = Promise.resolve(0);
  actual.push("pre");
  for await (var x of toAsyncIterator([p])) {
    actual.push("loop");
  }
  actual.push("post");
}

// Count the number of ticks needed to complete the loop and compare the actual log.
Promise.resolve(0)
  .then(() => actual.push("tick 1"))
  .then(() => actual.push("tick 2"))
  .then(() => {
    assert.compareArray(actual, expected, "Ticks and constructor lookups");
}).then($DONE, $DONE);

// Redefine `Promise.constructor` in order to intercept "constructor" lookups from PromiseResolve.
// (Perform last so that the lookups from SpeciesConstructor in `then` aren't logged.)
Object.defineProperty(Promise.prototype, "constructor", {
  get() {
    actual.push("constructor");
    return Promise;
  },
  configurable: true,
});

// Start the asynchronous function.
f();