Bug 143608 - [Streams API] Implement ReadableStreamController
Summary: [Streams API] Implement ReadableStreamController
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebCore Misc. (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: youenn fablet
URL:
Keywords:
Depends on:
Blocks: 143752
  Show dependency treegraph
 
Reported: 2015-04-10 09:02 PDT by youenn fablet
Modified: 2015-04-22 08:56 PDT (History)
4 users (show)

See Also:


Attachments
Patch (48.86 KB, patch)
2015-04-12 08:03 PDT, youenn fablet
no flags Details | Formatted Diff | Diff
Trying to fix mac build (48.85 KB, patch)
2015-04-12 09:01 PDT, youenn fablet
no flags Details | Formatted Diff | Diff
Rebased patch (46.26 KB, patch)
2015-04-14 07:27 PDT, youenn fablet
no flags Details | Formatted Diff | Diff
Archive of layout-test-results from ews102 for mac-mavericks (526.02 KB, application/zip)
2015-04-14 07:59 PDT, Build Bot
no flags Details
Archive of layout-test-results from ews105 for mac-mavericks-wk2 (576.03 KB, application/zip)
2015-04-14 08:05 PDT, Build Bot
no flags Details
Rebasing webkit specifc test (49.54 KB, patch)
2015-04-15 03:53 PDT, youenn fablet
no flags Details | Formatted Diff | Diff
Fixing wrapper issue (51.81 KB, patch)
2015-04-16 01:56 PDT, youenn fablet
no flags Details | Formatted Diff | Diff
Patch (51.46 KB, patch)
2015-04-16 13:45 PDT, Xabier Rodríguez Calvar
no flags Details | Formatted Diff | Diff
Patch (51.51 KB, patch)
2015-04-21 08:17 PDT, Xabier Rodríguez Calvar
no flags Details | Formatted Diff | Diff
Patch (51.15 KB, patch)
2015-04-22 07:26 PDT, Xabier Rodríguez Calvar
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description youenn fablet 2015-04-10 09:02:37 PDT
Implement ReadableStreamController as defined in https://streams.spec.whatwg.org/#rs-controller-class
Comment 1 youenn fablet 2015-04-12 08:03:09 PDT
Created attachment 250603 [details]
Patch
Comment 2 youenn fablet 2015-04-12 09:01:16 PDT
Created attachment 250605 [details]
Trying to fix mac build
Comment 3 Xabier Rodríguez Calvar 2015-04-14 03:43:30 PDT
Comment on attachment 250605 [details]
Trying to fix mac build

View in context: https://bugs.webkit.org/attachment.cgi?id=250605&action=review

> Source/WebCore/ChangeLog:1
> +2015-04-12  Youenn Fablet  <youenn.fablet@crf.canon.fr>

Do not forget me ;)

> Source/WebCore/Modules/streams/ReadableStreamController.h:44
> +/* This class is only used for JS source readable streams to allow enqueuing, closing or erroring a readable stream.
> +   Its definition is at https://streams.spec.whatwg.org/#rs-controller-class.
> +   Note that its constructor is taking a ReadableJSStream as it should only be used for JS sources.*/

// Comments

> LayoutTests/ChangeLog:1
> +2015-04-12  Youenn Fablet  <youenn.fablet@crf.canon.fr>

Me.

> LayoutTests/streams/reference-implementation/readable-stream.html:78
> -
> -            assert_array_equals(Object.getOwnPropertyNames(Object.getPrototypeOf(controller)).sort(), [ 'close', 'constructor', 'enqueue', 'error' ]);
> +            // FIXME: decide whether exposing the constructor.
> +            assert_array_equals(Object.getOwnPropertyNames(Object.getPrototypeOf(controller)).sort(), [ 'close', 'enqueue', 'error' ]);

I think we should do what the reference implementation does, which is exposing the constructor. Therefore this wouldn't be needed.

