@@ -5501,13 +5501,15 @@ dictionary Transformer {
5501
5501
TransformerStartCallback start;
5502
5502
TransformerTransformCallback transform;
5503
5503
TransformerFlushCallback flush;
5504
+ TransformerCancelCallback cancel;
5504
5505
any readableType;
5505
5506
any writableType;
5506
5507
};
5507
5508
5508
5509
callback TransformerStartCallback = any (TransformStreamDefaultController controller);
5509
5510
callback TransformerFlushCallback = Promise<undefined> (TransformStreamDefaultController controller);
5510
5511
callback TransformerTransformCallback = Promise<undefined> (any chunk, TransformStreamDefaultController controller);
5512
+ callback TransformerCancelCallback = Promise<undefined> (any reason);
5511
5513
</xmp>
5512
5514
5513
5515
<dl>
@@ -5570,6 +5572,25 @@ callback TransformerTransformCallback = Promise<undefined> (any chunk, Transform
5570
5572
{{Transformer/flush|flush()}} ; the stream is already in the process of successfully closing down,
5571
5573
and terminating it would be counterproductive.)
5572
5574
5575
+ <dt> <dfn dict-member for="Transformer" lt="cancel">cancel(<var ignore>reason</var>)</dfn> </dt>
5576
+ <dd>
5577
+ <p> A function called when the [=readable side=] is cancelled, or when the [=writable side=] is
5578
+ aborted.
5579
+
5580
+ <p> Typically this is used to clean up underlying transformer resources when the stream is aborted
5581
+ or cancelled.
5582
+
5583
+ <p> If the cancellation process is asynchronous, the function can return a promise to signal
5584
+ success or failure; the result will be communicated to the caller of
5585
+ {{WritableStream/abort()|stream.writable.abort()}} or
5586
+ {{ReadableStream/cancel()|stream.readable.cancel()}} . Throwing an exception is treated the same
5587
+ as returning a rejected promise.
5588
+
5589
+ <p> (Note that there is no need to call
5590
+ {{TransformStreamDefaultController/terminate()|controller.terminate()}} inside
5591
+ {{Transformer/cancel|cancel()}} ; the stream is already in the process of cancelling/aborting, and
5592
+ terminating it would be counterproductive.)
5593
+
5573
5594
<dt> <dfn dict-member for="Transformer">readableType</dfn> </dt>
5574
5595
<dd>
5575
5596
<p> This property is reserved for future use, so any attempts to supply a value will throw an
@@ -5583,8 +5604,8 @@ callback TransformerTransformCallback = Promise<undefined> (any chunk, Transform
5583
5604
5584
5605
The <code> controller</code> object passed to {{Transformer/start|start()}} ,
5585
5606
{{Transformer/transform|transform()}} , and {{Transformer/flush|flush()}} is an instance of
5586
- {{TransformStreamDefaultController}} , and has the ability to enqueue [=chunks=] to the [=readable
5587
- side=] , or to terminate or error the stream.
5607
+ {{TransformStreamDefaultController}} , and has the ability to enqueue [=chunks=] to the
5608
+ [=readable side=] , or to terminate or error the stream.
5588
5609
5589
5610
<h4 id="ts-prototype">Constructor and properties</h4>
5590
5611
@@ -5738,6 +5759,16 @@ the following table:
5738
5759
<th> Internal Slot</th>
5739
5760
<th> Description (<em> non-normative</em> )</th>
5740
5761
<tbody>
5762
+ <tr>
5763
+ <td> <dfn>\[[cancelAlgorithm]]</dfn>
5764
+ <td class="non-normative"> A promise-returning algorithm, taking one argument (the reason for
5765
+ cancellation), which communicates a requested cancellation to the [=transformer=]
5766
+ <tr>
5767
+ <td> <dfn>\[[finishPromise]]</dfn>
5768
+ <td class="non-normative"> A promise which resolves on completion of either the
5769
+ [=TransformStreamDefaultController/[[cancelAlgorithm]]=] or the
5770
+ [=TransformStreamDefaultController/[[flushAlgorithm]]=] . If this field is unpopulated (that is,
5771
+ undefined), then neither of those algorithms have been [=invoked=] yet
5741
5772
<tr>
5742
5773
<td> <dfn>\[[flushAlgorithm]]</dfn>
5743
5774
<td class="non-normative"> A promise-returning algorithm which communicates a requested close to
@@ -5831,8 +5862,7 @@ The following abstract operations operate on {{TransformStream}} instances at a
5831
5862
1. Let |pullAlgorithm| be the following steps:
5832
5863
1. Return ! [$TransformStreamDefaultSourcePullAlgorithm$] (|stream|).
5833
5864
1. Let |cancelAlgorithm| be the following steps, taking a |reason| argument:
5834
- 1. Perform ! [$TransformStreamErrorWritableAndUnblockWrite$] (|stream|, |reason|).
5835
- 1. Return [=a promise resolved with=] undefined.
5865
+ 1. Return ! [$TransformStreamDefaultSourceCancelAlgorithm$] (|stream|, |reason|).
5836
5866
1. Set |stream|.[=TransformStream/[[readable]]=] to ! [$CreateReadableStream$] (|startAlgorithm|,
5837
5867
|pullAlgorithm|, |cancelAlgorithm|, |readableHighWaterMark|, |readableSizeAlgorithm|).
5838
5868
1. Set |stream|.[=TransformStream/[[backpressure]]=] and
@@ -5866,12 +5896,7 @@ The following abstract operations operate on {{TransformStream}} instances at a
5866
5896
1. Perform ! [$TransformStreamDefaultControllerClearAlgorithms$] (|stream|.[=TransformStream/[[controller]]=] ).
5867
5897
1. Perform !
5868
5898
[$WritableStreamDefaultControllerErrorIfNeeded$] (|stream|.[=TransformStream/[[writable]]=] .[=WritableStream/[[controller]]=] , |e|).
5869
- 1. If |stream|.[=TransformStream/[[backpressure]]=] is true, perform ! [$TransformStreamSetBackpressure$] (|stream|,
5870
- false).
5871
-
5872
- <p class="note"> The [$TransformStreamDefaultSinkWriteAlgorithm$] abstract operation could be
5873
- waiting for the promise stored in the [=TransformStream/[[backpressureChangePromise]]=] slot to
5874
- resolve. The call to [$TransformStreamSetBackpressure$] ensures that the promise always resolves.
5899
+ 1. Perform ! [$TransformStreamUnblockWrite$] (|stream|).
5875
5900
</div>
5876
5901
5877
5902
<div algorithm>
@@ -5886,6 +5911,19 @@ The following abstract operations operate on {{TransformStream}} instances at a
5886
5911
1. Set |stream|.[=TransformStream/[[backpressure]]=] to |backpressure|.
5887
5912
</div>
5888
5913
5914
+ <div algorithm>
5915
+ <dfn abstract-op lt="TransformStreamUnblockWrite"
5916
+ id="transform-stream-unblock-write"> TransformStreamUnblockWrite(|stream|)</dfn> performs the
5917
+ following steps:
5918
+
5919
+ 1. If |stream|.[=TransformStream/[[backpressure]]=] is true, perform ! [$TransformStreamSetBackpressure$] (|stream|,
5920
+ false).
5921
+
5922
+ <p class="note"> The [$TransformStreamDefaultSinkWriteAlgorithm$] abstract operation could be
5923
+ waiting for the promise stored in the [=TransformStream/[[backpressureChangePromise]]=] slot to
5924
+ resolve. The call to [$TransformStreamSetBackpressure$] ensures that the promise always resolves.
5925
+ </div>
5926
+
5889
5927
<h4 id="ts-default-controller-abstract-ops">Default controllers</h4>
5890
5928
5891
5929
The following abstract operations support the implementaiton of the
@@ -5894,7 +5932,8 @@ The following abstract operations support the implementaiton of the
5894
5932
<div algorithm>
5895
5933
<dfn abstract-op lt="SetUpTransformStreamDefaultController"
5896
5934
id="set-up-transform-stream-default-controller"> SetUpTransformStreamDefaultController(|stream|,
5897
- |controller|, |transformAlgorithm|, |flushAlgorithm|)</dfn> performs the following steps:
5935
+ |controller|, |transformAlgorithm|, |flushAlgorithm|, |cancelAlgorithm|)</dfn> performs the
5936
+ following steps:
5898
5937
5899
5938
1. Assert: |stream| [=implements=] {{TransformStream}} .
5900
5939
1. Assert: |stream|.[=TransformStream/[[controller]]=] is undefined.
@@ -5903,6 +5942,7 @@ The following abstract operations support the implementaiton of the
5903
5942
1. Set |controller|.[=TransformStreamDefaultController/[[transformAlgorithm]]=] to
5904
5943
|transformAlgorithm|.
5905
5944
1. Set |controller|.[=TransformStreamDefaultController/[[flushAlgorithm]]=] to |flushAlgorithm|.
5945
+ 1. Set |controller|.[=TransformStreamDefaultController/[[cancelAlgorithm]]=] to |cancelAlgorithm|.
5906
5946
</div>
5907
5947
5908
5948
<div algorithm>
@@ -5916,15 +5956,20 @@ The following abstract operations support the implementaiton of the
5916
5956
1. If |result| is an abrupt completion, return [=a promise rejected with=] |result|.\[[Value]] .
5917
5957
1. Otherwise, return [=a promise resolved with=] undefined.
5918
5958
1. Let |flushAlgorithm| be an algorithm which returns [=a promise resolved with=] undefined.
5959
+ 1. Let |cancelAlgorithm| be an algorithm which returns [=a promise resolved with=] undefined.
5919
5960
1. If |transformerDict|["{{Transformer/transform}}"] [=map/exists=] , set |transformAlgorithm| to an
5920
5961
algorithm which takes an argument |chunk| and returns the result of [=invoking=]
5921
5962
|transformerDict|["{{Transformer/transform}}"] with argument list « |chunk|,
5922
5963
|controller| » and [=callback this value=] |transformer|.
5923
5964
1. If |transformerDict|["{{Transformer/flush}}"] [=map/exists=] , set |flushAlgorithm| to an
5924
5965
algorithm which returns the result of [=invoking=] |transformerDict|["{{Transformer/flush}}"]
5925
5966
with argument list « |controller| » and [=callback this value=] |transformer|.
5967
+ 1. If |transformerDict|["{{Transformer/cancel}}"] [=map/exists=] , set |cancelAlgorithm| to an
5968
+ algorithm which takes an argument |reason| and returns the result of [=invoking=]
5969
+ |transformerDict|["{{Transformer/cancel}}"] with argument list « |reason| » and
5970
+ [=callback this value=] |transformer|.
5926
5971
1. Perform ! [$SetUpTransformStreamDefaultController$] (|stream|, |controller|,
5927
- |transformAlgorithm|, |flushAlgorithm|).
5972
+ |transformAlgorithm|, |flushAlgorithm|, |cancelAlgorithm| ).
5928
5973
</div>
5929
5974
5930
5975
<div algorithm>
@@ -5943,6 +5988,7 @@ The following abstract operations support the implementaiton of the
5943
5988
5944
5989
1. Set |controller|.[=TransformStreamDefaultController/[[transformAlgorithm]]=] to undefined.
5945
5990
1. Set |controller|.[=TransformStreamDefaultController/[[flushAlgorithm]]=] to undefined.
5991
+ 1. Set |controller|.[=TransformStreamDefaultController/[[cancelAlgorithm]]=] to undefined.
5946
5992
</div>
5947
5993
5948
5994
<div algorithm>
@@ -6033,36 +6079,89 @@ side=] of [=transform streams=].
6033
6079
id="transform-stream-default-sink-abort-algorithm"> TransformStreamDefaultSinkAbortAlgorithm(|stream|,
6034
6080
|reason|)</dfn> performs the following steps:
6035
6081
6036
- 1. Perform ! [$TransformStreamError$] (|stream|, |reason|).
6037
- 1. Return [=a promise resolved with=] undefined.
6082
+ 1. Let |controller| be |stream|.[=TransformStream/[[controller]]=] .
6083
+ 1. If |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] is not undefined, return
6084
+ |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] .
6085
+ 1. Let |readable| be |stream|.[=TransformStream/[[readable]]=] .
6086
+ 1. Let |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] be a new promise.
6087
+ 1. Let |cancelPromise| be the result of performing
6088
+ |controller|.[=TransformStreamDefaultController/[[cancelAlgorithm]]=] , passing |reason|.
6089
+ 1. Perform ! [$TransformStreamDefaultControllerClearAlgorithms$] (|controller|).
6090
+ 1. [=React=] to |cancelPromise|:
6091
+ 1. If |cancelPromise| was fulfilled, then:
6092
+ 1. If |readable|.[=ReadableStream/[[state]]=] is "`errored`", [=reject=]
6093
+ |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] with
6094
+ |readable|.[=ReadableStream/[[storedError]]=] .
6095
+ 1. Otherwise:
6096
+ 1. Perform ! [$ReadableStreamDefaultControllerError$] (|readable|.[=ReadableStream/[[controller]]=] , |reason|).
6097
+ 1. [=Resolve=] |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] with undefined.
6098
+ 1. If |cancelPromise| was rejected with reason |r|, then:
6099
+ 1. Perform ! [$ReadableStreamDefaultControllerError$] (|readable|.[=ReadableStream/[[controller]]=] , |r|).
6100
+ 1. [=Reject=] |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] with |r|.
6101
+ 1. Return |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] .
6038
6102
</div>
6039
6103
6040
6104
<div algorithm>
6041
6105
<dfn abstract-op lt="TransformStreamDefaultSinkCloseAlgorithm"
6042
6106
id="transform-stream-default-sink-close-algorithm"> TransformStreamDefaultSinkCloseAlgorithm(|stream|)</dfn>
6043
6107
performs the following steps:
6044
6108
6045
- 1. Let |readable| be |stream|.[=TransformStream/[[readable]]=] .
6046
6109
1. Let |controller| be |stream|.[=TransformStream/[[controller]]=] .
6110
+ 1. If |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] is not undefined, return
6111
+ |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] .
6112
+ 1. Let |readable| be |stream|.[=TransformStream/[[readable]]=] .
6113
+ 1. Let |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] be a new promise.
6047
6114
1. Let |flushPromise| be the result of performing
6048
6115
|controller|.[=TransformStreamDefaultController/[[flushAlgorithm]]=] .
6049
6116
1. Perform ! [$TransformStreamDefaultControllerClearAlgorithms$] (|controller|).
6050
- 1. Return the result of [=reacting =] to |flushPromise|:
6117
+ 1. [=React =] to |flushPromise|:
6051
6118
1. If |flushPromise| was fulfilled, then:
6052
- 1. If |readable|.[=ReadableStream/[[state]]=] is "`errored`", throw
6119
+ 1. If |readable|.[=ReadableStream/[[state]]=] is "`errored`", [=reject=]
6120
+ |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] with
6053
6121
|readable|.[=ReadableStream/[[storedError]]=] .
6054
- 1. Perform !
6055
- [$ReadableStreamDefaultControllerClose$] (|readable|.[=ReadableStream/[[controller]]=] ).
6122
+ 1. Otherwise:
6123
+ 1. Perform ! [$ReadableStreamDefaultControllerClose$] (|readable|.[=ReadableStream/[[controller]]=] ).
6124
+ 1. [=Resolve=] |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] with undefined.
6056
6125
1. If |flushPromise| was rejected with reason |r|, then:
6057
- 1. Perform ! [$TransformStreamError$] (|stream|, |r|).
6058
- 1. Throw |readable|.[=ReadableStream/[[storedError]]=] .
6126
+ 1. Perform ! [$ReadableStreamDefaultControllerError$] (|readable|.[=ReadableStream/[[controller]]=] , |r|).
6127
+ 1. [=Reject=] |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] with |r|.
6128
+ 1. Return |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] .
6059
6129
</div>
6060
6130
6061
6131
<h4 id="ts-default-source-abstract-ops">Default sources</h4>
6062
6132
6063
6133
The following abstract operation is used to implement the [=underlying source=] for the [=readable
6064
6134
side=] of [=transform streams=] .
6065
6135
6136
+ <div algorithm>
6137
+ <dfn abstract-op lt="TransformStreamDefaultSourceCancelAlgorithm"
6138
+ id="transform-stream-default-source-cancel"> TransformStreamDefaultSourceCancelAlgorithm(|stream|,
6139
+ |reason|)</dfn> performs the following steps:
6140
+
6141
+ 1. Let |controller| be |stream|.[=TransformStream/[[controller]]=] .
6142
+ 1. If |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] is not undefined, return
6143
+ |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] .
6144
+ 1. Let |writable| be |stream|.[=TransformStream/[[writable]]=] .
6145
+ 1. Let |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] be a new promise.
6146
+ 1. Let |cancelPromise| be the result of performing
6147
+ |controller|.[=TransformStreamDefaultController/[[cancelAlgorithm]]=] , passing |reason|.
6148
+ 1. Perform ! [$TransformStreamDefaultControllerClearAlgorithms$] (|controller|).
6149
+ 1. [=React=] to |cancelPromise|:
6150
+ 1. If |cancelPromise| was fulfilled, then:
6151
+ 1. If |writable|.[=WritableStream/[[state]]=] is "`errored`", [=reject=]
6152
+ |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] with
6153
+ |writable|.[=WritableStream/[[storedError]]=] .
6154
+ 1. Otherwise:
6155
+ 1. Perform ! [$WritableStreamDefaultControllerErrorIfNeeded$] (|writable|.[=WritableStream/[[controller]]=] , |reason|).
6156
+ 1. Perform ! [$TransformStreamUnblockWrite$] (|stream|).
6157
+ 1. [=Resolve=] |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] with undefined.
6158
+ 1. If |cancelPromise| was rejected with reason |r|, then:
6159
+ 1. Perform ! [$WritableStreamDefaultControllerErrorIfNeeded$] (|writable|.[=WritableStream/[[controller]]=] , |r|).
6160
+ 1. Perform ! [$TransformStreamUnblockWrite$] (|stream|).
6161
+ 1. [=Reject=] |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] with |r|.
6162
+ 1. Return |controller|.[=TransformStreamDefaultController/[[finishPromise]]=] .
6163
+ </div>
6164
+
6066
6165
<div algorithm>
6067
6166
<dfn abstract-op lt="TransformStreamDefaultSourcePullAlgorithm"
6068
6167
id="transform-stream-default-source-pull"> TransformStreamDefaultSourcePullAlgorithm(|stream|)</dfn>
@@ -7118,9 +7217,10 @@ reason.
7118
7217
<div algorithm="create a TransformStream">
7119
7218
To <dfn export for="TransformStream" lt="set up|setting up">set up</dfn> a
7120
7219
newly-[=new|created-via-Web IDL=] {{TransformStream}} |stream| given an algorithm <dfn export
7121
- for="TransformStream/set up"><var> transformAlgorithm</var></dfn> and an optional algorithm <dfn
7122
- export for="TransformStream/set up"><var> flushAlgorithm</var></dfn> , perform the following steps.
7123
- |transformAlgorithm| and, if given, |flushAlgorithm|, may return a promise.
7220
+ for="TransformStream/set up"><var> transformAlgorithm</var></dfn> , an optional algorithm <dfn
7221
+ export for="TransformStream/set up"><var> flushAlgorithm</var></dfn> , and an optional algorithm <dfn
7222
+ export for="TransformStream/set up"><var> cancelAlgorithm</var></dfn> , perform the following steps.
7223
+ |transformAlgorithm| and, if given, |flushAlgorithm| and |cancelAlgorithm|, may return a promise.
7124
7224
7125
7225
1. Let |writableHighWaterMark| be 1.
7126
7226
1. Let |writableSizeAlgorithm| be an algorithm that returns 1.
@@ -7136,12 +7236,18 @@ reason.
7136
7236
null otherwise. If this throws an exception |e|, return [=a promise rejected with=] |e|.
7137
7237
1. If |result| is a {{Promise}} , then return |result|.
7138
7238
1. Return [=a promise resolved with=] undefined.
7239
+ 1. Let |cancelAlgorithmWrapper| be an algorithm that runs these steps given a value |reason|:
7240
+ 1. Let |result| be the result of running |cancelAlgorithm| given |reason|, if |cancelAlgorithm|
7241
+ was given, or null otherwise. If this throws an exception |e|, return
7242
+ [=a promise rejected with=] |e|.
7243
+ 1. If |result| is a {{Promise}} , then return |result|.
7244
+ 1. Return [=a promise resolved with=] undefined.
7139
7245
1. Let |startPromise| be [=a promise resolved with=] undefined.
7140
7246
1. Perform ! [$InitializeTransformStream$] (|stream|, |startPromise|, |writableHighWaterMark|,
7141
7247
|writableSizeAlgorithm|, |readableHighWaterMark|, |readableSizeAlgorithm|).
7142
7248
1. Let |controller| be a [=new=] {{TransformStreamDefaultController}} .
7143
7249
1. Perform ! [$SetUpTransformStreamDefaultController$] (|stream|, |controller|,
7144
- |transformAlgorithmWrapper|, |flushAlgorithmWrapper|).
7250
+ |transformAlgorithmWrapper|, |flushAlgorithmWrapper|, |cancelAlgorithmWrapper| ).
7145
7251
7146
7252
Other specifications should be careful when constructing their
7147
7253
<i> [=TransformStream/set up/transformAlgorithm=] </i> to avoid [=in parallel=] reads from the given
0 commit comments