Skip to content

Commit 4b38437

Browse files
Skip executing fetch handlers if it is no-op. (#1674)
Fixes #1671
1 parent 25f60ac commit 4b38437

File tree

1 file changed

+51
-5
lines changed

1 file changed

+51
-5
lines changed

docs/index.bs

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,11 @@ spec: ecma-262; urlPrefix: http://tc39.github.io/ecma262/
6262
type: abstract-op
6363
text: NormalCompletion; url: sec-normalcompletion
6464
text: ThrowCompletion; url: sec-throwcompletion
65+
text: IsCallable; url: sec-iscallable
66+
text: Get; url: sec-get-o-p
6567
type: dfn
6668
text: Assert; url: sec-algorithm-conventions
67-
text: [[Call]]; url: sec-ecmascript-function-objects-call-thisargument-argumentslist
69+
text: \[[Call]]; url: sec-ecmascript-function-objects-call-thisargument-argumentslist
6870
text: promise; url: sec-promise-objects
6971
text: DetachArrayBuffer; url: sec-detacharraybuffer
7072
url: sec-list-and-record-specification-type
@@ -77,6 +79,10 @@ spec: ecma-262; urlPrefix: http://tc39.github.io/ecma262/
7779
text: Completion; url: sec-completion-record-specification-type
7880
text: Module Record; url: sec-abstract-module-records
7981
text: Cyclic Module Record; url: sec-cyclic-module-records
82+
text: function body; url: prod-FunctionBody
83+
url: sec-ecmascript-language-statements-and-declarations
84+
text: statement
85+
text: declaration
8086

8187
spec: page-visibility; urlPrefix: https://www.w3.org/TR/page-visibility/
8288
type: enum; text: VisibilityState; url: VisibilityState
@@ -199,6 +205,8 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/
199205

200206
A [=/service worker=] has an associated <dfn>start status</dfn> which can be null or a [=Completion=]. It is initially null.
201207

208+
A [=/service worker=] has an associated <dfn>all fetch listeners are empty flag</dfn>. It is initially unset.
209+
202210
A [=/service worker=] is said to be <dfn>running</dfn> if its [=event loop=] is running.
203211

204212
<section>
@@ -2159,15 +2167,15 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/
21592167
1. Return [=a new promise=] |promise| and run the following substeps [=in parallel=]:
21602168
1. [=map/For each=] |cacheName| → |cache| of the [=relevant name to cache map=]:
21612169
1. If |options|["{{MultiCacheQueryOptions/cacheName}}"] matches |cacheName|, then:
2162-
1. Resolve |promise| with the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with |request| and |options| (providing |cache| as thisArgument to the `[[Call]]` internal method of {{Cache/match(request, options)}}.)
2170+
1. Resolve |promise| with the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with |request| and |options| (providing |cache| as thisArgument to the `\[[Call]]` internal method of {{Cache/match(request, options)}}.)
21632171
1. Abort these steps.
21642172
1. Resolve |promise| with undefined.
21652173
1. Else:
21662174
1. Let |promise| be [=a promise resolved with=] undefined.
21672175
1. [=map/For each=] <var ignore>cacheName</var> → |cache| of the [=relevant name to cache map=]:
21682176
1. Set |promise| to the result of [=promise/reacting=] to itself with a fulfillment handler that, when called with argument |response|, performs the following substeps:
21692177
1. If |response| is not undefined, return |response|.
2170-
1. Return the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with |request| and |options| as the arguments (providing |cache| as thisArgument to the `[[Call]]` internal method of {{Cache/match(request, options)}}.)
2178+
1. Return the result of running the algorithm specified in {{Cache/match(request, options)}} method of {{Cache}} interface with |request| and |options| as the arguments (providing |cache| as thisArgument to the `\[[Call]]` internal method of {{Cache/match(request, options)}}.)
21712179
1. Return |promise|.
21722180
</section>
21732181

@@ -2973,16 +2981,48 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/
29732981
1. For each |eventType| of |settingsObject|'s [=environment settings object/global object=]'s associated list of <a>event listeners</a>' event types:
29742982
1. [=set/Append=] |eventType| to |workerGlobalScope|'s associated [=ServiceWorkerGlobalScope/service worker=]'s <a>set of event types to handle</a>.
29752983

2976-
Note: If the global object's associated list of event listeners does not have any event listener added at this moment, the service worker's set of event types to handle remains an empty set. The user agents are encouraged to show a warning that the event listeners must be added on the very first evaluation of the worker script.
2984+
Note: If the global object's associated list of event listeners does not have any event listener added at this moment, the service worker's [=set of event types to handle=] remains an empty set.
29772985

29782986
1. Set |script|'s <a>has ever been evaluated flag</a>.
2987+
1. Unset the |serviceWorker|'s [=all fetch listeners are empty flag=].
2988+
1. The user agent may, if the [=All Fetch Listeners Are Empty=] algorithm with |workerGlobalScope| returns true, set |serviceWorker|'s [=all fetch listeners are empty flag=].
2989+
29792990
1. Run the <a>responsible event loop</a> specified by |settingsObject| until it is destroyed.
29802991
1. [=map/Clear=] |workerGlobalScope|'s [=map of active timers=].
29812992
1. Wait for |serviceWorker| to be [=running=], or for |startFailed| to be true.
29822993
1. If |startFailed| is true, then return *failure*.
29832994
1. Return |serviceWorker|'s [=start status=].
29842995
</section>
29852996

2997+
<section algorithm>
2998+
<h3 id="all-fetch-listeners-are-empty-algorithm"><dfn>All Fetch Listeners Are Empty</dfn></h3>
2999+
3000+
: Input
3001+
:: |workerGlobalScope|, a [=service worker/global object=].
3002+
: Output
3003+
:: a boolean
3004+
3005+
1. If |workerGlobalScope|'s [=set of event types to handle=] does not [=set/contain=] <code>fetch</code>, then return true.
3006+
1. Let |eventHandler| be |workerGlobalScope|'s [=EventTarget/event handler map=]["onfetch"]'s value.
3007+
1. Let |eventListenerCallbacks| be the result of calling [=legacy-obtain service worker fetch event listener callbacks=] given |workerGlobalScope|.
3008+
1. [=list/For each=] |eventListenerCallback| of |eventListenerCallbacks|:
3009+
1. Let |callback| be null.
3010+
1. If |eventHandler| is not null and |eventListenerCallback| equals |eventHandler|'s [=event handler/listener=]'s [=event listener/callback=], then set |callback| to the result of [=convert to an ECMAScript value|converting to an ECMAScript value=] |eventHandler|'s [=event handler/value=].
3011+
1. Otherwise, set |callback| to the result of [=convert to an ECMAScript value|converting to an ECMAScript value=] |eventListenerCallback|.
3012+
1. If [$IsCallable$](|callback|) is false:
3013+
1. Let |getResult| be [=Completion=]([$Get$](|callback|), <code>handleEvent</code>).
3014+
1. If |getResult| is [=abrupt completion=], then return false.
3015+
1. Set |callback| to |getResult|.
3016+
1. If [$IsCallable$](|callback|) is false, or |callback|'s [=function body=] is not empty (i.e. either a [=statement=] or [=declaration=] exist), then return false.
3017+
3018+
Note: This detects "<code>fetch</code>" listeners like `() => {}`. Some sites have a fetch event listener with empty body to make them recognized by Chromium as a progressive web application (PWA).
3019+
3020+
1. Return true.
3021+
3022+
Note: User agents are encouraged to show a warning indicating that empty "<code>fetch</code>" listeners are unnecessary, and may have a negative performance impact.
3023+
3024+
</section>
3025+
29863026
<section algorithm>
29873027
<h3 id="terminate-service-worker-algorithm"><dfn>Terminate Service Worker</dfn></h3>
29883028

@@ -3040,7 +3080,7 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/
30403080
1. Set |registration| to the result of running <a>Match Service Worker Registration</a> given |storage key| and |request|'s [=request/url=].
30413081
1. If |registration| is null or |registration|'s <a>active worker</a> is null, return null.
30423082
1. If |request|'s [=request/destination=] is not {{RequestDestination/"report"}}, set |reservedClient|'s <a>active service worker</a> to |registration|'s <a>active worker</a>.
3043-
1. If |request| is a [=navigation request=], |registration|'s [=navigation preload enabled flag=] is set, |request|'s [=request/method=] is \`<code>GET</code>\`, and |registration|'s [=active worker=]'s <a>set of event types to handle</a> [=set/contains=] <code>fetch</code>, then:
3083+
1. If |request| is a [=navigation request=], |registration|'s [=navigation preload enabled flag=] is set, |request|'s [=request/method=] is \`<code>GET</code>\`, |registration|'s [=active worker=]'s [=set of event types to handle=] [=set/contains=] <code>fetch</code>, and |registration|'s [=active worker=]'s [=all fetch listeners are empty flag=] is not set then:
30443084

30453085
Note: If the above is true except |registration|'s [=active worker=]'s <a>set of event types to handle</a> **does not** contain <code>fetch</code>, then the user agent may wish to show a console warning, as the developer's intent isn't clear.
30463086

@@ -3075,6 +3115,12 @@ spec: storage; urlPrefix: https://storage.spec.whatwg.org/
30753115
1. If the result of running the [=Should Skip Event=] algorithm with "fetch" and |activeWorker| is true, then:
30763116
1. If |shouldSoftUpdate| is true, then [=in parallel=] run the [=Soft Update=] algorithm with |registration|.
30773117
1. Return null.
3118+
1. If |activeWorker|'s [=all fetch listeners are empty flag=] is set:
3119+
1. [=In parallel=]:
3120+
1. If |activeWorker|'s [=service worker/state=] is "activating", then wait for |activeWorker|'s [=service worker/state=] to become "activated".
3121+
1. Run the [=Run Service Worker=] algorithm with |activeWorker|.
3122+
1. If |shouldSoftUpdate| is true, then run the [=Soft Update=] algorithm with |registration|.
3123+
1. Return null.
30783124
1. If |useHighResPerformanceTimers| is true, then set |useHighResPerformanceTimers| to |activeWorker|'s [=service worker/global object=]'s [=WorkerGlobalScope/cross-origin isolated capability=].
30793125
1. Let |timingInfo|'s [=service worker timing info/start time=] be the [=coarsened shared current time=] given |useHighResPerformanceTimers|.
30803126
1. If |activeWorker|'s [=service worker/state=] is "`activating`", wait for |activeWorker|'s [=service worker/state=] to become "`activated`".

0 commit comments

Comments
 (0)