workbox-window.dev.es5.mjs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  1. try {
  2. self['workbox:window:4.3.1'] && _();
  3. } catch (e) {} // eslint-disable-line
  4. /*
  5. Copyright 2019 Google LLC
  6. Use of this source code is governed by an MIT-style
  7. license that can be found in the LICENSE file or at
  8. https://opensource.org/licenses/MIT.
  9. */
  10. /**
  11. * Sends a data object to a service worker via `postMessage` and resolves with
  12. * a response (if any).
  13. *
  14. * A response can be set in a message handler in the service worker by
  15. * calling `event.ports[0].postMessage(...)`, which will resolve the promise
  16. * returned by `messageSW()`. If no response is set, the promise will not
  17. * resolve.
  18. *
  19. * @param {ServiceWorker} sw The service worker to send the message to.
  20. * @param {Object} data An object to send to the service worker.
  21. * @return {Promise<Object|undefined>}
  22. *
  23. * @memberof module:workbox-window
  24. */
  25. var messageSW = function messageSW(sw, data) {
  26. return new Promise(function (resolve) {
  27. var messageChannel = new MessageChannel();
  28. messageChannel.port1.onmessage = function (evt) {
  29. return resolve(evt.data);
  30. };
  31. sw.postMessage(data, [messageChannel.port2]);
  32. });
  33. };
  34. function _defineProperties(target, props) {
  35. for (var i = 0; i < props.length; i++) {
  36. var descriptor = props[i];
  37. descriptor.enumerable = descriptor.enumerable || false;
  38. descriptor.configurable = true;
  39. if ("value" in descriptor) descriptor.writable = true;
  40. Object.defineProperty(target, descriptor.key, descriptor);
  41. }
  42. }
  43. function _createClass(Constructor, protoProps, staticProps) {
  44. if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  45. if (staticProps) _defineProperties(Constructor, staticProps);
  46. return Constructor;
  47. }
  48. function _inheritsLoose(subClass, superClass) {
  49. subClass.prototype = Object.create(superClass.prototype);
  50. subClass.prototype.constructor = subClass;
  51. subClass.__proto__ = superClass;
  52. }
  53. function _assertThisInitialized(self) {
  54. if (self === void 0) {
  55. throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  56. }
  57. return self;
  58. }
  59. try {
  60. self['workbox:core:4.3.1'] && _();
  61. } catch (e) {} // eslint-disable-line
  62. /*
  63. Copyright 2018 Google LLC
  64. Use of this source code is governed by an MIT-style
  65. license that can be found in the LICENSE file or at
  66. https://opensource.org/licenses/MIT.
  67. */
  68. /**
  69. * The Deferred class composes Promises in a way that allows for them to be
  70. * resolved or rejected from outside the constructor. In most cases promises
  71. * should be used directly, but Deferreds can be necessary when the logic to
  72. * resolve a promise must be separate.
  73. *
  74. * @private
  75. */
  76. var Deferred =
  77. /**
  78. * Creates a promise and exposes its resolve and reject functions as methods.
  79. */
  80. function Deferred() {
  81. var _this = this;
  82. this.promise = new Promise(function (resolve, reject) {
  83. _this.resolve = resolve;
  84. _this.reject = reject;
  85. });
  86. };
  87. /*
  88. Copyright 2019 Google LLC
  89. Use of this source code is governed by an MIT-style
  90. license that can be found in the LICENSE file or at
  91. https://opensource.org/licenses/MIT.
  92. */
  93. var logger = function () {
  94. var inGroup = false;
  95. var methodToColorMap = {
  96. debug: "#7f8c8d",
  97. // Gray
  98. log: "#2ecc71",
  99. // Green
  100. warn: "#f39c12",
  101. // Yellow
  102. error: "#c0392b",
  103. // Red
  104. groupCollapsed: "#3498db",
  105. // Blue
  106. groupEnd: null // No colored prefix on groupEnd
  107. };
  108. var print = function print(method, args) {
  109. var _console2;
  110. if (method === 'groupCollapsed') {
  111. // Safari doesn't print all console.groupCollapsed() arguments:
  112. // https://bugs.webkit.org/show_bug.cgi?id=182754
  113. if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
  114. var _console;
  115. (_console = console)[method].apply(_console, args);
  116. return;
  117. }
  118. }
  119. var styles = ["background: " + methodToColorMap[method], "border-radius: 0.5em", "color: white", "font-weight: bold", "padding: 2px 0.5em"]; // When in a group, the workbox prefix is not displayed.
  120. var logPrefix = inGroup ? [] : ['%cworkbox', styles.join(';')];
  121. (_console2 = console)[method].apply(_console2, logPrefix.concat(args));
  122. if (method === 'groupCollapsed') {
  123. inGroup = true;
  124. }
  125. if (method === 'groupEnd') {
  126. inGroup = false;
  127. }
  128. };
  129. var api = {};
  130. var _arr = Object.keys(methodToColorMap);
  131. var _loop = function _loop() {
  132. var method = _arr[_i];
  133. api[method] = function () {
  134. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  135. args[_key] = arguments[_key];
  136. }
  137. print(method, args);
  138. };
  139. };
  140. for (var _i = 0; _i < _arr.length; _i++) {
  141. _loop();
  142. }
  143. return api;
  144. }();
  145. /*
  146. Copyright 2019 Google LLC
  147. Use of this source code is governed by an MIT-style
  148. license that can be found in the LICENSE file or at
  149. https://opensource.org/licenses/MIT.
  150. */
  151. /**
  152. * A minimal `EventTarget` shim.
  153. * This is necessary because not all browsers support constructable
  154. * `EventTarget`, so using a real `EventTarget` will error.
  155. * @private
  156. */
  157. var EventTargetShim =
  158. /*#__PURE__*/
  159. function () {
  160. /**
  161. * Creates an event listener registry
  162. *
  163. * @private
  164. */
  165. function EventTargetShim() {
  166. // A registry of event types to listeners.
  167. this._eventListenerRegistry = {};
  168. }
  169. /**
  170. * @param {string} type
  171. * @param {Function} listener
  172. * @private
  173. */
  174. var _proto = EventTargetShim.prototype;
  175. _proto.addEventListener = function addEventListener(type, listener) {
  176. this._getEventListenersByType(type).add(listener);
  177. };
  178. /**
  179. * @param {string} type
  180. * @param {Function} listener
  181. * @private
  182. */
  183. _proto.removeEventListener = function removeEventListener(type, listener) {
  184. this._getEventListenersByType(type).delete(listener);
  185. };
  186. /**
  187. * @param {Event} event
  188. * @private
  189. */
  190. _proto.dispatchEvent = function dispatchEvent(event) {
  191. event.target = this;
  192. this._getEventListenersByType(event.type).forEach(function (listener) {
  193. return listener(event);
  194. });
  195. };
  196. /**
  197. * Returns a Set of listeners associated with the passed event type.
  198. * If no handlers have been registered, an empty Set is returned.
  199. *
  200. * @param {string} type The event type.
  201. * @return {Set} An array of handler functions.
  202. * @private
  203. */
  204. _proto._getEventListenersByType = function _getEventListenersByType(type) {
  205. return this._eventListenerRegistry[type] = this._eventListenerRegistry[type] || new Set();
  206. };
  207. return EventTargetShim;
  208. }();
  209. /*
  210. Copyright 2019 Google LLC
  211. Use of this source code is governed by an MIT-style
  212. license that can be found in the LICENSE file or at
  213. https://opensource.org/licenses/MIT.
  214. */
  215. /**
  216. * Returns true if two URLs have the same `.href` property. The URLS can be
  217. * relative, and if they are the current location href is used to resolve URLs.
  218. *
  219. * @private
  220. * @param {string} url1
  221. * @param {string} url2
  222. * @return {boolean}
  223. */
  224. var urlsMatch = function urlsMatch(url1, url2) {
  225. return new URL(url1, location).href === new URL(url2, location).href;
  226. };
  227. /*
  228. Copyright 2019 Google LLC
  229. Use of this source code is governed by an MIT-style
  230. license that can be found in the LICENSE file or at
  231. https://opensource.org/licenses/MIT.
  232. */
  233. /**
  234. * A minimal `Event` subclass shim.
  235. * This doesn't *actually* subclass `Event` because not all browsers support
  236. * constructable `EventTarget`, and using a real `Event` will error.
  237. * @private
  238. */
  239. var WorkboxEvent =
  240. /**
  241. * @param {string} type
  242. * @param {Object} props
  243. */
  244. function WorkboxEvent(type, props) {
  245. Object.assign(this, props, {
  246. type: type
  247. });
  248. };
  249. function _catch(body, recover) {
  250. try {
  251. var result = body();
  252. } catch (e) {
  253. return recover(e);
  254. }
  255. if (result && result.then) {
  256. return result.then(void 0, recover);
  257. }
  258. return result;
  259. }
  260. function _async(f) {
  261. return function () {
  262. for (var args = [], i = 0; i < arguments.length; i++) {
  263. args[i] = arguments[i];
  264. }
  265. try {
  266. return Promise.resolve(f.apply(this, args));
  267. } catch (e) {
  268. return Promise.reject(e);
  269. }
  270. };
  271. }
  272. function _invoke(body, then) {
  273. var result = body();
  274. if (result && result.then) {
  275. return result.then(then);
  276. }
  277. return then(result);
  278. }
  279. function _await(value, then, direct) {
  280. if (direct) {
  281. return then ? then(value) : value;
  282. }
  283. if (!value || !value.then) {
  284. value = Promise.resolve(value);
  285. }
  286. return then ? value.then(then) : value;
  287. }
  288. function _awaitIgnored(value, direct) {
  289. if (!direct) {
  290. return value && value.then ? value.then(_empty) : Promise.resolve();
  291. }
  292. }
  293. function _empty() {}
  294. // `skipWaiting()` wasn't called. This 200 amount wasn't scientifically
  295. // chosen, but it seems to avoid false positives in my testing.
  296. var WAITING_TIMEOUT_DURATION = 200; // The amount of time after a registration that we can reasonably conclude
  297. // that the registration didn't trigger an update.
  298. var REGISTRATION_TIMEOUT_DURATION = 60000;
  299. /**
  300. * A class to aid in handling service worker registration, updates, and
  301. * reacting to service worker lifecycle events.
  302. *
  303. * @fires [message]{@link module:workbox-window.Workbox#message}
  304. * @fires [installed]{@link module:workbox-window.Workbox#installed}
  305. * @fires [waiting]{@link module:workbox-window.Workbox#waiting}
  306. * @fires [controlling]{@link module:workbox-window.Workbox#controlling}
  307. * @fires [activated]{@link module:workbox-window.Workbox#activated}
  308. * @fires [redundant]{@link module:workbox-window.Workbox#redundant}
  309. * @fires [externalinstalled]{@link module:workbox-window.Workbox#externalinstalled}
  310. * @fires [externalwaiting]{@link module:workbox-window.Workbox#externalwaiting}
  311. * @fires [externalactivated]{@link module:workbox-window.Workbox#externalactivated}
  312. *
  313. * @memberof module:workbox-window
  314. */
  315. var Workbox =
  316. /*#__PURE__*/
  317. function (_EventTargetShim) {
  318. _inheritsLoose(Workbox, _EventTargetShim);
  319. /**
  320. * Creates a new Workbox instance with a script URL and service worker
  321. * options. The script URL and options are the same as those used when
  322. * calling `navigator.serviceWorker.register(scriptURL, options)`. See:
  323. * https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register
  324. *
  325. * @param {string} scriptURL The service worker script associated with this
  326. * instance.
  327. * @param {Object} [registerOptions] The service worker options associated
  328. * with this instance.
  329. */
  330. function Workbox(scriptURL, registerOptions) {
  331. var _this;
  332. if (registerOptions === void 0) {
  333. registerOptions = {};
  334. }
  335. _this = _EventTargetShim.call(this) || this;
  336. _this._scriptURL = scriptURL;
  337. _this._registerOptions = registerOptions;
  338. _this._updateFoundCount = 0; // Deferreds we can resolve later.
  339. _this._swDeferred = new Deferred();
  340. _this._activeDeferred = new Deferred();
  341. _this._controllingDeferred = new Deferred(); // Bind event handler callbacks.
  342. _this._onMessage = _this._onMessage.bind(_assertThisInitialized(_assertThisInitialized(_this)));
  343. _this._onStateChange = _this._onStateChange.bind(_assertThisInitialized(_assertThisInitialized(_this)));
  344. _this._onUpdateFound = _this._onUpdateFound.bind(_assertThisInitialized(_assertThisInitialized(_this)));
  345. _this._onControllerChange = _this._onControllerChange.bind(_assertThisInitialized(_assertThisInitialized(_this)));
  346. return _this;
  347. }
  348. /**
  349. * Registers a service worker for this instances script URL and service
  350. * worker options. By default this method delays registration until after
  351. * the window has loaded.
  352. *
  353. * @param {Object} [options]
  354. * @param {Function} [options.immediate=false] Setting this to true will
  355. * register the service worker immediately, even if the window has
  356. * not loaded (not recommended).
  357. */
  358. var _proto = Workbox.prototype;
  359. _proto.register = _async(function (_temp) {
  360. var _this2 = this;
  361. var _ref = _temp === void 0 ? {} : _temp,
  362. _ref$immediate = _ref.immediate,
  363. immediate = _ref$immediate === void 0 ? false : _ref$immediate;
  364. {
  365. if (_this2._registrationTime) {
  366. logger.error('Cannot re-register a Workbox instance after it has ' + 'been registered. Create a new instance instead.');
  367. return;
  368. }
  369. }
  370. return _invoke(function () {
  371. if (!immediate && document.readyState !== 'complete') {
  372. return _awaitIgnored(new Promise(function (res) {
  373. return addEventListener('load', res);
  374. }));
  375. }
  376. }, function () {
  377. // Set this flag to true if any service worker was controlling the page
  378. // at registration time.
  379. _this2._isUpdate = Boolean(navigator.serviceWorker.controller); // Before registering, attempt to determine if a SW is already controlling
  380. // the page, and if that SW script (and version, if specified) matches this
  381. // instance's script.
  382. _this2._compatibleControllingSW = _this2._getControllingSWIfCompatible();
  383. return _await(_this2._registerScript(), function (_this2$_registerScrip) {
  384. _this2._registration = _this2$_registerScrip;
  385. // If we have a compatible controller, store the controller as the "own"
  386. // SW, resolve active/controlling deferreds and add necessary listeners.
  387. if (_this2._compatibleControllingSW) {
  388. _this2._sw = _this2._compatibleControllingSW;
  389. _this2._activeDeferred.resolve(_this2._compatibleControllingSW);
  390. _this2._controllingDeferred.resolve(_this2._compatibleControllingSW);
  391. _this2._reportWindowReady(_this2._compatibleControllingSW);
  392. _this2._compatibleControllingSW.addEventListener('statechange', _this2._onStateChange, {
  393. once: true
  394. });
  395. } // If there's a waiting service worker with a matching URL before the
  396. // `updatefound` event fires, it likely means that this site is open
  397. // in another tab, or the user refreshed the page (and thus the prevoius
  398. // page wasn't fully unloaded before this page started loading).
  399. // https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#waiting
  400. var waitingSW = _this2._registration.waiting;
  401. if (waitingSW && urlsMatch(waitingSW.scriptURL, _this2._scriptURL)) {
  402. // Store the waiting SW as the "own" Sw, even if it means overwriting
  403. // a compatible controller.
  404. _this2._sw = waitingSW; // Run this in the next microtask, so any code that adds an event
  405. // listener after awaiting `register()` will get this event.
  406. Promise.resolve().then(function () {
  407. _this2.dispatchEvent(new WorkboxEvent('waiting', {
  408. sw: waitingSW,
  409. wasWaitingBeforeRegister: true
  410. }));
  411. {
  412. logger.warn('A service worker was already waiting to activate ' + 'before this script was registered...');
  413. }
  414. });
  415. } // If an "own" SW is already set, resolve the deferred.
  416. if (_this2._sw) {
  417. _this2._swDeferred.resolve(_this2._sw);
  418. }
  419. {
  420. logger.log('Successfully registered service worker.', _this2._scriptURL);
  421. if (navigator.serviceWorker.controller) {
  422. if (_this2._compatibleControllingSW) {
  423. logger.debug('A service worker with the same script URL ' + 'is already controlling this page.');
  424. } else {
  425. logger.debug('A service worker with a different script URL is ' + 'currently controlling the page. The browser is now fetching ' + 'the new script now...');
  426. }
  427. }
  428. var currentPageIsOutOfScope = function currentPageIsOutOfScope() {
  429. var scopeURL = new URL(_this2._registerOptions.scope || _this2._scriptURL, document.baseURI);
  430. var scopeURLBasePath = new URL('./', scopeURL.href).pathname;
  431. return !location.pathname.startsWith(scopeURLBasePath);
  432. };
  433. if (currentPageIsOutOfScope()) {
  434. logger.warn('The current page is not in scope for the registered ' + 'service worker. Was this a mistake?');
  435. }
  436. }
  437. _this2._registration.addEventListener('updatefound', _this2._onUpdateFound);
  438. navigator.serviceWorker.addEventListener('controllerchange', _this2._onControllerChange, {
  439. once: true
  440. }); // Add message listeners.
  441. if ('BroadcastChannel' in self) {
  442. _this2._broadcastChannel = new BroadcastChannel('workbox');
  443. _this2._broadcastChannel.addEventListener('message', _this2._onMessage);
  444. }
  445. navigator.serviceWorker.addEventListener('message', _this2._onMessage);
  446. return _this2._registration;
  447. });
  448. });
  449. });
  450. /**
  451. * Resolves to the service worker registered by this instance as soon as it
  452. * is active. If a service worker was already controlling at registration
  453. * time then it will resolve to that if the script URLs (and optionally
  454. * script versions) match, otherwise it will wait until an update is found
  455. * and activates.
  456. *
  457. * @return {Promise<ServiceWorker>}
  458. */
  459. /**
  460. * Resolves with a reference to a service worker that matches the script URL
  461. * of this instance, as soon as it's available.
  462. *
  463. * If, at registration time, there's already an active or waiting service
  464. * worker with a matching script URL, it will be used (with the waiting
  465. * service worker taking precedence over the active service worker if both
  466. * match, since the waiting service worker would have been registered more
  467. * recently).
  468. * If there's no matching active or waiting service worker at registration
  469. * time then the promise will not resolve until an update is found and starts
  470. * installing, at which point the installing service worker is used.
  471. *
  472. * @return {Promise<ServiceWorker>}
  473. */
  474. _proto.getSW = _async(function () {
  475. var _this3 = this;
  476. // If `this._sw` is set, resolve with that as we want `getSW()` to
  477. // return the correct (new) service worker if an update is found.
  478. return _this3._sw || _this3._swDeferred.promise;
  479. });
  480. /**
  481. * Sends the passed data object to the service worker registered by this
  482. * instance (via [`getSW()`]{@link module:workbox-window.Workbox#getSW}) and resolves
  483. * with a response (if any).
  484. *
  485. * A response can be set in a message handler in the service worker by
  486. * calling `event.ports[0].postMessage(...)`, which will resolve the promise
  487. * returned by `messageSW()`. If no response is set, the promise will never
  488. * resolve.
  489. *
  490. * @param {Object} data An object to send to the service worker
  491. * @return {Promise<Object>}
  492. */
  493. _proto.messageSW = _async(function (data) {
  494. var _this4 = this;
  495. return _await(_this4.getSW(), function (sw) {
  496. return messageSW(sw, data);
  497. });
  498. });
  499. /**
  500. * Checks for a service worker already controlling the page and returns
  501. * it if its script URL matchs.
  502. *
  503. * @private
  504. * @return {ServiceWorker|undefined}
  505. */
  506. _proto._getControllingSWIfCompatible = function _getControllingSWIfCompatible() {
  507. var controller = navigator.serviceWorker.controller;
  508. if (controller && urlsMatch(controller.scriptURL, this._scriptURL)) {
  509. return controller;
  510. }
  511. };
  512. /**
  513. * Registers a service worker for this instances script URL and register
  514. * options and tracks the time registration was complete.
  515. *
  516. * @private
  517. */
  518. _proto._registerScript = _async(function () {
  519. var _this5 = this;
  520. return _catch(function () {
  521. return _await(navigator.serviceWorker.register(_this5._scriptURL, _this5._registerOptions), function (reg) {
  522. // Keep track of when registration happened, so it can be used in the
  523. // `this._onUpdateFound` heuristic. Also use the presence of this
  524. // property as a way to see if `.register()` has been called.
  525. _this5._registrationTime = performance.now();
  526. return reg;
  527. });
  528. }, function (error) {
  529. {
  530. logger.error(error);
  531. } // Re-throw the error.
  532. throw error;
  533. });
  534. });
  535. /**
  536. * Sends a message to the passed service worker that the window is ready.
  537. *
  538. * @param {ServiceWorker} sw
  539. * @private
  540. */
  541. _proto._reportWindowReady = function _reportWindowReady(sw) {
  542. messageSW(sw, {
  543. type: 'WINDOW_READY',
  544. meta: 'workbox-window'
  545. });
  546. };
  547. /**
  548. * @private
  549. */
  550. _proto._onUpdateFound = function _onUpdateFound() {
  551. var installingSW = this._registration.installing; // If the script URL passed to `navigator.serviceWorker.register()` is
  552. // different from the current controlling SW's script URL, we know any
  553. // successful registration calls will trigger an `updatefound` event.
  554. // But if the registered script URL is the same as the current controlling
  555. // SW's script URL, we'll only get an `updatefound` event if the file
  556. // changed since it was last registered. This can be a problem if the user
  557. // opens up the same page in a different tab, and that page registers
  558. // a SW that triggers an update. It's a problem because this page has no
  559. // good way of knowing whether the `updatefound` event came from the SW
  560. // script it registered or from a registration attempt made by a newer
  561. // version of the page running in another tab.
  562. // To minimize the possibility of a false positive, we use the logic here:
  563. var updateLikelyTriggeredExternally = // Since we enforce only calling `register()` once, and since we don't
  564. // add the `updatefound` event listener until the `register()` call, if
  565. // `_updateFoundCount` is > 0 then it means this method has already
  566. // been called, thus this SW must be external
  567. this._updateFoundCount > 0 || // If the script URL of the installing SW is different from this
  568. // instance's script URL, we know it's definitely not from our
  569. // registration.
  570. !urlsMatch(installingSW.scriptURL, this._scriptURL) || // If all of the above are false, then we use a time-based heuristic:
  571. // Any `updatefound` event that occurs long after our registration is
  572. // assumed to be external.
  573. performance.now() > this._registrationTime + REGISTRATION_TIMEOUT_DURATION ? // If any of the above are not true, we assume the update was
  574. // triggered by this instance.
  575. true : false;
  576. if (updateLikelyTriggeredExternally) {
  577. this._externalSW = installingSW;
  578. this._registration.removeEventListener('updatefound', this._onUpdateFound);
  579. } else {
  580. // If the update was not triggered externally we know the installing
  581. // SW is the one we registered, so we set it.
  582. this._sw = installingSW;
  583. this._swDeferred.resolve(installingSW); // The `installing` state isn't something we have a dedicated
  584. // callback for, but we do log messages for it in development.
  585. {
  586. if (navigator.serviceWorker.controller) {
  587. logger.log('Updated service worker found. Installing now...');
  588. } else {
  589. logger.log('Service worker is installing...');
  590. }
  591. }
  592. } // Increment the `updatefound` count, so future invocations of this
  593. // method can be sure they were triggered externally.
  594. ++this._updateFoundCount; // Add a `statechange` listener regardless of whether this update was
  595. // triggered externally, since we have callbacks for both.
  596. installingSW.addEventListener('statechange', this._onStateChange);
  597. };
  598. /**
  599. * @private
  600. * @param {Event} originalEvent
  601. */
  602. _proto._onStateChange = function _onStateChange(originalEvent) {
  603. var _this6 = this;
  604. var sw = originalEvent.target;
  605. var state = sw.state;
  606. var isExternal = sw === this._externalSW;
  607. var eventPrefix = isExternal ? 'external' : '';
  608. var eventProps = {
  609. sw: sw,
  610. originalEvent: originalEvent
  611. };
  612. if (!isExternal && this._isUpdate) {
  613. eventProps.isUpdate = true;
  614. }
  615. this.dispatchEvent(new WorkboxEvent(eventPrefix + state, eventProps));
  616. if (state === 'installed') {
  617. // This timeout is used to ignore cases where the service worker calls
  618. // `skipWaiting()` in the install event, thus moving it directly in the
  619. // activating state. (Since all service workers *must* go through the
  620. // waiting phase, the only way to detect `skipWaiting()` called in the
  621. // install event is to observe that the time spent in the waiting phase
  622. // is very short.)
  623. // NOTE: we don't need separate timeouts for the own and external SWs
  624. // since they can't go through these phases at the same time.
  625. this._waitingTimeout = setTimeout(function () {
  626. // Ensure the SW is still waiting (it may now be redundant).
  627. if (state === 'installed' && _this6._registration.waiting === sw) {
  628. _this6.dispatchEvent(new WorkboxEvent(eventPrefix + 'waiting', eventProps));
  629. {
  630. if (isExternal) {
  631. logger.warn('An external service worker has installed but is ' + 'waiting for this client to close before activating...');
  632. } else {
  633. logger.warn('The service worker has installed but is waiting ' + 'for existing clients to close before activating...');
  634. }
  635. }
  636. }
  637. }, WAITING_TIMEOUT_DURATION);
  638. } else if (state === 'activating') {
  639. clearTimeout(this._waitingTimeout);
  640. if (!isExternal) {
  641. this._activeDeferred.resolve(sw);
  642. }
  643. }
  644. {
  645. switch (state) {
  646. case 'installed':
  647. if (isExternal) {
  648. logger.warn('An external service worker has installed. ' + 'You may want to suggest users reload this page.');
  649. } else {
  650. logger.log('Registered service worker installed.');
  651. }
  652. break;
  653. case 'activated':
  654. if (isExternal) {
  655. logger.warn('An external service worker has activated.');
  656. } else {
  657. logger.log('Registered service worker activated.');
  658. if (sw !== navigator.serviceWorker.controller) {
  659. logger.warn('The registered service worker is active but ' + 'not yet controlling the page. Reload or run ' + '`clients.claim()` in the service worker.');
  660. }
  661. }
  662. break;
  663. case 'redundant':
  664. if (sw === this._compatibleControllingSW) {
  665. logger.log('Previously controlling service worker now redundant!');
  666. } else if (!isExternal) {
  667. logger.log('Registered service worker now redundant!');
  668. }
  669. break;
  670. }
  671. }
  672. };
  673. /**
  674. * @private
  675. * @param {Event} originalEvent
  676. */
  677. _proto._onControllerChange = function _onControllerChange(originalEvent) {
  678. var sw = this._sw;
  679. if (sw === navigator.serviceWorker.controller) {
  680. this.dispatchEvent(new WorkboxEvent('controlling', {
  681. sw: sw,
  682. originalEvent: originalEvent
  683. }));
  684. {
  685. logger.log('Registered service worker now controlling this page.');
  686. }
  687. this._controllingDeferred.resolve(sw);
  688. }
  689. };
  690. /**
  691. * @private
  692. * @param {Event} originalEvent
  693. */
  694. _proto._onMessage = function _onMessage(originalEvent) {
  695. var data = originalEvent.data;
  696. this.dispatchEvent(new WorkboxEvent('message', {
  697. data: data,
  698. originalEvent: originalEvent
  699. }));
  700. };
  701. _createClass(Workbox, [{
  702. key: "active",
  703. get: function get() {
  704. return this._activeDeferred.promise;
  705. }
  706. /**
  707. * Resolves to the service worker registered by this instance as soon as it
  708. * is controlling the page. If a service worker was already controlling at
  709. * registration time then it will resolve to that if the script URLs (and
  710. * optionally script versions) match, otherwise it will wait until an update
  711. * is found and starts controlling the page.
  712. * Note: the first time a service worker is installed it will active but
  713. * not start controlling the page unless `clients.claim()` is called in the
  714. * service worker.
  715. *
  716. * @return {Promise<ServiceWorker>}
  717. */
  718. }, {
  719. key: "controlling",
  720. get: function get() {
  721. return this._controllingDeferred.promise;
  722. }
  723. }]);
  724. return Workbox;
  725. }(EventTargetShim); // The jsdoc comments below outline the events this instance may dispatch:
  726. /*
  727. Copyright 2019 Google LLC
  728. Use of this source code is governed by an MIT-style
  729. license that can be found in the LICENSE file or at
  730. https://opensource.org/licenses/MIT.
  731. */
  732. export { Workbox, messageSW };
  733. //# sourceMappingURL=workbox-window.dev.es5.mjs.map