> LayoutTests/streams/reference-implementation/readable-stream.html:94
> -            assert_array_equals(Object.getOwnPropertyNames(enqueue).sort(), [ 'arguments', 'caller', 'length', 'name', 'prototype' ]);
> -            assert_array_equals(Object.getOwnPropertyNames(close).sort(), [ 'arguments', 'caller', 'length', 'name', 'prototype' ]);
> -            assert_array_equals(Object.getOwnPropertyNames(error).sort(), [ 'arguments', 'caller', 'length', 'name', 'prototype' ]);
> +            assert_array_equals(Object.getOwnPropertyNames(enqueue).sort(), [ 'length', 'name' ]);
> +            assert_array_equals(Object.getOwnPropertyNames(close).sort(), [ 'length', 'name' ]);
> +            assert_array_equals(Object.getOwnPropertyNames(error).sort(), [ 'length', 'name' ]);
>  
> -            assert_equals(enqueue.name, '');
> -            assert_equals(close.name, '');
> -            assert_equals(error.name, '');
> +            assert_equals(enqueue.name, 'enqueue');
> +            assert_equals(close.name, 'close');
> +            assert_equals(error.name, 'error');

This test has changed. It needs to be rebased. Also, I don't think we should be removing the things that are part of spec tests, we should comply.

> LayoutTests/streams/reference-implementation/readable-stream.html:115
> -            assert_array_equals(Object.getOwnPropertyNames(Object.getPrototypeOf(controller)).sort(), [ 'close', 'constructor', 'enqueue', 'error' ]);
> +            assert_array_equals(Object.getOwnPropertyNames(Object.getPrototypeOf(controller)).sort(), [ 'close', 'enqueue', 'error' ]);
>              controller.test = "";
> -            assert_array_equals(Object.getOwnPropertyNames(Object.getPrototypeOf(controller)).sort(), [ 'close', 'constructor', 'enqueue', 'error' ]);
> +            assert_array_equals(Object.getOwnPropertyNames(Object.getPrototypeOf(controller)).sort(), [ 'close', 'enqueue', 'error' ]);

Ditto.
Comment 4 youenn fablet 2015-04-14 05:28:24 PDT
(In reply to comment #3)
> Comment on attachment 250605 [details]
> Trying to fix mac build
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=250605&action=review
> 
> > Source/WebCore/ChangeLog:1
> > +2015-04-12  Youenn Fablet  <youenn.fablet@crf.canon.fr>
> 
> Do not forget me ;)
Woups, sure.

> > LayoutTests/streams/reference-implementation/readable-stream.html:78
> > -
> > -            assert_array_equals(Object.getOwnPropertyNames(Object.getPrototypeOf(controller)).sort(), [ 'close', 'constructor', 'enqueue', 'error' ]);
> > +            // FIXME: decide whether exposing the constructor.
> > +            assert_array_equals(Object.getOwnPropertyNames(Object.getPrototypeOf(controller)).sort(), [ 'close', 'enqueue', 'error' ]);
> 
> I think we should do what the reference implementation does, which is
> exposing the constructor. Therefore this wouldn't be needed.

The binding generator is not supporting NoInterfaceObject and CustomConstructor, hence the issue.
The constructor is always throwing an exception, hence not all that useful.
This could be fixed in JSReadablestreamCustom.cpp later on.

> > LayoutTests/streams/reference-implementation/readable-stream.html:94
> > -            assert_array_equals(Object.getOwnPropertyNames(enqueue).sort(), [ 'arguments', 'caller', 'length', 'name', 'prototype' ]);
> > -            assert_array_equals(Object.getOwnPropertyNames(close).sort(), [ 'arguments', 'caller', 'length', 'name', 'prototype' ]);
> > -            assert_array_equals(Object.getOwnPropertyNames(error).sort(), [ 'arguments', 'caller', 'length', 'name', 'prototype' ]);
> > +            assert_array_equals(Object.getOwnPropertyNames(enqueue).sort(), [ 'length', 'name' ]);
> > +            assert_array_equals(Object.getOwnPropertyNames(close).sort(), [ 'length', 'name' ]);
> > +            assert_array_equals(Object.getOwnPropertyNames(error).sort(), [ 'length', 'name' ]);
> >  
> > -            assert_equals(enqueue.name, '');
> > -            assert_equals(close.name, '');
> > -            assert_equals(error.name, '');
> > +            assert_equals(enqueue.name, 'enqueue');
> > +            assert_equals(close.name, 'close');
> > +            assert_equals(error.name, 'error');
> 
> This test has changed. It needs to be rebased. Also, I don't think we should
> be removing the things that are part of spec tests, we should comply.

With testharness tests, the test stops after the first failed assertion.
In that case, we are exiting the test without having tested any API really.
By updating the test, we still test all implemented properties.

