<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.2">Jekyll</generator><link href="https://blog.wanderview.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://blog.wanderview.com/" rel="alternate" type="text/html" /><updated>2022-12-07T16:06:25+00:00</updated><id>https://blog.wanderview.com/feed.xml</id><title type="html">wanderview</title><subtitle>My name is Ben Kelly.  I'm a software engineer.</subtitle><entry><title type="html">Firefox 52 setTimeout() Changes</title><link href="https://blog.wanderview.com/blog/2017/03/13/firefox-52-settimeout-changes/" rel="alternate" type="text/html" title="Firefox 52 setTimeout() Changes" /><published>2017-03-13T13:30:00+00:00</published><updated>2017-03-13T13:30:00+00:00</updated><id>https://blog.wanderview.com/blog/2017/03/13/firefox-52-settimeout-changes</id><content type="html" xml:base="https://blog.wanderview.com/blog/2017/03/13/firefox-52-settimeout-changes/">&lt;p&gt;Firefox 52 hit the release channel last week and it includes a few &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1300659&quot;&gt;changes to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setTimeout()&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setInterval()&lt;/code&gt;&lt;/a&gt;.  In particular, we have changed how we
schedule and execute timer callbacks in order to reduce the possibility of
jank.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;To start, consider the following simple demo site (you may not want to run
it yourself):&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://people-mozilla.org/~bkelly/timer-flood/index.html&quot;&gt;Demo Site&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you click the “Start” button the site will begin flooding the browser
with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setTimeout()&lt;/code&gt; calls.  Each callback will call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setTimeout()&lt;/code&gt; twice.
This results in an exponential explosion of timers.  Clicking “Stop” will
cause the timers to stop calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setTimeout()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The animated GIF is there so that you can visually see if any jank occurs.
(This is a great technique I am stealing from &lt;a href=&quot;https://twitter.com/nolanlawson&quot;&gt;Nolan Lawson&lt;/a&gt;’s &lt;a href=&quot;https://nolanlawson.com/2015/09/29/indexeddb-websql-localstorage-what-blocks-the-dom/&quot;&gt;IDB
performance post&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Traditionally, browsers will begin dropping frames when this sort of thing
happens and the GIF will stop animating.  For example, this video shows
Firefox 45 ESR running the demo:&lt;/p&gt;

&lt;video src=&quot;/videos/timer-flood-45esr.mp4&quot; controls=&quot;&quot; width=&quot;80%&quot; class=&quot;center-block&quot;&gt;&lt;/video&gt;

&lt;p&gt;In Firefox 52, however, we have made changes which allows the browser to
mostly survive this use case.  This video shows that, while there is a
brief pause, the animated GIF continues to play fairly smoothly in spite
of the timer flood.&lt;/p&gt;

&lt;video src=&quot;/videos/timer-flood-52.mp4&quot; controls=&quot;&quot; width=&quot;80%&quot; class=&quot;center-block&quot;&gt;&lt;/video&gt;

&lt;h2 id=&quot;how-does-it-work&quot;&gt;How Does It Work?&lt;/h2&gt;

&lt;p&gt;Firefox achieves this by implementing &lt;strong&gt;yielding&lt;/strong&gt; between timer callbacks.
After a timer callback is executed we allow any other non-timer event pending
in the queue to complete before running the next timer callback.&lt;/p&gt;

&lt;p&gt;For example, consider the case where we have a number of timer callbacks that
want to run at the same time as a vsync refresh.  Its a bit of a race which
events will get to run first.  The refresh, however, is often considered more
important because if it’s delayed then the site’s frame-per-second will drop.&lt;/p&gt;

&lt;p&gt;With this in mind, consider the “best” case and “worst” case for scheduling
the events:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/event-queue-flood.svg&quot; width=&quot;100%&quot; class=&quot;center-block&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In the best case the refresh runs first and is not delayed.  In the worst
case the refresh is delayed until all the timer callbacks have executed.  In
extreme cases, like the demo above, this delay can be quite long.&lt;/p&gt;

&lt;p&gt;Yielding between timer callbacks changes the situation so that the worst case
looks like this instead:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/event-queue-yielding-effect.svg&quot; width=&quot;100%&quot; class=&quot;center-block&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now, the refresh will be delayed by at most one timer callback.&lt;/p&gt;

&lt;p&gt;In reality we don’t actually re-arrange events in the event queue.  Perhaps
a better way to think of it is that timers are stored in a separate queue.
Only a single timer is allowed to be scheduled on the main event queue at
any time.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/event-queue-yielding-timer-queue.svg&quot; width=&quot;100%&quot; class=&quot;center-block&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So after “callback 1” completes here “callback 2” will be placed on the
main event queue at the end.  This allows the refresh event to execute next.&lt;/p&gt;

&lt;h2 id=&quot;is-this-throttling&quot;&gt;Is This Throttling?&lt;/h2&gt;

&lt;p&gt;No.  Typically “timer throttling” means introducing some amount of delay
into each timer.  For example, if you call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setTimeout(func, 5)&lt;/code&gt; in a
background tab most browsers will delay the timer callback for at least
one second.&lt;/p&gt;

&lt;p&gt;Yielding is different in that it allows timers to run at &lt;strong&gt;full speed&lt;/strong&gt; if
the main thread is idle.  Yielding only causes timers to be delayed if the
main thread is busy.  (Of course, if the main thread is busy then timers
have always run the risk of being delayed.)&lt;/p&gt;

&lt;p&gt;That being said, if we detect that the timer queue is backing up we do
begin throttling timers.  This backpressure helps avoid exhausting memory
when a script is generating more &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setTimeout()&lt;/code&gt; calls than can be executed.
This back pressure is tuned to only trigger in extreme cases and most sites
should not experience it.&lt;/p&gt;

&lt;h2 id=&quot;is-this-prioritization&quot;&gt;Is This Prioritization?&lt;/h2&gt;

&lt;p&gt;Again, no.  Timer yielding is not quite the same as using a priority queue
and marking timer callbacks low priority.  In a strict prioritization scheme
it would be possible for low priority events to never run.  That is not the
case here.&lt;/p&gt;

&lt;p&gt;In our timer yielding approach the next timer callback is run at the same
priority as all other events.  It may execute before other work.  It is
also guaranteed to be executed at some point.&lt;/p&gt;

&lt;h2 id=&quot;whats-the-catch&quot;&gt;What’s The Catch?&lt;/h2&gt;

&lt;p&gt;While our general approach is to yield between timers, our end solution
doesn’t actually do that.  We actually allow a limited number of timer
callbacks to run without yielding.  We do this to mitigate impact to
sites that use timers while saturating the main thread.&lt;/p&gt;

&lt;p&gt;For example, consider a site that is:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Running an animation through a large number of timer callbacks.&lt;/li&gt;
  &lt;li&gt;The animation is saturating the main thread with painting.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this case the timer callbacks will be throttled by the rate at which
the paints can happen.  When the browser cannot execute the paints at
60 FPS, then you will get at most one timer callback between each refresh
driver event.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/event-queue-expensive-paint.svg&quot; width=&quot;100%&quot; class=&quot;center-block&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This is not a problem for “closed loop” animations where you measure how long
things are taking to run and adjust your changes to match.  It can, however,
dramatically increase the overall animation time for “open loop” animations.&lt;/p&gt;

&lt;p&gt;For example, consider this animation demonstration site:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://mozdevs.github.io/servo-experiments/experiments/tiles/&quot;&gt;“Open Loop” Animation Demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here the site pre-computes all the animation steps and schedules a separate
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setTimeout()&lt;/code&gt; for each one.  Each timer callback simply modifies the DOM
for its step without measuring to see if the animation is behind.&lt;/p&gt;

&lt;p&gt;This demo site will cause pretty much every modern browser to drop to zero
frames-per-second.  The total animation, however, will run quite quickly.&lt;/p&gt;

&lt;video src=&quot;/videos/open-loop-animation-45.mp4&quot; controls=&quot;&quot; width=&quot;80%&quot; class=&quot;center-block&quot;&gt;&lt;/video&gt;

&lt;p&gt;In Firefox 52, however, we end up delaying many of the timers due
to our yielding.  This keeps the browser running at 30fps, but the animation
takes much longer to complete:&lt;/p&gt;

&lt;video src=&quot;/videos/open-loop-animation-52.mp4&quot; controls=&quot;&quot; width=&quot;80%&quot; class=&quot;center-block&quot;&gt;&lt;/video&gt;

&lt;p&gt;This is an extreme case that we don’t think reflects the typical behavior on
most sites.  There are many ways to implement this animation without scheduling
hundreds or thousands of simultaneous timers.  Its very likely that sites are
using these alternate methods to avoid triggering the poor FPS performance caused
by this technique.&lt;/p&gt;

&lt;p&gt;That being said, we still want to avoid breaking existing sites if we can.  This
is why we are not enforcing a strict yield after every timer callback.  We hope
that by allowing a few timer callbacks to run without yielding we can mitigate
the impact to these kinds of workloads while still improving performance on
sites in general.&lt;/p&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s Next?&lt;/h2&gt;

&lt;p&gt;These &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setTimeout()&lt;/code&gt; changes have just hit our release channel with Firefox 52.
We will be on the look-out for any compatibility problems in the wild.  So
far we have only had a &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1342854&quot;&gt;single bug report&lt;/a&gt; in the four months since this
landed in nightly.&lt;/p&gt;

&lt;p&gt;If you believe you have a problem on your site in Firefox due to these changes
please &lt;a href=&quot;https://bugzilla.mozilla.org/enter_bug.cgi?format=guided#h=dupes|Core|DOM&quot;&gt;file a bug&lt;/a&gt; and &lt;a href=&quot;https://bugzilla.mozilla.org/user_profile?login=bkelly%40mozilla.com&quot;&gt;add me to the CC list&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Barring large-scale problems we plan to continue refining this approach.  We will
likely change our limit on “timers allowed before yielding” to use a
time budget approach instead of a fixed number.  In addition, the &lt;a href=&quot;https://billmccloskey.wordpress.com/2016/10/27/mozillas-quantum-project/&quot;&gt;Quantum DOM&lt;/a&gt;
project will be experimenting with more changes to event queue scheduling in
general.&lt;/p&gt;

&lt;h2 id=&quot;update-3302018&quot;&gt;Update (3/30/2018)&lt;/h2&gt;

&lt;p&gt;NOTE: We implemented a time budget approach to yielding in &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1343912&quot;&gt;Firefox 55&lt;/a&gt;.  By
default Firefox will now execute consecutive timers for up to 4ms before forcing
a yield.&lt;/p&gt;</content><author><name></name></author><category term="mozilla" /><category term="dom" /><category term="timer" /><summary type="html">Firefox 52 hit the release channel last week and it includes a few changes to setTimeout() and setInterval(). In particular, we have changed how we schedule and execute timer callbacks in order to reduce the possibility of jank.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.wanderview.com/images/event-queue-yielding-timer-queue-twitter.png" /><media:content medium="image" url="https://blog.wanderview.com/images/event-queue-yielding-timer-queue-twitter.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Patching Resources in Service Workers</title><link href="https://blog.wanderview.com/blog/2015/10/13/patching-resources-in-service-workers/" rel="alternate" type="text/html" title="Patching Resources in Service Workers" /><published>2015-10-13T14:30:00+00:00</published><updated>2015-10-13T14:30:00+00:00</updated><id>https://blog.wanderview.com/blog/2015/10/13/patching-resources-in-service-workers</id><content type="html" xml:base="https://blog.wanderview.com/blog/2015/10/13/patching-resources-in-service-workers/">&lt;p&gt;Consider a web site that uses a service worker to provide offline access.  It
consists of numerous resources stored in a versioned Cache.&lt;/p&gt;

&lt;p&gt;What does this site need to do when its code changes?&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;It clearly needs to update its cache.  Thanks to the service worker life cycle,
this is relatively straightforward.  As described in &lt;a href=&quot;https://twitter.com/jaffathecake&quot;&gt;Jake Archibald&lt;/a&gt;’s
&lt;a href=&quot;https://jakearchibald.com/2014/offline-cookbook/#on-install-as-a-dependency&quot;&gt;Offline Cookbook&lt;/a&gt;, the site simply needs to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cache.addAll()&lt;/code&gt; the new resource
in the install event and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caches.delete()&lt;/code&gt; the old Cache in the activate event:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;self.addEventListener('install', function(evt) {
  evt.waitUntil(
    caches.open('v2').then(function(cache) {
      return cache.addAll(resourceList);
    })
  );
});

self.addEventListener('activate', function(evt) {
  evt.waitUntil(caches.delete('v1'));
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is nice and simple, but it does have one downside.  It requests the
entire resource list from the browser’s network stack on each upgrade.&lt;/p&gt;

&lt;p&gt;This can be mitigated pretty easily For unchanged files.  Simply set the correct
cache control headers on the server so you hit the HTTP cache.  Or even copy the
resource directly from the old &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v1&lt;/code&gt; cache to the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v2&lt;/code&gt; cache.&lt;/p&gt;

&lt;p&gt;That being said, we normally only update when things change.  Is there anything
we can do to improve the situation for modified resources?&lt;/p&gt;

&lt;h2 id=&quot;can-we-do-better&quot;&gt;Can we do better?&lt;/h2&gt;

&lt;p&gt;Consider this &lt;a href=&quot;/delta-cache/&quot;&gt;demo site&lt;/a&gt; (&lt;a href=&quot;https://github.com/wanderview/delta-cache&quot;&gt;source code&lt;/a&gt;).  Open it with your devtools network panel visible.
It should work in both Firefox and Chrome release channels.  (There is an &lt;a href=&quot;https://code.google.com/p/chromium/issues/detail?id=542668&quot;&gt;issue&lt;/a&gt;
with Chrome on windows, though.)&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;center-block&quot; src=&quot;/images/upgrades-initial.png&quot; width=&quot;800&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The buttons let you simulate upgrading a cache as the service worker would.  Each
version of the cache stores two resources; JQuery and Bootstrap.  The contents of
each resource is shown in a separate div so you can inspect the final loaded
resource.&lt;/p&gt;

&lt;p&gt;So, to model the typical upgrade process you would click:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Load v1 Resources&lt;/li&gt;
  &lt;li&gt;Clear All Resources&lt;/li&gt;
  &lt;li&gt;Load v2 Resources&lt;/li&gt;
  &lt;li&gt;Clear All REsources&lt;/li&gt;
  &lt;li&gt;Load v3 Resources&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates the following network traffic.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;center-block&quot; src=&quot;/images/upgrades-no-delta.png&quot; width=&quot;800&quot; /&gt;&lt;/p&gt;

&lt;p&gt;However, if you click the load buttons in sequence without clearing, then we
can see an optimization at work.  So:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Load v1 Resources&lt;/li&gt;
  &lt;li&gt;Load v2 Resources&lt;/li&gt;
  &lt;li&gt;Load v3 Resources&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which gives us:&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;center-block&quot; src=&quot;/images/upgrades-with-delta.png&quot; width=&quot;800&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In this case the v2 and v3 network traffic has been reduced by a factor of ten.&lt;/p&gt;

&lt;h2 id=&quot;what-is-going-on-here&quot;&gt;What is going on here?&lt;/h2&gt;

&lt;p&gt;The demo site is using an optimization called &lt;a href=&quot;https://en.wikipedia.org/wiki/Delta_encoding&quot;&gt;delta encoding&lt;/a&gt; to request
only the changes in each resource.  In this (admittedly contrived) case, both
JQuery and Bootstrap are only being updated across minor versions, so the
changes are quite small.&lt;/p&gt;

&lt;p&gt;While the demo is using relatively small updates, delta encoding is still
useful for larger changes.  For example, sending the gzip’ed differences between
JQuery 1.11.3 and 2.1.4 still only requires 8.6KB.&lt;/p&gt;

&lt;p&gt;Of course, delta encoding is not a new concept.  We use it every day with
git and other tools.  It was even proposed as an HTTP standard in 2002 in
&lt;a href=&quot;https://tools.ietf.org/html/rfc3229&quot;&gt;RFC 3229&lt;/a&gt;.  It never caught on, however, because it requires extensive
server resources to implement in a general way.  For example, see this
article on the &lt;a href=&quot;https://blog.cloudflare.com/efficiently-compressing-dynamically-generated-53805/&quot;&gt;CloudFlare blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The nice thing about service workers is they let us implement this algorithm
in a site-specific way that is tailored to our use case.  We determine where
it makes sense to use delta encoding and skip it for resources where its
not feasible.  This lets us use the optimization without dealing with the
complications of making it general purpose across all web sites.&lt;/p&gt;

&lt;h2 id=&quot;diffing-and-patching&quot;&gt;Diff’ing and Patching&lt;/h2&gt;

&lt;p&gt;When I first considered delta encoding, I searched for a good diff/patch
algorithm implemented in javascript.  At the time I didn’t find much that
was suitable.  It seemed most libraries were either focused on creating
traditional UNIX diff output or wrappers around native code.  I needed
a patching algorithm solely implemented in javascript, however.&lt;/p&gt;

&lt;p&gt;In order for delta encoding to be useful the patching algorithm in the
browser must be small.  We can’t just use emscripten to compile a C
patch program, because the size of the resulting library would dwarf any
advantage gained from the delta encoding.&lt;/p&gt;

&lt;p&gt;(It occurrs to me now that the projects like &lt;a href=&quot;https://github.com/creationix/js-git&quot;&gt;js-git&lt;/a&gt; might have patching
code I could have borrowed, but I didn’t think of it at the time.)&lt;/p&gt;

&lt;p&gt;In the end I adapted &lt;a href=&quot;https://twitter.com/cperciva&quot;&gt;Colin Percival&lt;/a&gt;’s excellent set of &lt;a href=&quot;http://www.daemonology.net/bsdiff/&quot;&gt;bsdiff&lt;/a&gt; tools.&lt;/p&gt;

&lt;p&gt;At first glance, bsdiff seemed like a good fit.  Its an extremely effective
diffing tool that works well on both text and binary resources.  Whats more,
bspatch is a single small C file that I could transcribe to javascript.&lt;/p&gt;

&lt;p&gt;Then I ran into bzip.  It turns out bsdiff works by creating file segments
slightly larger than the original file, but with a large number of zeros
for unchanged content.  It then internally uses bzip to compress these
segments.  The result is a compact difference file.&lt;/p&gt;

&lt;p&gt;Porting bzip seemed like a daunting task and likely to require a large
library.&lt;/p&gt;

&lt;p&gt;It occurred to me, however, the browser already knows how to decompress gzip
natively.  Could we instead strip the internal bzip compression out and
just serve the resulting files with gzip encoding?&lt;/p&gt;

&lt;p&gt;The answer is yes.  The demo site uses exactly this technique.&lt;/p&gt;

&lt;p&gt;In fact, if you look closely at the delta encoding network traffic, you will
see devtools reports the resulting uncompressed file as being slightly
larger than the original resource.  This is bsdiff’s internal segment
algorithm at work.&lt;/p&gt;

&lt;p&gt;The u(ncompressed) bsdiff code is on github as &lt;a href=&quot;https://github.com/wanderview/ubsdiff&quot;&gt;ubsdiff&lt;/a&gt;.  In addition, I’ve
published &lt;a href=&quot;https://www.npmjs.com/package/ubspatch&quot;&gt;ubspatch&lt;/a&gt; as a separate npm module.  Currently the ubsdiff
code is only available in C, but it could also be ported to javascript.&lt;/p&gt;

&lt;h2 id=&quot;should-i-use-this-in-production&quot;&gt;Should I Use This in Production&lt;/h2&gt;

&lt;p&gt;Probably not with this specific code.  I wrote a lot of it while my kids were
throwing legos at my head.&lt;/p&gt;

&lt;p&gt;The technique, however, seems suitable for service worker updates using
the install event.  The install event runs in parallel with any currently
active service worker, so you will not create problems for the current page.&lt;/p&gt;

&lt;p&gt;For read-through-caching, though, its less clear.  In these cases you
will often need to patch the resource on-demand in a fetch event handler.
This is problematic because the patching can take a non-trivial amount of time.
Since its not streaming yet, it will just block the worker event loop while it
runs.  If there are additional fetch events waiting to be serviced, this will
cause network jank.&lt;/p&gt;

&lt;p&gt;Ideally, service workers would allow heavy workloads like patching to be
offloaded via a worker.  The spec really needs to be extended to allow workers
to be accessed within the service worker.&lt;/p&gt;

&lt;p&gt;(You could bounce a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;postMessage()&lt;/code&gt; through the fetch event source document to
a worker that does the patching and then back, but that seems a bit convoluted
to really recommend.)&lt;/p&gt;

&lt;h2 id=&quot;frameworks-and-tools&quot;&gt;Frameworks and Tools&lt;/h2&gt;

&lt;p&gt;Ultimately I think this technique probably needs client-side frameworks
and server-side tooling to really shine.&lt;/p&gt;

&lt;p&gt;A framework could transparently handle a number of things:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Automatically include currently cached resource versions in outgoing requests.&lt;/li&gt;
  &lt;li&gt;Dynamically determine if using delta encoding makes sense for any given
resource.&lt;/li&gt;
  &lt;li&gt;Automatically patch differences returned from the server.&lt;/li&gt;
  &lt;li&gt;Provide integrity checks on the final resource after patching.  This is a
crucial step for any production system, but not something I included in the
prototype here.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;service-workers-are-delightful&quot;&gt;Service Workers Are Delightful&lt;/h2&gt;

&lt;p&gt;At the end of the day, though, I find service workers exciting because
they let web developers implement features that had previously been the
sole domain of the browser.  The browsers are old, creaky, and have lots
of constraints.  Web sites can break free of these constraints by using
service workers.&lt;/p&gt;</content><author><name></name></author><category term="mozilla" /><category term="serviceworker" /><category term="dom" /><category term="cache" /><category term="fetch" /><category term="ubsdiff" /><category term="ubspatch" /><summary type="html">Consider a web site that uses a service worker to provide offline access. It consists of numerous resources stored in a versioned Cache. What does this site need to do when its code changes?</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.wanderview.com/images/upgrades-with-delta.png" /><media:content medium="image" url="https://blog.wanderview.com/images/upgrades-with-delta.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Service Worker Meeting Highlights</title><link href="https://blog.wanderview.com/blog/2015/07/28/service-worker-meeting-highlights/" rel="alternate" type="text/html" title="Service Worker Meeting Highlights" /><published>2015-07-28T20:30:00+00:00</published><updated>2015-07-28T20:30:00+00:00</updated><id>https://blog.wanderview.com/blog/2015/07/28/service-worker-meeting-highlights</id><content type="html" xml:base="https://blog.wanderview.com/blog/2015/07/28/service-worker-meeting-highlights/">&lt;p&gt;&lt;img class=&quot;pull-right&quot; src=&quot;/images/highlighter-small.jpg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Last week folks from Apple, Google, Microsoft, Mozilla, and Samsung met in San Francisco
to talk about service workers.  The focus was on addressing problems with the
current spec and to discuss what new features should be added next.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;The &lt;a href=&quot;https://docs.google.com/document/d/1X5KvUxLjXS2kIWheYUzj6GOgwP2eGHj1cAuau-cn8sE/edit?usp=sharing&quot;&gt;minutes&lt;/a&gt; for the meeting are online.  We covered a lot of ground, though,
and these notes are thirty pages long.  It seems many people will simply throw them
in the “tl;dr” bucket and move on.&lt;/p&gt;

&lt;p&gt;The goal of this post is to try to distill the meeting into a few highlights that
are a bit more readable and still reflect what we accomplished.&lt;/p&gt;

&lt;p&gt;The group came to agreement (more or less) on these items:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#other-specs&quot;&gt;Integrating Fetch Event with Other Specs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#foreign-fetch&quot;&gt;Fall-through or Foreign Fetch&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#no-fetch&quot;&gt;No-fetch Optimization&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#updates&quot;&gt;Coordinated Updates&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#max-age&quot;&gt;Service-Worker-Max-Age Header&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#meetings&quot;&gt;Meeting Planning&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This list mainly focuses on the decisions that came out of the top level agenda
items.  There were many other discussions that did not resolve to any immediate
decision.  In addition, a lot of good work was done addressing many of the open
&lt;a href=&quot;https://github.com/slightlyoff/ServiceWorker/issues?q=is%3Aopen+is%3Aissue+milestone%3A%22Version+1%22&quot;&gt;v1 issues&lt;/a&gt;.  Please see the &lt;a href=&quot;https://docs.google.com/document/d/1X5KvUxLjXS2kIWheYUzj6GOgwP2eGHj1cAuau-cn8sE/edit?usp=sharing&quot;&gt;minutes&lt;/a&gt; if you want to delve into these
topics.&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;other-specs&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;integrating-fetch-event-with-other-specs&quot;&gt;Integrating Fetch Event with Other Specs&lt;/h2&gt;

&lt;p&gt;The group decided to investigate and document how the fetch spec should be
integrated into pre-existing specs.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Currently service workers are defined in two specs:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;a href=&quot;https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html&quot;&gt;service worker spec&lt;/a&gt; defines how to register and message the worker
objects.  It also defines the life cycle of service workers.&lt;/li&gt;
  &lt;li&gt;The &lt;a href=&quot;https://fetch.spec.whatwg.org/&quot;&gt;fetch spec&lt;/a&gt; defines how network requests are performed.  At a particular
point in these steps it calls out to the service worker spec to perform
fetch event network interception.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unfortunately, the majority of the other pre-existing specs do not currently use
the fetch spec to perform network requests.  Instead they use their own algorithm
or no specific algorithm at all.&lt;/p&gt;

&lt;p&gt;This is a problem because many of the security checks in the fetch spec require
that attributes are set properly on the request.  Each spec must set the
appropriate Request context and mode.&lt;/p&gt;

&lt;p&gt;In addition, its unclear if certain specs should not intercept at all.  For
example, it seems appcache requests should never produce service worker fetch
events, but what about things like CSP violation reports?&lt;/p&gt;

&lt;p&gt;These questions are not currently answered by the available specs.&lt;/p&gt;

&lt;p&gt;At the meeting last week, however, Google’s &lt;a href=&quot;https://twitter.com/FalkenMatto&quot;&gt;Matt Falkenhagen&lt;/a&gt; offered to help
us at least determine what Chrome currently ships.  We plan to examine each
network request call site to methodically determine the correct behavior and
attributes.  We will then document the result in the fetch spec until it
can be properly moved integrated into the other specs.&lt;/p&gt;

&lt;p&gt;This is great news for Mozilla because the potential security holes here
are the main reason we chose &lt;a href=&quot;/blog/2015/06/18/service-workers-will-not-ship-in-firefox-41/&quot;&gt;not to ship in Firefox 41&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;foreign-fetch&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;fall-through-or-foreign-fetch&quot;&gt;Fall-through or Foreign Fetch&lt;/h2&gt;

&lt;p&gt;The group decided to pursue a fetch oriented design for communicating with
cross-origin service workers.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;For a while now Google has been working on an addition to the spec to allow
service workers for different origins to communicate with one another.  This
would support use cases such as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Offline analytics&lt;/li&gt;
  &lt;li&gt;Cloud storage APIs&lt;/li&gt;
  &lt;li&gt;Efficiently sharing fonts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The solution was originally envisioned as an RPC-like API called
&lt;a href=&quot;https://github.com/mkruisselbrink/navigator-connect&quot;&gt;navigator.connect()&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Over time, however, the effort migrated to a system based on FetchEvent.  The
idea is to permit a service worker to intercept fetch events to its own origin.
So, for example, Google could register a service worker that receives fetch
events for analytics.js and instantly returns the script from the offline Cache.&lt;/p&gt;

&lt;p&gt;In general, we prefer this fetch event based system better for a number of
reasons:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Its more “webby” using HTTP requests instead of RPC-like messags.&lt;/li&gt;
  &lt;li&gt;As a consequence its easy to provide offline support for REST APIs build on
top of HTTP verbs like GET and POST.&lt;/li&gt;
  &lt;li&gt;Its progressive.  If a browser does not support this new system, then the
requests simply go to the server as they used to.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While there is general agreement with the direction, we still need to work out
the details.  Google has proposed &lt;a href=&quot;https://github.com/slightlyoff/ServiceWorker/issues/684&quot;&gt;fall-through fetch&lt;/a&gt;, while Mozilla has
proposed &lt;a href=&quot;https://wiki.whatwg.org/wiki/Foreign_Fetch&quot;&gt;foreign fetch&lt;/a&gt;.  They are very similar, however, and we don’t
currently anticipate any difficult issues.&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;no-fetch&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;no-fetch-optimization&quot;&gt;No-fetch Optimization&lt;/h2&gt;

&lt;p&gt;The group decided to provide an API during the install event to explicitly
&lt;a href=&quot;https://github.com/slightlyoff/ServiceWorker/issues/718#issuecomment-123530545&quot;&gt;opt-out of fetch events&lt;/a&gt; for a particular service worker.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Currently the registration API assumes that a service worker is going to be
handling fetch events.  You must provide a scope to identify the service
worker.  If a network request matches that scope, then you are going to get
a fetch event.  If you don’t actually intend to handle the event, this adds
needless delay to network requests.&lt;/p&gt;

&lt;p&gt;Many options were discussed, but the final solution we settled on is to
provide &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;disableFetch()&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enableFetch()&lt;/code&gt; methods on the install event.&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;updates&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;coordinated-updates&quot;&gt;Coordinated Updates&lt;/h2&gt;

&lt;p&gt;The group decided that we need to support &lt;a href=&quot;https://github.com/slightlyoff/ServiceWorker/issues/727&quot;&gt;coordinated updates&lt;/a&gt; for
sites with multiple service workers.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Currently its difficult to use multiple service workers for the same site.
When you update their code, one will always update before the other one
creating the potential for bugs.&lt;/p&gt;

&lt;p&gt;We need to spec an extension to the API to allow multiple service workers
to update together coherently.&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;max-age&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;service-worker-max-age-header&quot;&gt;Service-Worker-Max-Age Header&lt;/h2&gt;

&lt;p&gt;The group decided to support the &lt;a href=&quot;https://github.com/slightlyoff/ServiceWorker/issues/721&quot;&gt;Service-Worker-Max-Age header&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Currently the update algorithm only examines the top level service worker
script to determine if there is a new version.  Code within imported scripts
is not examined.  This can make it awkward to trigger service worker updates
when one of these dependent scripts has changed.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/slightlyoff/ServiceWorker/issues/721&quot;&gt;Service-Worker-Max-Age header&lt;/a&gt; provides a way to opt-out of this
behavior by setting a maximum time to run any single version of the service
worker.&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;meetings&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;meeting-planning&quot;&gt;Meeting Planning&lt;/h2&gt;

&lt;p&gt;Finally, the group decided to have more frequent face-to-face meetings.  The
next one will be held at &lt;a href=&quot;http://www.w3.org/2015/10/TPAC/&quot;&gt;TPAC&lt;/a&gt; at the end of October.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;small&gt;&lt;a href=&quot;https://www.flickr.com/photos/42931449@N07/5418401602&quot;&gt;Highlighter image&lt;/a&gt; courtesy of &lt;a href=&quot;https://www.flickr.com/photos/42931449@N07/&quot;&gt;photosteve101&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;</content><author><name></name></author><category term="mozilla" /><category term="google" /><category term="apple" /><category term="microsoft" /><category term="samsung" /><category term="serviceworker" /><category term="dom" /><category term="cache" /><category term="fetch" /><summary type="html">Last week folks from Apple, Google, Microsoft, Mozilla, and Samsung met in San Francisco to talk about service workers. The focus was on addressing problems with the current spec and to discuss what new features should be added next.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.wanderview.com/images/highlighter-small.jpg" /><media:content medium="image" url="https://blog.wanderview.com/images/highlighter-small.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Evaluating the Streams API’s Asynchronous Read Function</title><link href="https://blog.wanderview.com/blog/2015/06/19/evaluating-streams-api-async-read/" rel="alternate" type="text/html" title="Evaluating the Streams API’s Asynchronous Read Function" /><published>2015-06-19T18:50:00+00:00</published><updated>2015-06-19T18:50:00+00:00</updated><id>https://blog.wanderview.com/blog/2015/06/19/evaluating-streams-api-async-read</id><content type="html" xml:base="https://blog.wanderview.com/blog/2015/06/19/evaluating-streams-api-async-read/">&lt;p&gt;For a while now Google’s &lt;a href=&quot;https://twitter.com/domenic&quot;&gt;Domenic Denicola&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/ysnysnysn&quot;&gt;Takeshi Yoshino&lt;/a&gt;, and others have been
working on a new specification for streaming data in the browser.  The
&lt;a href=&quot;https://streams.spec.whatwg.org/&quot;&gt;Streams API&lt;/a&gt; is important because it allows large resources to be processed
in a memory efficient way.  Currently, browser APIs like XMLHttpRequest do not
support this kind of processing.&lt;/p&gt;

&lt;p&gt;Mozilla is very interested in implementing some kind of streaming data interface.
To that end we’ve been evaluating the proposed Streams spec to determine if its
the right way forward for Firefox.&lt;/p&gt;

&lt;p&gt;In particular, we had a concern about how the proposed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read()&lt;/code&gt; function was
defined to always be asynchronous and return a promise.  Given how often data
is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read()&lt;/code&gt; from a stream, it seemed like this might introduce excessive overhead
that could not be easily optimized away.  To try to address that concern we wrote
some rough benchmarks to see how the spec might perform.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; The benchmarks suggest that the &lt;a href=&quot;https://streams.spec.whatwg.org/&quot;&gt;Streams API&lt;/a&gt;’s asynchronous
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read()&lt;/code&gt; will not cause performance problems in practice.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;h2 id=&quot;the-concern&quot;&gt;The Concern&lt;/h2&gt;

&lt;p&gt;Before we describe the benchmarks, let’s discuss what our concern was in a
more detail.&lt;/p&gt;

&lt;p&gt;The spec currently defines the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read()&lt;/code&gt; function as returning a promise.  When
data is available in the stream, then the promise resolves with the data.&lt;/p&gt;

&lt;p&gt;So a typical read loop might look like this with the proposed spec:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var reader = stream.getReader();
reader.read().then(function handleChunk(result) {
  if (result.done) {
    return;
  }

  processChunk(result.value);

  return reader.read().then(handleChunk);
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This API was ultimately chosen after &lt;a href=&quot;https://github.com/whatwg/streams/issues/253&quot;&gt;much discussion&lt;/a&gt; in order to support
certain optimizations.&lt;/p&gt;

&lt;p&gt;In contrast, other streaming APIs often provide a synchronous read operation
with some way to determine when data is available.&lt;/p&gt;

&lt;p&gt;Consider what a read loop using node.js streams looks like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;stream.on('readable', function handleReadable() {
  var chunk = stream.read();
  while (chunk) {
    processChunk(chunk);
    chunk = stream.read();
  }

  stream.on('readable', handleReadable);
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;These loops have a lot in common.  They both use an async callback to iteratively
process chunks of data.  The difference, however, is in how much work they can
perform for each async callback.&lt;/p&gt;

&lt;p&gt;The node.js streams can completely drain the stream on each async callback.  In the
Streams API loop, however, there is one async callback per chunk even if there are
many chunks already buffered up in memory.  In addition, it allocates an additional
object each read for the promise.&lt;/p&gt;

&lt;p&gt;We were concerned that these additional async callbacks and promise allocations
would introduce a noticeable performance penalty.&lt;/p&gt;

&lt;p&gt;In order to try to assess if this possibility we wrote a couple benchmarks.  These
benchmarks are not perfect.  The spec is essentially conceptual at this point without
a full concrete implementation.  In addition, we want to compare to possible
implementations.  This is difficult to do without fully implementing the spec.
Therefore, these benchmarks are very much speculative and may not reflect the final
performance.  Currently, however, they are the best that we have available.&lt;/p&gt;

&lt;h2 id=&quot;micro-benchmarking&quot;&gt;Micro-Benchmarking&lt;/h2&gt;

&lt;p&gt;The first benchmark we tried was a micro test.  It essentially executed the loops
above for different numbers of “buffered chunks”.  A version of &lt;a href=&quot;http://benchmarkjs.com/&quot;&gt;benchmark.js&lt;/a&gt; was
then used to repeat the tests and get stable, significant results.&lt;/p&gt;

&lt;p&gt;In addition, the micro benchmark was executed using both native and &lt;a href=&quot;https://github.com/petkaantonov/bluebird&quot;&gt;Bluebird&lt;/a&gt;
promises across a variety platforms and browsers.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/wanderview/streams-promise-read&quot;&gt;code for the micro benchmark&lt;/a&gt; is available on Github.  You can also
&lt;a href=&quot;https://blog.wanderview.com/streams-promise-read/&quot;&gt;run the micro benchmark&lt;/a&gt; yourself.&lt;/p&gt;

&lt;p&gt;So, what kind of results did this benchmark produce?  First, lets compare native
promises to Bluebird promises.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;center-block&quot; src=&quot;/images/streams-micro-promise-type-chart.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Here we can see that Bluebird promises are currently significantly faster than
native promises in this test.  This is not terribly surprising as there are
known areas for improvement in both Firefox’s and Chrome’s promise
implementations.  In the long term, though, we expect both browsers’ native
promises to be competitive with Bluebird performance.&lt;/p&gt;

&lt;p&gt;Based on these results, we’ll just focus on the Bluebird results from now on.&lt;/p&gt;

&lt;p&gt;With that in mind, lets see how things look on a desktop platform.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;center-block&quot; src=&quot;/images/streams-micro-desktop-chart.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This shows that on both Chrome and Firefox the synchronous read loop achieves
greater throughput than the async read loop.  In addition, the sync read loop
has a shallower slope and does not degrade as quickly as we increase the number
of buffered chunks in the pipe.&lt;/p&gt;

&lt;p&gt;Now lets look at performance on a Nexus5.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;center-block&quot; src=&quot;/images/streams-micro-mobile-chart.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This shows a similar story, although the throughput is greatly reduced (as
we would expect for a such a device).  The drop off for the async read is
significant enough that at 128 chunks in the pipe both Chrome and Firefox
require more than 1ms to drain a pipe with the async read.  Given 60fps
time budgets, this is a significant amount of time.&lt;/p&gt;

&lt;p&gt;At this point I’m sure some of you are saying “wait a minute, I thought the
TLDR was that the async read was not a problem!”  These results certainly do
look grim.&lt;/p&gt;

&lt;p&gt;Domenic, however, &lt;a href=&quot;https://github.com/whatwg/streams/issues/320#issuecomment-91424200&quot;&gt;correctly pointed out&lt;/a&gt; that streams performance will
typically be dominated by source or sink I/O.  The micro benchmark does
not capture the overall performance of a system using streams.  What we
really care about is how streams will perform in real systems and not in
artificial benchmarks like this.&lt;/p&gt;

&lt;h2 id=&quot;approximating-a-system&quot;&gt;Approximating a System&lt;/h2&gt;

&lt;p&gt;So next we attempted to write a macro level benchmark that compares the
impact of async read on a system using streams.  This was much more difficult.
We finally settled on a Rube-Goldberg setup like this:&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;center-block&quot; src=&quot;/images/streams-macro-benchmark-diagram.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Here we have a node.js server that responds to an HTTP request by echoing
back time stamps in a stream.  The browser receives these time stamps using
the Fetch Response body stream that has been implemented by Chrome.  The
time stamps are then individually parsed out and sent back to the node.js server
via websocket.  The node.js server then compares the time stamps to determine
round-trip latency.  The total numbers of time stamps are also counted to
measure throughput.&lt;/p&gt;

&lt;p&gt;The key part of this setup is where the Response body stream provides a buffered
chunk of data containing multiple time stamps.  A wrapper stream is used to parse
the chunk into individual time stamps.  Each time stamp is represented as an
object.  This means that a single chunk from the network-oriented Response body
is translated into many smaller chunks.  This is similar to the “buffer chunks in
a pipe scenario” in the micro benchmark.  These smaller chunks are then read
using either a sync or async interface.&lt;/p&gt;

&lt;p&gt;Switching between these read interfaces at this point gives us the difference we
are looking for and lets us compare the impact of sync vs async read on the
system.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/wanderview/streams-time-echo&quot;&gt;code for the macro benchmark&lt;/a&gt; is available on Github.  You can also
run the macro benchmark yourself by checking out the repo and running the
node.js server on your local network.&lt;/p&gt;

&lt;p&gt;It should be noted, however, this benchmark is not particularly stable.  Since
the Chrome Fetch Response body stream does not currently support backpressure, the test
had to manually implement this in the node.js server to avoid simply swamping
the browser.  This manual backpressure mechanism then creates a possibility for
deadlock with the buffering algorithm within the Response body stream.  Its
a bit fragile and I did not take the time to fully fix it.  In the interests of
time I instead restarted the test when this occurred.&lt;/p&gt;

&lt;p&gt;For this test we did not vary any settings.  Instead we simply measured
the throughput across 20 executions and took the mean.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;center-block&quot; src=&quot;/images/streams-macro-throughput-chart.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We can see a few things here.  First, the Nexus5 achieves about 80% of the
throughput of desktop.  The main exception is the async read case using
native promises which runs much slower.  This particular result is not too
surprising, however, given the native-vs-Bluebird results above.&lt;/p&gt;

&lt;p&gt;Again, since we expect native promises to approach Bluebird performance in the
future, we will just ignore the native promise results for now.&lt;/p&gt;

&lt;p&gt;For the Bluebird cases it appears that there is not much difference between
async read and sync read in this test.  Indeed, performing a t-test on the
data shows alpha values ranging from 0.16 to 0.82.  This suggests that there is
not enough statistical evidence to detect a difference between async and
sync read.&lt;/p&gt;

&lt;p&gt;The data for all of these results can be found in this &lt;a href=&quot;https://docs.google.com/spreadsheets/d/1rl6mbD2z1x1bgJLD6y9KJLYWjppB7BujfiWvUMjYTVs/edit?usp=sharing&quot;&gt;spreadsheet&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h2&gt;

&lt;p&gt;The results from the micro benchmark clearly show that in isolation a synchronous
read function is faster than an asynchronous read function for a particular
kind of buffered work load.  The macro benchmark, however, supports Domenic’s
contention that this type of work load does not realistically occur in systems
performing I/O.&lt;/p&gt;

&lt;p&gt;Benchmarking is hard.  It’s especially hard when you’re trying to compare
non-existent, potential implementations of a specification.  The tests we
ran are clearly not perfect here, but they are reasonable approximations of future
behavior and do provide some insight.  In the absence of better data we must
decide how to move forward with the information at hand.&lt;/p&gt;

&lt;p&gt;Given these results, we have concluded that the asynchronous read function in the
Streams API is acceptable and will likely not be a performance problem.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;small&gt;Thank you to Domenic Denicola for reviewing an earlier draft of this
post.&lt;/small&gt;&lt;/p&gt;</content><author><name></name></author><category term="mozilla,streams" /><summary type="html">For a while now Google’s Domenic Denicola, Takeshi Yoshino, and others have been working on a new specification for streaming data in the browser. The Streams API is important because it allows large resources to be processed in a memory efficient way. Currently, browser APIs like XMLHttpRequest do not support this kind of processing. Mozilla is very interested in implementing some kind of streaming data interface. To that end we’ve been evaluating the proposed Streams spec to determine if its the right way forward for Firefox. In particular, we had a concern about how the proposed read() function was defined to always be asynchronous and return a promise. Given how often data is read() from a stream, it seemed like this might introduce excessive overhead that could not be easily optimized away. To try to address that concern we wrote some rough benchmarks to see how the spec might perform. TL;DR: The benchmarks suggest that the Streams API’s asynchronous read() will not cause performance problems in practice.</summary></entry><entry><title type="html">Intent to Implement Streams in Firefox</title><link href="https://blog.wanderview.com/blog/2015/06/19/intent-to-implement-streams-in-firefox/" rel="alternate" type="text/html" title="Intent to Implement Streams in Firefox" /><published>2015-06-19T18:50:00+00:00</published><updated>2015-06-19T18:50:00+00:00</updated><id>https://blog.wanderview.com/blog/2015/06/19/intent-to-implement-streams-in-firefox</id><content type="html" xml:base="https://blog.wanderview.com/blog/2015/06/19/intent-to-implement-streams-in-firefox/">&lt;p&gt;&lt;img class=&quot;pull-right&quot; src=&quot;/images/logo-streams.svg&quot; width=&quot;100&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In the next few months I intend to begin implementing the &lt;a href=&quot;https://streams.spec.whatwg.org/&quot;&gt;Streams API&lt;/a&gt;
in the Gecko codebase.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;Google has been working on this spec for a while and has shipped a small
subset of the API for the &lt;a href=&quot;https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/35_QSL1ABTY&quot;&gt;fetch Response body&lt;/a&gt;.  Over the last few months
I’ve worked with others at Mozilla and Google to try to evaluate if this
spec is suitable for Firefox.&lt;/p&gt;

&lt;p&gt;This evaluation resulted in three main concerns that I believe have been
addressed.&lt;/p&gt;

&lt;h2 id=&quot;async-read&quot;&gt;Async Read&lt;/h2&gt;

&lt;p&gt;The current spec proposes a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read()&lt;/code&gt; function that always returns a promise.
We had concerns about possible performance problems with forcing an asynchronous
callback and creating an additional object on every read.&lt;/p&gt;

&lt;p&gt;To investigate this issue we implemented a couple rough benchmarks to try to
determine what kind of performance could be expected.  The details here are a
bit long, so I wrote a separate post describing the &lt;a href=&quot;/blog/2015/06/19/evaluating-streams-api-async-read/&quot;&gt;async read evaluation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The end conclusion, however, was the the currently proposed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read()&lt;/code&gt; should not
be a problem in practice.&lt;/p&gt;

&lt;h2 id=&quot;algorithms-operating-on-the-public-api&quot;&gt;Algorithms Operating on the Public API&lt;/h2&gt;

&lt;p&gt;As currently proposed, the Streams spec defines certain algorithms in terms of
publicly exposed functions.&lt;/p&gt;

&lt;p&gt;For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pipeTo()&lt;/code&gt; is essentially spec’d as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;function doPipe() {
  lastRead = reader.read();
  Promise.all([lastRead, dest.ready]).then(([{ value, done }]) =&amp;gt; {
    if (Boolean(done) === true) {
      closeDest();
    } else if (dest.state === 'writable') {
      lastWrite = dest.write(value);
      doPipe();
    }
  });
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This calls the public &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.read()&lt;/code&gt; function on the source stream’s reader and the
public &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.write()&lt;/code&gt; function on the sink stream.&lt;/p&gt;

&lt;p&gt;At face value this is a fine thing to do.  It enables creating duck typed streams.
It also allows “JavaScripty” things like monkey patching these functions to observe
the stream.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var origWrite = dest.write;
dest.write = function(value) {
  console.log('Writing: ' + value);
  origWrite(value);
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Unfortunately, providing this kind of feature makes certain kinds of optimizations
in the browser exceptionally hard.&lt;/p&gt;

&lt;p&gt;For example, consider if the source stream and sink stream being piped together are
both C++ implemented streams.  Perhaps the source is a Response.body and the sink
is a file stream (which is not currently spec’d).&lt;/p&gt;

&lt;p&gt;In this case, the browser should be able to perform the data copying on a separate
thread.  There is nothing that requires actually interrupting the JavaScript
event loop with copying operations.&lt;/p&gt;

&lt;p&gt;That is, unless JavaScript monkey patches the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.read()&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.write()&lt;/code&gt; functions.
In that case, the browser must round-trip each value copy through the JavaScript
thread.&lt;/p&gt;

&lt;p&gt;Even if we were to add checking for monkey patching vs unmodified public functions,
the checks add complexity and introduce performance penalties themselves.&lt;/p&gt;

&lt;p&gt;To avoid these kinds of issues, it’s cleanest if algorithms like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pipeTo()&lt;/code&gt; are instead
spec’d to operate on internal data.  Instead of calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.read()&lt;/code&gt; they would “read from
the internal source”.  Instead of calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.write()&lt;/code&gt; they would “write to the
internal sink”.&lt;/p&gt;

&lt;p&gt;While the original design was written in terms of public functions, I believe we have
consensus to move to an &lt;a href=&quot;https://github.com/whatwg/streams/issues/321&quot;&gt;internal object design&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;transferring-streams-between-threads&quot;&gt;Transferring Streams Between Threads&lt;/h2&gt;

&lt;p&gt;Finally, we feel it’s important that the spec supports transferring streams from one
thread to another.  So for example, a fetch Response could be initiated on the main
thread in a window, the body stream passed to a Worker to process the data, and
finally streamed to storage.&lt;/p&gt;

&lt;p&gt;Again, I believe we have an informal agreement on how to move forward.  The
&lt;a href=&quot;https://github.com/whatwg/streams/issues/276&quot;&gt;thread transfer issue&lt;/a&gt; outlines how the stream would be locked on the current
thread and conceptually drained as the new thread reads it.&lt;/p&gt;

&lt;p&gt;For C++ source streams this may not result in any copying, but instead just moving
a handle over behind the scenes.  For JavaScript streams, the data would be read as
normal and copied across to the new thread.&lt;/p&gt;

&lt;p&gt;This generally needs many of the same things required for off-main-thread
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pipeTo()&lt;/code&gt;.  For example, in addition to the internal object design mentioned above,
the spec also uses a locked reader design which further supports these kinds of
optimizations.&lt;/p&gt;

&lt;h2 id=&quot;looking-forward&quot;&gt;Looking Forward&lt;/h2&gt;

&lt;p&gt;With these concerns in mind I intend to begin implementing Streams in Gecko.&lt;/p&gt;

&lt;p&gt;In addition to providing an implementation, I believe this will allow me to be more
active in shaping the spec itself.  Many parts of the spec are stable, but things
are still changing.  Work is proceeding on writable streams, byte streams, and
transforms.  It’s in everyone’s interest to have more browser vendors actively
engaged in working with the spec to find issues early.&lt;/p&gt;

&lt;p&gt;Shipping code will depend on how things finalize in the spec and the code, of
course.  My hope, however, is to have an implementation of the fetch Response
body stream shipping by the end of the year.  This is the same subset of the
spec currently shipped by Chrome.&lt;/p&gt;

&lt;p&gt;Please let me know if you have any questions or concerns.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;small&gt;Thank you to Domenic Denicola and Andrew Overholt for reviewing an earlier draft
of this post.&lt;/small&gt;&lt;/p&gt;</content><author><name></name></author><category term="mozilla,streams" /><summary type="html">In the next few months I intend to begin implementing the Streams API in the Gecko codebase.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.wanderview.com/images/logo-streams.svg" /><media:content medium="image" url="https://blog.wanderview.com/images/logo-streams.svg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Service Workers Will Not Ship in Firefox 41</title><link href="https://blog.wanderview.com/blog/2015/06/18/service-workers-will-not-ship-in-firefox-41/" rel="alternate" type="text/html" title="Service Workers Will Not Ship in Firefox 41" /><published>2015-06-18T15:15:00+00:00</published><updated>2015-06-18T15:15:00+00:00</updated><id>https://blog.wanderview.com/blog/2015/06/18/service-workers-will-not-ship-in-firefox-41</id><content type="html" xml:base="https://blog.wanderview.com/blog/2015/06/18/service-workers-will-not-ship-in-firefox-41/">&lt;p&gt;In &lt;a href=&quot;/blog/2015/03/24/service-workers-in-firefox-nightly&quot;&gt;my last post&lt;/a&gt; I tried to estimate when Service Workers would ship in
Firefox.  I was pretty sure it would not make it in 40, but thought 41 was a
possibility.  It’s a few months later and things are looking clearer.&lt;/p&gt;

&lt;p&gt;Unfortunately, Service Workers will not ship in Firefox 41.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;While Service Workers are largely feature complete, we’ve had issues with the
network interception code.  It’s become clear that implementing this feature
has introduced a number of security risks.  We need to perform a fresh security
audit before the code can ship.&lt;/p&gt;

&lt;p&gt;This was a difficult decision to make, but we feel it was the right one
given the security implications.&lt;/p&gt;

&lt;p&gt;That being said, it’s still possible we will ship parts of the Service Worker
spec in Firefox 41:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Specifically, push notifications are very close and may make it into the
release.  If this occurs we will add a preference to disable fetch event
while exposing the rest of the Service Worker API.  This will allow push-based
Service Workers while the network interception goes through its security audit.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;In addition, it seems likely that the Cache API will ship in Firefox 41.  While
this feature is not as useful without the fetch event, it’s a large piece needed
to support offline web pages.  Getting it released moves us that much closer to
full offline support and will let us focus more people on polishing network
interception.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As always, we appreciate your support and patience.  Please don’t hesitate to
contact us if you encounter any problems.&lt;/p&gt;</content><author><name></name></author><category term="mozilla" /><category term="serviceworker" /><category term="dom" /><category term="push" /><category term="fetch" /><category term="cache" /><summary type="html">In my last post I tried to estimate when Service Workers would ship in Firefox. I was pretty sure it would not make it in 40, but thought 41 was a possibility. It’s a few months later and things are looking clearer. Unfortunately, Service Workers will not ship in Firefox 41.</summary></entry><entry><title type="html">Service Workers in Firefox Nightly</title><link href="https://blog.wanderview.com/blog/2015/03/24/service-workers-in-firefox-nightly/" rel="alternate" type="text/html" title="Service Workers in Firefox Nightly" /><published>2015-03-24T15:15:00+00:00</published><updated>2015-03-24T15:15:00+00:00</updated><id>https://blog.wanderview.com/blog/2015/03/24/service-workers-in-firefox-nightly</id><content type="html" xml:base="https://blog.wanderview.com/blog/2015/03/24/service-workers-in-firefox-nightly/">&lt;p&gt;&lt;img class=&quot;pull-right&quot; src=&quot;/images/nightly-logo-small.png&quot; width=&quot;200&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I’m pleased to announce that we now recommend normal Nightly builds for testing
our implementation of Service Workers.  We will not be posting any more custom
builds here.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;Now that &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1110814&quot;&gt;bug 1110814&lt;/a&gt; has landed in mozilla-central, Nightly has roughly the
same functionality as the last sw-build.  Just enable these preferences in
about:config:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dom.caches.enabled&lt;/code&gt; to true.&lt;/li&gt;
  &lt;li&gt;Set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dom.serviceWorkers.enabled&lt;/code&gt; to true.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please note that on Firefox OS you must enable an additional preference as well.
See &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1125961#c35&quot;&gt;bug 1125961&lt;/a&gt; for details.&lt;/p&gt;

&lt;p&gt;In addition, we’ve decided to move forward with enabling the Service Worker and
Cache API preferences by default in non-releases builds.  We expect the Cache
preference to be enabled in the tree today.  The Service Worker preference should
be enabled within the next week once &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=931249&quot;&gt;bug 931249&lt;/a&gt; is complete.&lt;/p&gt;

&lt;p&gt;When Nightly merges to Aurora (Developer Edition), these preferences will also be
enabled by default there.  They will not, however, ride the trains to Beta or
Release yet.  We feel we need more time stabilizing the implementation before that
can occur.&lt;/p&gt;

&lt;p&gt;So, unfortunately, I cannot tell you exactly which Firefox Release will ship with
Service Workers yet.  It will definitely not be Firefox 39.  Its possible Service
Workers will ship in Firefox 40, but its more likely to finally be enabled in
Firefox 41.&lt;/p&gt;

&lt;p&gt;Developer Edition 39, however, will have Cache enabled and will likely also have
Service Workers enabled.&lt;/p&gt;

&lt;p&gt;Finally, while the code is stabilizing you may see Service Worker registrations
and Cache data be deleted when you update the browser.  If we find that the data
format on disk needs to change we will simply be reseting the relevant storage
area in your profile.  Once the decision to ship is made any future changes will
then properly migrate data without any loss.  Again, this only effects Service
Worker registrations and data stored in Cache.&lt;/p&gt;

&lt;p&gt;As always we appreciate your help testing, reporting bugs, and implementing code.&lt;/p&gt;</content><author><name></name></author><category term="mozilla" /><category term="serviceworker" /><category term="dom" /><category term="cache" /><category term="fetch" /><summary type="html">I’m pleased to announce that we now recommend normal Nightly builds for testing our implementation of Service Workers. We will not be posting any more custom builds here.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.wanderview.com/images/nightly-logo-tiny.png" /><media:content medium="image" url="https://blog.wanderview.com/images/nightly-logo-tiny.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Initial Cache API Lands in Nightly</title><link href="https://blog.wanderview.com/blog/2015/03/09/initial-cache-api-lands-in-nightly/" rel="alternate" type="text/html" title="Initial Cache API Lands in Nightly" /><published>2015-03-09T15:30:00+00:00</published><updated>2015-03-09T15:30:00+00:00</updated><id>https://blog.wanderview.com/blog/2015/03/09/initial-cache-api-lands-in-nightly</id><content type="html" xml:base="https://blog.wanderview.com/blog/2015/03/09/initial-cache-api-lands-in-nightly/">&lt;p&gt;Its been two busy weeks since the last Service Worker build and a lot has
happened.  The first version of the Cache API has landed in Nightly along
with many other improvements and fixes.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;The Cache landing is nice because it was the largest set of patches blocking
users from testing directly in Nightly.  Finally getting it into the tree brings
us much closer to the point where we don’t need these custom builds any more.&lt;/p&gt;

&lt;p&gt;We’re not there yet, though.  The custom builds will still be needed until
the following two issues are fixed:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Cache.put() current does not work.  In order to fix this we must integrate
Cache with the CrossProcessPipe.  These patches have been in the custom builds
from the start, but we must complete the work in order for most Service Worker
sites to be usable on Nightly. | &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1110814&quot;&gt;bug 1110814&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Service Worker scripts and their dependencies are not currently saved for
offline access.  Obviously, we must fix this in order for Service Workers
to provide true offline support.  This feature is in progress, but unfortunately
is not in the custom build yet. | &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=931249&quot;&gt;bug 931249&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once these two bugs are fixed we will begin encouraging the community to test
with Nightly directly.&lt;/p&gt;

&lt;p&gt;This week’s build was updated as of yesterday, March 8:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/sw-builds&quot;&gt;Firefox Service Worker Builds&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This build includes the following feature changes in Nightly:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;Cache API&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=940273&quot;&gt;bug 940273&lt;/a&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;FetchDriver channel stalls when Service Worker returns from fetch event too
early | &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1130803&quot;&gt;bug 1130803&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;remove Service Worker Cache “prefixMatch” option&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1130452&quot;&gt;bug 1130452&lt;/a&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;ServiceWorkerGlobalScope.close() should throw InvalidAccessError |
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1131353&quot;&gt;bug 1131353&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;ServiceWorkerClients API spec changes&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1058311&quot;&gt;bug 1058311&lt;/a&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;Remove ServiceWorkerGlobalScope.scope&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1132673&quot;&gt;bug 1132673&lt;/a&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;ServiceWorker: client.postMessage should be dispatched to
navigator.serviceWorker.onmessage | &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1136467&quot;&gt;bug 1136467&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also includes these bug fixes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;navigator.serviceWorker.controller does not track underlying state |
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1131882&quot;&gt;bug 1131882&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;Fix registration persistence in some activation cases&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1131874&quot;&gt;bug 1131874&lt;/a&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;Don’t persist registrations that fail&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1132141&quot;&gt;bug 1132141&lt;/a&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;FetchDriver should check content load policy before proceeding |
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1139665&quot;&gt;bug 1139665&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Use correct principal for channel which updates ServiceWorker |
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1137419&quot;&gt;bug 1137419&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;Seg Fault when calling cache.matchAll without parameters&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1138916&quot;&gt;bug 1138916&lt;/a&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;Crash in ActorChild::SetFeature&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1140065&quot;&gt;bug 1140065&lt;/a&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;Fix -Winconsistent-missing-override warnings introduced in Cache API |
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1139603&quot;&gt;bug 1139603&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;disallow creating nested workers from ServiceWorker&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1137398&quot;&gt;bug 1137398&lt;/a&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, a number of testing changes were made:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Replace getServiced() with matchAll() in a couple of ServiceWorker tests |
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1137477&quot;&gt;bug 1137477&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;Various ServiceWorker test fixes&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1139561&quot;&gt;bug 1139561&lt;/a&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;Remove activatingWorker warning in ServiceWorkerManager&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1139990&quot;&gt;bug 1139990&lt;/a&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;Remove a couple of unused test functions on ServiceWorkerContainer |
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1140120&quot;&gt;bug 1140120&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;nice to have a test-interfaces.html for ServiceWorkers&lt;/td&gt;
          &lt;td&gt;&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1137816&quot;&gt;bug 1137816&lt;/a&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many thanks to all the contributors:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/baku82845977&quot;&gt;Andrea Marchesini&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://plus.google.com/+CatalinBadea/about&quot;&gt;Catalin Badea&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/CodingExon&quot;&gt;Daniel Holbert&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/ehsanakhgari&quot;&gt;Ehsan Akhgari&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/Gioyik&quot;&gt;Giovanny Gongora&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.janbambas.cz/&quot;&gt;Honza Bambas&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Jason Gersztyn&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/lastontheboat&quot;&gt;Josh Mathews&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/nikhilcutshort&quot;&gt;Nikhil Marathe&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please let us know if you find any new issues.  Thank you!&lt;/p&gt;</content><author><name></name></author><category term="mozilla" /><category term="serviceworker" /><category term="dom" /><category term="cache" /><category term="fetch" /><summary type="html">Its been two busy weeks since the last Service Worker build and a lot has happened. The first version of the Cache API has landed in Nightly along with many other improvements and fixes.</summary></entry><entry><title type="html">That Event Is So Fetch</title><link href="https://blog.wanderview.com/blog/2015/02/23/that-event-is-so-fetch/" rel="alternate" type="text/html" title="That Event Is So Fetch" /><published>2015-02-23T15:00:00+00:00</published><updated>2015-02-23T15:00:00+00:00</updated><id>https://blog.wanderview.com/blog/2015/02/23/that-event-is-so-fetch</id><content type="html" xml:base="https://blog.wanderview.com/blog/2015/02/23/that-event-is-so-fetch/">&lt;p&gt;The Service Workers builds have been updated as of yesterday, February 22:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/sw-builds&quot;&gt;Firefox Service Worker Builds&lt;/a&gt;&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;Notable contributions this week were:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/lastontheboat&quot;&gt;Josh Mathews&lt;/a&gt; landed Fetch Event support in Nightly.  This is important,
of course, because without the Fetch Event you cannot actually intercept
any network requests with your Service Worker. | &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1065216&quot;&gt;bug 1065216&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://plus.google.com/+CatalinBadea/about&quot;&gt;Catalin Badea&lt;/a&gt; landed more of the Service Worker API in Nightly, including
the ability to communicate with the Service Worker using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;postMessage()&lt;/code&gt;. |
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=982726&quot;&gt;bug 982726&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/nikhilcutshort&quot;&gt;Nikhil Marathe&lt;/a&gt; landed some more of his spec implementations to handle
unloading documents correctly and to treat activations atomically. |
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1041340&quot;&gt;bug 1041340&lt;/a&gt; | &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1130065&quot;&gt;bug 1130065&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/baku82845977&quot;&gt;Andrea Marchesini&lt;/a&gt; landed fixes for FirefoxOS discovered by the team in
Paris. | &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1133242&quot;&gt;bug 1133242&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/jaoo&quot;&gt;Jose Antonio Olivera Ortega&lt;/a&gt; contributed a work-in-progress patch to force
Service Worker scripts to update when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dom.serviceWorkers.test.enabled&lt;/code&gt; is
set. | &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1134329&quot;&gt;bug 1134329&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;I landed my implementation of the Fetch Request and Response &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clone()&lt;/code&gt;
methods. | &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1073231&quot;&gt;bug 1073231&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As always, please let us know if you run into any problems.  Thank you for
testing!&lt;/p&gt;</content><author><name></name></author><category term="mozilla" /><category term="serviceworker" /><category term="dom" /><category term="cache" /><category term="fetch" /><summary type="html">The Service Workers builds have been updated as of yesterday, February 22: Firefox Service Worker Builds</summary></entry><entry><title type="html">A Very Special Valentines Day Build</title><link href="https://blog.wanderview.com/blog/2015/02/14/a-very-special-valentines-day-build/" rel="alternate" type="text/html" title="A Very Special Valentines Day Build" /><published>2015-02-14T19:26:52+00:00</published><updated>2015-02-14T19:26:52+00:00</updated><id>https://blog.wanderview.com/blog/2015/02/14/a-very-special-valentines-day-build</id><content type="html" xml:base="https://blog.wanderview.com/blog/2015/02/14/a-very-special-valentines-day-build/">&lt;p&gt;&lt;img class=&quot;pull-right&quot; src=&quot;/images/sw-candy-heart.jpg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Last week we &lt;a href=&quot;/blog/2015/02/10/introducing-firefox-service-worker-builds/&quot;&gt;introduced some custom Firefox builds&lt;/a&gt; that include our
work-in-progress on Service Workers.  The goal of these builds is to enable
wider testing of our implementation as it continues to progress.&lt;/p&gt;

&lt;p&gt;These builds have been updated today, February 14:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/sw-builds&quot;&gt;Firefox Service Worker Builds&lt;/a&gt;&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;This week’s build provides a number of improvements:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/baku82845977&quot;&gt;Andrea Marchesini&lt;/a&gt; landed &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=984050&quot;&gt;bug 984050&lt;/a&gt; in Nightly implementing
peristent Service Worker registrations.  Previously registrations would
be forgotten once the browser was closed.  Obviously, persistent
registrations is a key feature necessary to implement offline web apps
with Service Workers.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://twitter.com/nikhilcutshort&quot;&gt;Nikhil Marathe&lt;/a&gt; has a patch in &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1130065&quot;&gt;bug 1130065&lt;/a&gt; that fixes some of the
trickier aspects of activating a Service Worker for a document.&lt;/li&gt;
  &lt;li&gt;The Paris team has also been investigating using Service Workers on
FirefoxOS.  With Andrea’s help this work is being moved into the tree and
is also included in this build.&lt;/li&gt;
  &lt;li&gt;As a result, this build now includes a FirefoxOS build for the Flame device
based on the v18D firmware.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, some patches that were included in last week’s build have landed in the
tree for Nightly:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;As mentioned above, persistent registrations landed in &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=984050&quot;&gt;bug 984050&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Improvements to gecko’s stream infrastructure to support cloning also landed
in &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1100398&quot;&gt;bug 1100398&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As always, please let us know if you have any questions or run into any
problems.  Thank you for your assistance in testing this new feature!&lt;/p&gt;</content><author><name></name></author><category term="mozilla" /><category term="serviceworker" /><category term="dom" /><category term="cache" /><category term="fetch" /><summary type="html">Last week we introduced some custom Firefox builds that include our work-in-progress on Service Workers. The goal of these builds is to enable wider testing of our implementation as it continues to progress. These builds have been updated today, February 14: Firefox Service Worker Builds</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blog.wanderview.com/images/sw-candy-heart.jpg" /><media:content medium="image" url="https://blog.wanderview.com/images/sw-candy-heart.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>