New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 689576 link

Starred by 2 users

Issue metadata

Status: Fixed
Owner:
OoO until Feb 4th
Closed: Apr 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: All
Pri: 3
Type: Bug



Sign in to add a comment

Pair iterators should have %IteratorPrototype% in the prototype chain

Project Member Reported by raphael....@intel.com, Feb 7 2017

Issue description

Pair iterators returned by functions such as keys() or entries(), added to IDL interfaces via an iterable<K, V> declaration, do not have the right prototype chain.

Value iterators are also currently broken, but I'm focusing on pair iterators here because value iterators will be fixed automatically once  issue 632935  is fixed.

The WebIDL spec says in e.g. https://heycam.github.io/webidl/#es-iterable-values that the iterator returned by a function such as values() should be a "default iterator object" (https://heycam.github.io/webidl/#es-default-iterator-object), and its [[Prototype]] must be the "iterator prototype object" (https://heycam.github.io/webidl/#es-iterator-prototype-object). This iterator prototype object's [[Prototype]] should then be ECMAScript's %IteratorPrototype%, which is not the case at the moment.

In other words, this should return true but currently returns false:

    Object.getPrototypeOf(Object.getPrototypeOf(new Headers().entries())) === Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))

Fixing this likely requires new API in V8, as there's currently no way to make the v8::FunctionTemplate wrapping an IDL interface have a PrototypeTemplate that just returns an intrinsic V8 object such as %IteratorPrototype%.
 
Summary: Pair iterators should have %IteratorPrototype% in the prototype chain (was: Pair iterator's should have %IteratorPrototype% in the prototype chain)

Comment 2 by peria@chromium.org, Mar 2 2017

Status: Available (was: Untriaged)
Owner: raphael....@intel.com
Status: Assigned (was: Available)
I guess that rakuco may be interested in this issue, too.  So I assign this to rakuco.
But please feel free to unassign yourself if this is not the case.

I'm definitely interested in this, I'm just not sure yet how to best implement this.

At the moment, we have functions like Header.entries() return an Iterator that's defined in core/Iterator.{h,idl}, which uses the standard IDL machinery to install a "next" method in its prototype and whose prototype inherits from the default Object prototype object. We end up with the following hierarchy:

    %ObjectPrototype%
       ^
       |
       |
    Iterator's prototype (with next(), @@iterator)
    Configured by the IDL machinery
       ^
       |
       |
    Iterator object (empty)
    in core/Iterator.{h,idl}

whereas it should actually look like this:

    %ObjectPrototype%
       ^
       |
       |
    %IteratorPrototype% (has @@iterator)
    comes from V8
       ^
       |
       |
    Iterator's prototype (with next() only)
       ^
       |
       |
    Iterator object (empty)
    in core/Iterator.{h,idl}

exposing %IteratorPrototype% from V8 is not very difficult, but changing Iterator, Iterator's prototype and making the latter inherit from IteratorPrototype is more challenging.
(extra bonus points if this allows us to get rid of the "Iterable" extended IDL attribute)
Status: Started (was: Assigned)
Project Member

Comment 7 by bugdroid1@chromium.org, Apr 7 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/v8/v8.git/+/5ec1cddcdd0c599b00ae8f4fbb54987f92867b12

commit 5ec1cddcdd0c599b00ae8f4fbb54987f92867b12
Author: raphael.kubo.da.costa <raphael.kubo.da.costa@intel.com>
Date: Fri Apr 07 08:33:57 2017

Expose %IteratorPrototype% as an intrinsic in the public API.

The WebIDL spec expects iterator objects from interfaces that declare pair
iterators to ultimately inherit from %IteratorPrototype%. Expose the
intrinsic object in the public API so we can use it in Blink's bindings
code.

BUG= chromium:689576 
R=caitp@igalia.com,jkummerow@chromium.org,jochen@chromium.org

Review-Url: https://codereview.chromium.org/2784543004
Cr-Commit-Position: refs/heads/master@{#44472}

[modify] https://crrev.com/5ec1cddcdd0c599b00ae8f4fbb54987f92867b12/include/v8.h
[modify] https://crrev.com/5ec1cddcdd0c599b00ae8f4fbb54987f92867b12/test/cctest/test-api.cc

Project Member

Comment 8 by bugdroid1@chromium.org, Apr 10 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/6579200aa9189bce1cd61c05fb6eb4493f2302d8

commit 6579200aa9189bce1cd61c05fb6eb4493f2302d8
Author: raphael.kubo.da.costa <raphael.kubo.da.costa@intel.com>
Date: Mon Apr 10 11:54:08 2017

Make pair iterators inherit from %IteratorPrototype%.

Adjust the prototype chain for iterator objects returned by interfaces that
have pair iterators.

The WebIDL spec says when an interface has pair iterators the iterators it
returns must be instances of the "default iterator object" whose
[[Prototype]] points to an "iterator prototype object" whose [[Prototype]],
on its turn, points to %IteratorPrototype%. next() must be implemented in
the "iterator prototype object", while %IteratorPrototype% provides
@@iterator.

In practice, this means the following should return true but was returning
false:

    Object.getPrototypeOf(Object.getPrototypeOf(new Headers().entries())) === Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))

Previously, we just had the Iterator interface with both next() and
@@iterator added to its prototype object, which just inherited from
Object.prototype. We now adhere to the spec by making Iterator's prototype
object inherit by %IteratorPrototype% (which then inherits from
Object.prototype) instead. It also allows us to remove support for the
non-standard "Iterable" extended attribute we had in Blink.

The way we do it is not very pretty though: when the code for the Iterator
interface is generated, we create another function template with no
prototype and set the "prototype" property of its function object. When
|interfaceTemplate| is instantiated, its prototype.__proto__ will point to
the value of the "prototype" property we set, which is exactly what we want.

BUG= 689576 
R=bashi@chromium.org,haraken@chromium.org,yukishiino@chromium.org

Review-Url: https://codereview.chromium.org/2777183004
Cr-Commit-Position: refs/heads/master@{#463224}

[add] https://crrev.com/6579200aa9189bce1cd61c05fb6eb4493f2302d8/third_party/WebKit/LayoutTests/bindings/pair-iterators.html
[modify] https://crrev.com/6579200aa9189bce1cd61c05fb6eb4493f2302d8/third_party/WebKit/LayoutTests/external/wpt/fetch/api/headers/headers-basic-expected.txt
[modify] https://crrev.com/6579200aa9189bce1cd61c05fb6eb4493f2302d8/third_party/WebKit/Source/bindings/IDLExtendedAttributes.md
[modify] https://crrev.com/6579200aa9189bce1cd61c05fb6eb4493f2302d8/third_party/WebKit/Source/bindings/IDLExtendedAttributes.txt
[modify] https://crrev.com/6579200aa9189bce1cd61c05fb6eb4493f2302d8/third_party/WebKit/Source/bindings/scripts/v8_interface.py
[modify] https://crrev.com/6579200aa9189bce1cd61c05fb6eb4493f2302d8/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl
[modify] https://crrev.com/6579200aa9189bce1cd61c05fb6eb4493f2302d8/third_party/WebKit/Source/bindings/tests/idls/core/TestInterface.idl
[modify] https://crrev.com/6579200aa9189bce1cd61c05fb6eb4493f2302d8/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
[modify] https://crrev.com/6579200aa9189bce1cd61c05fb6eb4493f2302d8/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.h
[modify] https://crrev.com/6579200aa9189bce1cd61c05fb6eb4493f2302d8/third_party/WebKit/Source/core/dom/Iterator.idl

Status: Fixed (was: Started)

Sign in to add a comment