diff --git a/fetch.bs b/fetch.bs index 4d01e315b..490cfdf3d 100755 --- a/fetch.bs +++ b/fetch.bs @@ -114,6 +114,8 @@ urlPrefix:https://tc39.es/ecma262/#;type:dfn;spec:ecma-262 @@ -8512,7 +8514,24 @@ otherwise false.
 partial interface mixin WindowOrWorkerGlobalScope {
-  [NewObject] Promise<Response> fetch(RequestInfo input, optional RequestInit init = {});
+  [NewObject] Promise<Response> fetch(RequestInfo input, optional FetchInit init = {});
+};
+
+dictionary FetchInit : RequestInit {
+  FetchMonitorCallback monitor;
+};
+
+callback FetchMonitorCallback = undefined (FetchMonitor monitor);
+
+[Exposed=(Window,Worker)]
+interface FetchMonitor : EventTarget {
+  readonly attribute double requestLoaded;
+  readonly attribute double responseLoaded;
+  readonly attribute double requestTotal;
+  readonly attribute double responseTotal;
+
+  attribute EventHandler onrequestprogress;
+  attribute EventHandler onresponseprogress;
 };
 
@@ -8584,10 +8603,55 @@ method steps are: https://github.com/whatwg/dom/issues/1031#issuecomment-1233206400 --> +
  • Let monitor be null. + +

  • +

    If init["{{FetchInit/monitor}}"] exists, then: + +

      +
    1. Let monitorCallback be init["{{FetchInit/monitor}}"]. + +

    2. Set monitor to a {{FetchMonitor}}. + +

    3. Set monitor's requestTotal to request's + body's length, if request's body + is non-null; otherwise 0. + +

    4. Let args be « monitor ». + +

    5. [=invoke|Invoke=] monitorCallback with args + and "rethrow". If this throws an exception, reject p with it + and return p. +

    + +
  • +

    Let processRequestBodyChunkLength, given a bytesLength, be these steps: + +

      +
    1. If monitor is null, then return. + +

    2. Increase monitor's requestLoaded by bytesLength. + +

    3. If not roughly 50ms has passed since these steps were last invoked, then return. + +

    4. Fire a progress event named + requestprogress at monitor with + monitor's requestLoaded and monitor's requestTotal. +

    +
  • -

    Set controller to the result of calling fetch given - request and processResponse given response being - these steps: +

    Let processRequestEndOfBody be these steps: + +

      +
    1. If monitor is null, then return. + +

    2. Fire a progress event named requestprogress at + monitor with monitor's requestLoaded and + monitor's requestTotal. +

    + +
  • +

    Let processResponse given a response be these steps:

    1. If locallyAborted is true, then abort these steps. @@ -8615,10 +8679,17 @@ method steps are:

    2. Resolve p with responseObject.

    +
  • Set controller to the result of calling fetch given + request with processResponse set to processResponse, + processRequestBodyChunkLength set to processRequestBodyChunkLength, + and processRequestEndOfBody set to processRequestEndOfBody. +

  • Return p. +TEMPORARY requestprogress +

    To abort a fetch() call with a promise, request, responseObject, and an error: @@ -9132,6 +9203,125 @@ done only by navigations). The fetch controller is also used to process the next manual redirect for requests with redirect mode set to "manual". +

    Interface {{ProgressEvent}}

    + +
    +[Exposed=(Window,Worker)]
    +interface ProgressEvent : Event {
    +  constructor(DOMString type, optional ProgressEventInit eventInitDict = {});
    +
    +  readonly attribute boolean lengthComputable;
    +  readonly attribute double loaded;
    +  readonly attribute double total;
    +};
    +
    +dictionary ProgressEventInit : EventInit {
    +  boolean lengthComputable = false;
    +  double loaded = 0;
    +  double total = 0;
    +};
    +
    + +

    Events using the {{ProgressEvent}} interface indicate some kind of progression. + +

    The +lengthComputable, +loaded, and +total +getter steps are to return the value they were initialized to. + + +

    Firing events using the {{ProgressEvent}} interface

    + +

    To fire a progress event named e at +target, given transmitted and length, means to fire an event +named e at target, using {{ProgressEvent}}, with the {{ProgressEvent/loaded}} +attribute initialized to transmitted, and if length is not 0, with the +{{ProgressEvent/lengthComputable}} attribute initialized to true and the {{ProgressEvent/total}} +attribute initialized to length. + + +

    Suggested names for events using the {{ProgressEvent}} interface

    + +

    This section is non-normative. + +

    The suggested {{Event/type}} +attribute values for use with +events using the +{{ProgressEvent}} interface are summarized in the table below. +Specification editors are free to tune the details to their specific +scenarios, though are strongly encouraged to discuss their usage with the +WHATWG community to ensure input from people familiar with the subject. + + + + + + + + + + + + +
    {{Event/type}} attribute value + Description + Times + When +
    loadstart + Progress has begun. + Once. + First. +
    progress + In progress. + Once or more. + After loadstart has been + dispatched. +
    requestprogress + In progress request. + Once or more. + After loadstart has been + dispatched. +
    error + Progression failed. + Zero or once (mutually exclusive). + After the last progress has + been + dispatched. +
    abort + Progression is terminated. +
    timeout + Progression is terminated due to preset time expiring. +
    load + Progression is successful. +
    loadend + Progress has stopped. + Once. + After one of error, abort, + timeout or load has been + dispatched. +
    + +

    The error, abort, timeout, and +load event types are mutually exclusive. + +

    Throughout the web platform the error, abort, +timeout and load event types have +their {{Event/bubbles}} and {{Event/cancelable}} +attributes initialized to false, so it is suggested that for consistency all +events using the +{{ProgressEvent}} interface do the same. + + +

    Security considerations

    + +

    For cross-origin requests some kind of opt-in, e.g., the +CORS protocol, has to be used before events using the +{{ProgressEvent}} interface are +dispatched +as information (e.g., size) would be revealed that cannot be obtained +otherwise. +

    Acknowledgments