I think we can update the tests once implementing the API.
When finalizing, we can resync all tests.
Comment 5 youenn fablet 2015-04-14 07:27:40 PDT
Created attachment 250705 [details]
Rebased patch
Comment 6 Xabier Rodríguez Calvar 2015-04-14 07:29:20 PDT
(In reply to comment #4)
> > > LayoutTests/streams/reference-implementation/readable-stream.html:94
> > > -            assert_array_equals(Object.getOwnPropertyNames(enqueue).sort(), [ 'arguments', 'caller', 'length', 'name', 'prototype' ]);
> > > -            assert_array_equals(Object.getOwnPropertyNames(close).sort(), [ 'arguments', 'caller', 'length', 'name', 'prototype' ]);
> > > -            assert_array_equals(Object.getOwnPropertyNames(error).sort(), [ 'arguments', 'caller', 'length', 'name', 'prototype' ]);
> > > +            assert_array_equals(Object.getOwnPropertyNames(enqueue).sort(), [ 'length', 'name' ]);
> > > +            assert_array_equals(Object.getOwnPropertyNames(close).sort(), [ 'length', 'name' ]);
> > > +            assert_array_equals(Object.getOwnPropertyNames(error).sort(), [ 'length', 'name' ]);
> > >  
> > > -            assert_equals(enqueue.name, '');
> > > -            assert_equals(close.name, '');
> > > -            assert_equals(error.name, '');
> > > +            assert_equals(enqueue.name, 'enqueue');
> > > +            assert_equals(close.name, 'close');
> > > +            assert_equals(error.name, 'error');
> > 
> > This test has changed. It needs to be rebased. Also, I don't think we should
> > be removing the things that are part of spec tests, we should comply.
> 
> With testharness tests, the test stops after the first failed assertion.
> In that case, we are exiting the test without having tested any API really.
> By updating the test, we still test all implemented properties.
> 
> I think we can update the tests once implementing the API.
> When finalizing, we can resync all tests.

Commenting with Youenn on IRC we have two options here in order to not lose track of what we have now and what is the spec goal:

1. We could have in a comment which is the real goal of the test and keep running what we have now.
2. Keep the spec test failing and have a custom test that would be removed once  the everything is implemented and the spec test passes.

I was thinking that 1 would be better but maybe 2 is better if we refer to the goal spec test in the description of the custom one.
Comment 7 Build Bot 2015-04-14 07:59:44 PDT
Comment on attachment 250705 [details]
Rebased patch

Attachment 250705 [details] did not pass mac-ews (mac):
Output: http://webkit-queues.appspot.com/results/4539333881102336

New failing tests:
streams/readable-stream.html
Comment 8 Build Bot 2015-04-14 07:59:47 PDT
Created attachment 250707 [details]
Archive of layout-test-results from ews102 for mac-mavericks

The attached test failures were seen while running run-webkit-tests on the mac-ews.
Bot: ews102  Port: mac-mavericks  Platform: Mac OS X 10.9.5
Comment 9 Build Bot 2015-04-14 08:05:17 PDT
Comment on attachment 250705 [details]
Rebased patch

Attachment 250705 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://webkit-queues.appspot.com/results/5976024936349696

New failing tests:
streams/readable-stream.html
Comment 10 Build Bot 2015-04-14 08:05:20 PDT
Created attachment 250708 [details]
Archive of layout-test-results from ews105 for mac-mavericks-wk2

The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews.
Bot: ews105  Port: mac-mavericks-wk2  Platform: Mac OS X 10.9.5
Comment 11 Xabier Rodríguez Calvar 2015-04-14 08:29:02 PDT
(In reply to comment #7)
> Comment on attachment 250705 [details]
> Rebased patch
> 
> Attachment 250705 [details] did not pass mac-ews (mac):
> Output: http://webkit-queues.appspot.com/results/4539333881102336
> 
> New failing tests:
> streams/readable-stream.html

In this case, as tests are not in the spec yet, so I think we can update our custom test.
Comment 12 Benjamin Poulain 2015-04-14 14:50:36 PDT
Comment on attachment 250705 [details]
Rebased patch

View in context: https://bugs.webkit.org/attachment.cgi?id=250705&action=review

Was this supposed to be for review?

I think this is going in the right direction. I don't think this covers the cases I mentioned in the other bug.

> Source/WebCore/Modules/streams/ReadableStreamController.h:60
> +    ReadableJSStream* m_stream;

Please explain the lifetime of the objects in the Changelog.

> Source/WebCore/bindings/js/JSReadableStreamControllerCustom.cpp:46
> +    if (impl().stream().internalState() != ReadableStream::State::Readable) 

I would store impl().stream() in a temporary variable.

> LayoutTests/streams/reference-implementation/brand-checks-expected.txt:9
> +FAIL ReadableStreamController enforces a brand check on its argument assert_throws: Constructing a ReadableStreamController should throw function "function () { new ReadableStreamController(fakeReadableSt..." did not throw

Looks like we have a regression here.
Comment 13 youenn fablet 2015-04-15 03:41:59 PDT
(In reply to comment #12)
> Comment on attachment 250705 [details]
> Rebased patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=250705&action=review
> 
> Was this supposed to be for review?
> 
> I think this is going in the right direction. I don't think this covers the
> cases I mentioned in the other bug.
> 
> > Source/WebCore/Modules/streams/ReadableStreamController.h:60
> > +    ReadableJSStream* m_stream;
> 
> Please explain the lifetime of the objects in the Changelog.

Sounds good.

> 
> > Source/WebCore/bindings/js/JSReadableStreamControllerCustom.cpp:46
> > +    if (impl().stream().internalState() != ReadableStream::State::Readable) 
> 
> I would store impl().stream() in a temporary variable.

OK

> > LayoutTests/streams/reference-implementation/brand-checks-expected.txt:9
> > +FAIL ReadableStreamController enforces a brand check on its argument assert_throws: Constructing a ReadableStreamController should throw function "function () { new ReadableStreamController(fakeReadableSt..." did not throw
> 
> Looks like we have a regression here.

As long as the controller constructor is not implemented, all corresponding tests are not really relevant.
I will upload a new patch without controller constructor.
I do not really see the point of adding support for it but I will upload another patch dedicated to the constructor so that we can continue discussing that specific point.
Comment 14 youenn fablet 2015-04-15 03:53:27 PDT
Created attachment 250784 [details]
Rebasing webkit specifc test
Comment 15 youenn fablet 2015-04-15 03:54:55 PDT
> I do not really see the point of adding support for it but I will upload
> another patch dedicated to the constructor so that we can continue
> discussing that specific point.

Patch is available at https://bugs.webkit.org/show_bug.cgi?id=143752, on top of this latest patch.
Comment 16 youenn fablet 2015-04-15 05:32:55 PDT
Comment on attachment 250784 [details]
Rebasing webkit specifc test

Patch is rebased according current trunk.
Compared to previous patch, it does not implement close() functionality.
Plan is to add support for it in 143363 after this one is shipped, which is probably more logical that way.
Comment 17 Benjamin Poulain 2015-04-15 22:03:43 PDT
Comment on attachment 250784 [details]
Rebasing webkit specifc test

View in context: https://bugs.webkit.org/attachment.cgi?id=250784&action=review

> Source/WebCore/ChangeLog:12
> +        A controller is created at the time a ReadableJSStream is started and it is owned by it.
> +        The controller will be destroyed when the ReadableJSStream is also destroyed.

Sorry I did not have the time to review any stream patch today. :(

Quick question: The ReadableStreamController has a wrapper that keep a reference to it. Can't the wrapper outlive the ReadableJSStream?
Comment 18 youenn fablet 2015-04-16 01:56:42 PDT
Created attachment 250907 [details]
Fixing wrapper issue
Comment 19 youenn fablet 2015-04-16 02:06:50 PDT
(In reply to comment #17)
> Comment on attachment 250784 [details]
> Rebasing webkit specifc test
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=250784&action=review
> 
> > Source/WebCore/ChangeLog:12
> > +        A controller is created at the time a ReadableJSStream is started and it is owned by it.
> > +        The controller will be destroyed when the ReadableJSStream is also destroyed.
> 
> Sorry I did not have the time to review any stream patch today. :(
> 
> Quick question: The ReadableStreamController has a wrapper that keep a
> reference to it. Can't the wrapper outlive the ReadableJSStream?

Good spot!
Fixed the issue and added a related async test case.
I also filed https://bugs.webkit.org/show_bug.cgi?id=143818 as the implementation of ReadableStreamJSSource::startAsync was defeating garbage collection purpose.
Comment 20 youenn fablet 2015-04-16 11:27:42 PDT
Comment on attachment 250907 [details]
Fixing wrapper issue

View in context: https://bugs.webkit.org/attachment.cgi?id=250907&action=review

> Source/WebCore/bindings/js/JSReadableStreamControllerCustom.cpp:52
> +    notImplemented();

Will be implemented within rebased patch of https://bugs.webkit.org/show_bug.cgi?id=143363

> LayoutTests/streams/reference-implementation/brand-checks-expected.txt:-10
> -PASS ReadableStreamController can't be given a fully-constructed ReadableStream 

These regressions are fixed in https://bugs.webkit.org/show_bug.cgi?id=143752
Comment 21 Xabier Rodríguez Calvar 2015-04-16 11:34:19 PDT
Comment on attachment 250907 [details]
Fixing wrapper issue

View in context: https://bugs.webkit.org/attachment.cgi?id=250907&action=review

> Source/WebCore/bindings/js/JSReadableStreamControllerCustom.cpp:48
> +        return exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Controller has no reaadablestream")));

Typo reaadablestream

> Source/WebCore/bindings/js/JSReadableStreamControllerCustom.cpp:50
> +    if (stream->internalState() != ReadableStream::State::Readable) 

Trailing space at the end of the line

> Source/WebCore/bindings/js/JSReadableStreamControllerCustom.cpp:60
> +        return exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Controller has no reaadablestream")));

Typo

> Source/WebCore/bindings/js/JSReadableStreamControllerCustom.cpp:69
> +        return exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Controller has no reaadablestream")));

Typo
Comment 22 Xabier Rodríguez Calvar 2015-04-16 13:45:29 PDT
Created attachment 250948 [details]
Patch

Fixed typos and trailing spaces.
Comment 23 Xabier Rodríguez Calvar 2015-04-21 08:17:56 PDT
Created attachment 251229 [details]
Patch

Replaced /**/ comments
Comment 24 Benjamin Poulain 2015-04-21 20:30:55 PDT
Comment on attachment 251229 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=251229&action=review

Quick review but nothing looks out of place.

> Source/WebCore/ChangeLog:12
> +        A controller is created at the time a ReadableJSStream is started and it is owned by it.
> +        The controller will be destroyed when the ReadableJSStream is also destroyed.

Am I getting this right?
-ReadableStreamJSSource creates the ReadableStreamController
-It creates a JS wrapper for the controller.
-You keep a strong reference to the wrapper to ensure that ReadableStreamController does not outlive ReadableStreamJSSource.
Comment 25 youenn fablet 2015-04-22 00:56:39 PDT
(In reply to comment #24)
> Comment on attachment 251229 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=251229&action=review
> 
> Quick review but nothing looks out of place.

Thanks.

> > Source/WebCore/ChangeLog:12
> > +        A controller is created at the time a ReadableJSStream is started and it is owned by it.
> > +        The controller will be destroyed when the ReadableJSStream is also destroyed.
> 
> Am I getting this right?
> -ReadableStreamJSSource creates the ReadableStreamController
> -It creates a JS wrapper for the controller.
> -You keep a strong reference to the wrapper to ensure that
> ReadableStreamController does not outlive ReadableStreamJSSource.


That is it, maybe the change log could be further improved when landing.

As you spotted previously, ReadableStreamController may outlive ReadableStreamJSSource if the JS keeps a reference to it.
In that case, as seen in ReadableStreamJSSource destructor, ReadableStreamController stream is set to null, which makes the controller returns exception for any function call.
This could also be added in the change log.
Comment 26 Xabier Rodríguez Calvar 2015-04-22 07:26:35 PDT
Created attachment 251313 [details]
Patch

Fixed changelog according to comments
Comment 27 Xabier Rodríguez Calvar 2015-04-22 08:09:56 PDT
Comment on attachment 251313 [details]
Patch

Landing based on previous r+
Comment 28 WebKit Commit Bot 2015-04-22 08:56:29 PDT
Comment on attachment 251313 [details]
Patch

Clearing flags on attachment: 251313

Committed r183107: <http://trac.webkit.org/changeset/183107>
Comment 29 WebKit Commit Bot 2015-04-22 08:56:34 PDT
All reviewed patches have been landed.  Closing bug.