Skip to content

Instantly share code, notes, and snippets.

@jorendorff
Last active October 7, 2023 23:08
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jorendorff/95b670a90a4c7074ce6af4ce8c7bba62 to your computer and use it in GitHub Desktop.
Save jorendorff/95b670a90a4c7074ce6af4ce8c7bba62 to your computer and use it in GitHub Desktop.

details

  • Reflect.getOwnPropertyDescriptor(%Iterator.prototype%, "map")
  • %Iterator.prototype%.map.length === 1
  • %Iterator.prototype%.map.[[Prototype]] is %Generator%
  • %Iterator.prototype%.map.prototype
    • is an extensible object
    • has no properties
    • its typeof is "object"
    • its [[Prototype]] is %GeneratorPrototype%

behavior

  • prelude steps - what does that mean, figure out what the spec says and test it

  • map on an empty iterator

  • output of generator at end is {value: undefined, done: true}

  • %Iterator.prototype%.map.prototype works as expected, [[Prototype]] of iterators is whatever the spec says

  • methods still work if you clobber the global Symbol

  • test that Iterator.prototype.map can't be applied to an array

  • test that Iterator.prototype.map on a proxy doesn't access proxy[Symbol.iterator]

  • test that map passes mapped values back to the .next method

  • test that calling map on a proxy accesses the right properties in the right order

    • in normal execution: gets next exactly once, calls resulting method multiple times, access .value and .done on the result of the next() method.
    • with abrupt completion when calling the function f (.return is called)
    • with abrupt completion when yielding (.return is called)
    • with abrupt completion from IteratorValue (no .return call)
  • same iterator, two map() calls being iterated, interleaved

  • try to re-enter the map() generator by calling its .next method from the mapper

  • applying that .next method on it when the iterator isn't busy works, though, like

    const iter = [1, 2, 3][Symbol.iterator]().map(a => a ** 2);
    for (const item of iter) {
      const obj = it.next();  // should be a {value:, done:} object
      if (item == 1) {
        assertEq(obj.value, 4);
        assertEq(obj.done, false);
      } else {
        ...
      }
    }
  • test that passing values to next() passes them through to the target iterator

    • with a chain of multiple map()s

The following are really testing the consumer of map() iterators, so maybe it would be wasteful to replicate them for every single method:

  • Adding a next method on map.prototype (shadowing the one on %GeneratorPrototype%)
    • does not affect any iterations that have already been started
    • does affect subsequent iterations using the same generator object
    • does affect map generators created later
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment