@dr.pogodin/react-utils 1.14.1 → 1.14.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -38,19 +38,21 @@ function ClientSide({
38
38
  const {
39
39
  current: heap
40
40
  } = (0, _react.useRef)({
41
+ mounted: false,
41
42
  pendingStyles: [],
42
- renderInitialized: false,
43
- stylesInitialized: false
43
+ renderInitialized: false
44
44
  }); // publicPath from buildInfo does not have a trailing slash at the end.
45
45
 
46
46
  const {
47
47
  publicPath
48
- } = (0, _isomorphy.getBuildInfo)(); // This code block initiates style loading as soon as possible; it collects
49
- // into heap.pendingStyles all style load promises; and heap.stylesInitialized
50
- // flag remains set until the styles are teared down upon unmounting.
51
-
52
- if (!heap.stylesInitialized) {
53
- heap.stylesInitialized = true;
48
+ } = (0, _isomorphy.getBuildInfo)(); // This code block initiates style loading as soon as possible, even prior to
49
+ // the component loading, and it collects all style load / failure promises
50
+ // into heap.pendingStyles array, allowing us to wait and thus avoid flash of
51
+ // unstyled content issue (that's why we don't rely on mini-css-extract-plugin
52
+ // to handle CSS chunk mounting and unmounting, which it is able to do).
53
+
54
+ if (!heap.mounted) {
55
+ heap.mounted = true;
54
56
  window.CHUNK_GROUPS[chunkName].forEach(asset => {
55
57
  if (!asset.endsWith('.css')) return;
56
58
  const path = `${publicPath}/${asset}`;
@@ -61,7 +63,10 @@ function ClientSide({
61
63
  link.setAttribute('href', path);
62
64
  link.setAttribute('rel', 'stylesheet');
63
65
  const barrier = (0, _Barrier.newBarrier)();
64
- link.onload = barrier.resolve;
66
+ link.onload = barrier.resolve; // Even if the style load failed, still allow to mount the component,
67
+ // abeit with broken styling.
68
+
69
+ link.onerror = barrier.resolve;
65
70
  heap.pendingStyles.push(barrier);
66
71
  const head = document.querySelector('head');
67
72
  head.appendChild(link);
@@ -125,13 +130,13 @@ function ClientSide({
125
130
  if (data && !heap.renderInitialized) {
126
131
  heap.renderInitialized = true;
127
132
  Promise.all(heap.pendingStyles).then(() => {
128
- if (heap.stylesInitialized) setRender(createRender());
133
+ if (heap.mounted) setRender(createRender());
129
134
  });
130
135
  } // This effectively fires only once, just before the component unmounts.
131
136
 
132
137
 
133
138
  (0, _react.useEffect)(() => () => {
134
- heap.stylesInitialized = false;
139
+ heap.mounted = false;
135
140
  window.CHUNK_GROUPS[chunkName].forEach(item => {
136
141
  if (!item.endsWith('.css')) return;
137
142
  const path = `${publicPath}/${item}`;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/shared/components/CodeSplit/ClientSide.jsx"],"names":["ClientSide","chunkName","children","getClientSide","placeholder","serverSide","rest","current","heap","pendingStyles","renderInitialized","stylesInitialized","publicPath","window","CHUNK_GROUPS","forEach","asset","endsWith","path","link","document","querySelector","createElement","setAttribute","barrier","onload","resolve","push","head","appendChild","dependants","Set","add","data","maxage","time","YEAR_MS","createRender","Scene","default","render","setRender","length","node","__html","innerHTML","Promise","all","then","item","delete","size","removeChild"],"mappings":"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","sourcesContent":["/**\n * Client-side implementation of a split code chunk.\n */\n/* global document, window */\n/* eslint-disable react/jsx-props-no-spreading */\n\nimport { useEffect, useRef, useState } from 'react';\n\nimport { useAsyncData } from '@dr.pogodin/react-global-state';\n\nimport { newBarrier } from 'utils/Barrier';\nimport { getBuildInfo } from 'utils/isomorphy';\nimport time from 'utils/time';\n\nexport default function ClientSide({\n chunkName,\n children,\n getClientSide,\n placeholder,\n\n // Not used in <ClientSide>, but should not go into \"...rest\" either.\n serverSide,\n\n ...rest\n}) {\n const { current: heap } = useRef({\n pendingStyles: [],\n renderInitialized: false,\n stylesInitialized: false,\n });\n\n // publicPath from buildInfo does not have a trailing slash at the end.\n const { publicPath } = getBuildInfo();\n\n // This code block initiates style loading as soon as possible; it collects\n // into heap.pendingStyles all style load promises; and heap.stylesInitialized\n // flag remains set until the styles are teared down upon unmounting.\n if (!heap.stylesInitialized) {\n heap.stylesInitialized = true;\n window.CHUNK_GROUPS[chunkName].forEach((asset) => {\n if (!asset.endsWith('.css')) return;\n const path = `${publicPath}/${asset}`;\n let link = document.querySelector(`link[href=\"${path}\"]`);\n if (!link) {\n link = document.createElement('link');\n link.setAttribute('href', path);\n link.setAttribute('rel', 'stylesheet');\n\n const barrier = newBarrier();\n link.onload = barrier.resolve;\n heap.pendingStyles.push(barrier);\n\n const head = document.querySelector('head');\n head.appendChild(link);\n }\n if (!link.dependants) link.dependants = new Set([chunkName]);\n else link.dependants.add(chunkName);\n });\n }\n\n // Async loading of React component necessary to render the chunk.\n const { data } = useAsyncData(\n `dr_pogodin_react_utils___split_components.${chunkName}`,\n getClientSide,\n { maxage: time.YEAR_MS },\n );\n\n const createRender = () => {\n const Scene = data.default || data;\n return (\n <div data-chunk-name={chunkName}>\n <Scene {...rest}>\n {children}\n </Scene>\n </div>\n );\n };\n\n const [render, setRender] = useState(() => {\n // No need to await anything, we can render the final component right away.\n if (data && !heap.pendingStyles.length) {\n heap.renderInitialized = true;\n return createRender();\n }\n\n // Try to reuse the markup rendered during SSR.\n const node = document.querySelector(`[data-chunk-name=${chunkName}]`);\n if (node) {\n return (\n <div\n /* eslint-disable react/no-danger */\n dangerouslySetInnerHTML={{ __html: node.innerHTML || '' }}\n /* eslint-disable react/no-danger */\n data-chunk-name={chunkName}\n />\n );\n }\n\n // Else render placeholder, or empty div.\n const Scene = placeholder || (() => null);\n return <div><Scene {...rest}>{children}</Scene></div>;\n });\n\n // At this point, if we have data, the absense of heap.renderInitialized flag\n // means we have to await styles loading; once it is done, and if we are still\n // mounted, we can set the final render.\n if (data && !heap.renderInitialized) {\n heap.renderInitialized = true;\n Promise.all(heap.pendingStyles).then(() => {\n if (heap.stylesInitialized) setRender(createRender());\n });\n }\n\n // This effectively fires only once, just before the component unmounts.\n useEffect(() => () => {\n heap.stylesInitialized = false;\n window.CHUNK_GROUPS[chunkName].forEach((item) => {\n if (!item.endsWith('.css')) return;\n const path = `${publicPath}/${item}`;\n const link = document.querySelector(`link[href=\"${path}\"]`);\n link.dependants.delete(chunkName);\n if (!link.dependants.size) {\n const head = document.querySelector('head');\n head.removeChild(link);\n }\n });\n }, [chunkName, heap, publicPath]);\n\n return render;\n}\n"],"file":"ClientSide.js"}
1
+ {"version":3,"sources":["../../../../../src/shared/components/CodeSplit/ClientSide.jsx"],"names":["ClientSide","chunkName","children","getClientSide","placeholder","serverSide","rest","current","heap","mounted","pendingStyles","renderInitialized","publicPath","window","CHUNK_GROUPS","forEach","asset","endsWith","path","link","document","querySelector","createElement","setAttribute","barrier","onload","resolve","onerror","push","head","appendChild","dependants","Set","add","data","maxage","time","YEAR_MS","createRender","Scene","default","render","setRender","length","node","__html","innerHTML","Promise","all","then","item","delete","size","removeChild"],"mappings":"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","sourcesContent":["/**\n * Client-side implementation of a split code chunk.\n */\n/* global document, window */\n/* eslint-disable react/jsx-props-no-spreading */\n\nimport { useEffect, useRef, useState } from 'react';\n\nimport { useAsyncData } from '@dr.pogodin/react-global-state';\n\nimport { newBarrier } from 'utils/Barrier';\nimport { getBuildInfo } from 'utils/isomorphy';\nimport time from 'utils/time';\n\nexport default function ClientSide({\n chunkName,\n children,\n getClientSide,\n placeholder,\n\n // Not used in <ClientSide>, but should not go into \"...rest\" either.\n serverSide,\n\n ...rest\n}) {\n const { current: heap } = useRef({\n mounted: false,\n pendingStyles: [],\n renderInitialized: false,\n });\n\n // publicPath from buildInfo does not have a trailing slash at the end.\n const { publicPath } = getBuildInfo();\n\n // This code block initiates style loading as soon as possible, even prior to\n // the component loading, and it collects all style load / failure promises\n // into heap.pendingStyles array, allowing us to wait and thus avoid flash of\n // unstyled content issue (that's why we don't rely on mini-css-extract-plugin\n // to handle CSS chunk mounting and unmounting, which it is able to do).\n if (!heap.mounted) {\n heap.mounted = true;\n window.CHUNK_GROUPS[chunkName].forEach((asset) => {\n if (!asset.endsWith('.css')) return;\n const path = `${publicPath}/${asset}`;\n let link = document.querySelector(`link[href=\"${path}\"]`);\n if (!link) {\n link = document.createElement('link');\n link.setAttribute('href', path);\n link.setAttribute('rel', 'stylesheet');\n\n const barrier = newBarrier();\n link.onload = barrier.resolve;\n\n // Even if the style load failed, still allow to mount the component,\n // abeit with broken styling.\n link.onerror = barrier.resolve;\n\n heap.pendingStyles.push(barrier);\n\n const head = document.querySelector('head');\n head.appendChild(link);\n }\n if (!link.dependants) link.dependants = new Set([chunkName]);\n else link.dependants.add(chunkName);\n });\n }\n\n // Async loading of React component necessary to render the chunk.\n const { data } = useAsyncData(\n `dr_pogodin_react_utils___split_components.${chunkName}`,\n getClientSide,\n { maxage: time.YEAR_MS },\n );\n\n const createRender = () => {\n const Scene = data.default || data;\n return (\n <div data-chunk-name={chunkName}>\n <Scene {...rest}>\n {children}\n </Scene>\n </div>\n );\n };\n\n const [render, setRender] = useState(() => {\n // No need to await anything, we can render the final component right away.\n if (data && !heap.pendingStyles.length) {\n heap.renderInitialized = true;\n return createRender();\n }\n\n // Try to reuse the markup rendered during SSR.\n const node = document.querySelector(`[data-chunk-name=${chunkName}]`);\n if (node) {\n return (\n <div\n /* eslint-disable react/no-danger */\n dangerouslySetInnerHTML={{ __html: node.innerHTML || '' }}\n /* eslint-disable react/no-danger */\n data-chunk-name={chunkName}\n />\n );\n }\n\n // Else render placeholder, or empty div.\n const Scene = placeholder || (() => null);\n return <div><Scene {...rest}>{children}</Scene></div>;\n });\n\n // At this point, if we have data, the absense of heap.renderInitialized flag\n // means we have to await styles loading; once it is done, and if we are still\n // mounted, we can set the final render.\n if (data && !heap.renderInitialized) {\n heap.renderInitialized = true;\n Promise.all(heap.pendingStyles).then(() => {\n if (heap.mounted) setRender(createRender());\n });\n }\n\n // This effectively fires only once, just before the component unmounts.\n useEffect(() => () => {\n heap.mounted = false;\n window.CHUNK_GROUPS[chunkName].forEach((item) => {\n if (!item.endsWith('.css')) return;\n const path = `${publicPath}/${item}`;\n const link = document.querySelector(`link[href=\"${path}\"]`);\n link.dependants.delete(chunkName);\n if (!link.dependants.size) {\n const head = document.querySelector('head');\n head.removeChild(link);\n }\n });\n }, [chunkName, heap, publicPath]);\n\n return render;\n}\n"],"file":"ClientSide.js"}
@@ -11,11 +11,8 @@ var _Barrier = require("./Barrier");
11
11
  * Implements a simple semaphore for async code logic.
12
12
  */
13
13
  class Semaphore {
14
- #barrier;
15
- #ready;
16
-
17
- constructor(ready = false) {
18
- this.#ready = ready;
14
+ constructor(ready) {
15
+ this.#ready = !!ready;
19
16
  }
20
17
 
21
18
  get ready() {
@@ -23,21 +20,63 @@ class Semaphore {
23
20
  }
24
21
 
25
22
  setReady(ready) {
26
- this.#ready = ready;
23
+ const bool = !!ready;
27
24
 
28
- if (this.#barrier) {
29
- this.#barrier.resolve();
30
- this.#barrier = undefined;
25
+ if (this.#ready !== bool) {
26
+ this.#ready = bool;
27
+ if (bool && !this.#draining) this.#drainQueue();
31
28
  }
32
29
  }
30
+ /**
31
+ * Waits until the semaphore is ready, and marks it as non-ready (seizes it).
32
+ * @return {Promise}
33
+ */
34
+
35
+
36
+ async seize() {
37
+ await this.waitReady();
38
+ this.setReady(false);
39
+ }
33
40
 
34
41
  async waitReady() {
35
- while (!this.#ready) {
36
- if (!this.#barrier) this.#barrier = (0, _Barrier.newBarrier)();
37
- await this.#barrier; // eslint-disable-line no-await-in-loop
42
+ if (!this.#ready || this.#queue.length) {
43
+ const barrier = (0, _Barrier.newBarrier)();
44
+ this.#queue.push(barrier);
45
+ await barrier;
38
46
  }
39
- }
47
+ } // Private members below this point.
48
+
49
+ /**
50
+ * If semaphore is ready, it releases the next barrier in the queue, if any,
51
+ * and reschedules itself for a call in the next event loop iteration.
52
+ * Otherwise, it breaks the queue draining loop, which will be restarted
53
+ * the next time the semaphore is set ready.
54
+ */
55
+
40
56
 
57
+ #drainQueue() {
58
+ if (this.#ready && this.#queue.length) {
59
+ const next = this.#queue.shift();
60
+ next.resolve(); // Re-schedules itself for the next event loop iteration.
61
+
62
+ if (this.#queue.length) {
63
+ setTimeout(this.#drainQueue.bind(this));
64
+ this.#draining = true;
65
+ return; // Exit here to avoid the drain loop termination below.
66
+ }
67
+ } // Cleans up for the drain loop termination.
68
+
69
+
70
+ this.#draining = false;
71
+ } // "true" when the drain queue process is running (and thus no need to start
72
+ // a new one).
73
+
74
+
75
+ #draining = false; // The array of barriers set for each async code flow awaiting for
76
+ // the Semaphore to become ready.
77
+
78
+ #queue = [];
79
+ #ready;
41
80
  }
42
81
 
43
82
  exports.default = Semaphore;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/shared/utils/Semaphore.js"],"names":["Semaphore","barrier","ready","constructor","setReady","resolve","undefined","waitReady"],"mappings":";;;;;;;AAAA;;AAEA;AACA;AACA;AACe,MAAMA,SAAN,CAAgB;AAC7B,GAACC,OAAD;AAEA,GAACC,KAAD;;AAEAC,EAAAA,WAAW,CAACD,KAAK,GAAG,KAAT,EAAgB;AACzB,SAAK,CAACA,KAAN,GAAcA,KAAd;AACD;;AAEQ,MAALA,KAAK,GAAG;AAAE,WAAO,KAAK,CAACA,KAAb;AAAqB;;AAEnCE,EAAAA,QAAQ,CAACF,KAAD,EAAQ;AACd,SAAK,CAACA,KAAN,GAAcA,KAAd;;AACA,QAAI,KAAK,CAACD,OAAV,EAAmB;AACjB,WAAK,CAACA,OAAN,CAAcI,OAAd;AACA,WAAK,CAACJ,OAAN,GAAgBK,SAAhB;AACD;AACF;;AAEc,QAATC,SAAS,GAAG;AAChB,WAAO,CAAC,KAAK,CAACL,KAAd,EAAqB;AACnB,UAAI,CAAC,KAAK,CAACD,OAAX,EAAoB,KAAK,CAACA,OAAN,GAAgB,0BAAhB;AACpB,YAAM,KAAK,CAACA,OAAZ,CAFmB,CAEE;AACtB;AACF;;AAxB4B","sourcesContent":["import { newBarrier } from './Barrier';\n\n/**\n * Implements a simple semaphore for async code logic.\n */\nexport default class Semaphore {\n #barrier;\n\n #ready;\n\n constructor(ready = false) {\n this.#ready = ready;\n }\n\n get ready() { return this.#ready; }\n\n setReady(ready) {\n this.#ready = ready;\n if (this.#barrier) {\n this.#barrier.resolve();\n this.#barrier = undefined;\n }\n }\n\n async waitReady() {\n while (!this.#ready) {\n if (!this.#barrier) this.#barrier = newBarrier();\n await this.#barrier; // eslint-disable-line no-await-in-loop\n }\n }\n}\n"],"file":"Semaphore.js"}
1
+ {"version":3,"sources":["../../../../src/shared/utils/Semaphore.js"],"names":["Semaphore","constructor","ready","setReady","bool","draining","drainQueue","seize","waitReady","queue","length","barrier","push","next","shift","resolve","setTimeout","bind"],"mappings":";;;;;;;AAAA;;AAEA;AACA;AACA;AACe,MAAMA,SAAN,CAAgB;AAC7BC,EAAAA,WAAW,CAACC,KAAD,EAAQ;AACjB,SAAK,CAACA,KAAN,GAAc,CAAC,CAACA,KAAhB;AACD;;AAEQ,MAALA,KAAK,GAAG;AAAE,WAAO,KAAK,CAACA,KAAb;AAAqB;;AAEnCC,EAAAA,QAAQ,CAACD,KAAD,EAAQ;AACd,UAAME,IAAI,GAAG,CAAC,CAACF,KAAf;;AACA,QAAI,KAAK,CAACA,KAAN,KAAgBE,IAApB,EAA0B;AACxB,WAAK,CAACF,KAAN,GAAcE,IAAd;AACA,UAAIA,IAAI,IAAI,CAAC,KAAK,CAACC,QAAnB,EAA6B,KAAK,CAACC,UAAN;AAC9B;AACF;AAED;AACF;AACA;AACA;;;AACa,QAALC,KAAK,GAAG;AACZ,UAAM,KAAKC,SAAL,EAAN;AACA,SAAKL,QAAL,CAAc,KAAd;AACD;;AAEc,QAATK,SAAS,GAAG;AAChB,QAAI,CAAC,KAAK,CAACN,KAAP,IAAgB,KAAK,CAACO,KAAN,CAAYC,MAAhC,EAAwC;AACtC,YAAMC,OAAO,GAAG,0BAAhB;AACA,WAAK,CAACF,KAAN,CAAYG,IAAZ,CAAiBD,OAAjB;AACA,YAAMA,OAAN;AACD;AACF,GA9B4B,CAgC7B;;AAEA;AACF;AACA;AACA;AACA;AACA;;;AACE,GAACL,UAAU,GAAG;AACZ,QAAI,KAAK,CAACJ,KAAN,IAAe,KAAK,CAACO,KAAN,CAAYC,MAA/B,EAAuC;AACrC,YAAMG,IAAI,GAAG,KAAK,CAACJ,KAAN,CAAYK,KAAZ,EAAb;AACAD,MAAAA,IAAI,CAACE,OAAL,GAFqC,CAIrC;;AACA,UAAI,KAAK,CAACN,KAAN,CAAYC,MAAhB,EAAwB;AACtBM,QAAAA,UAAU,CAAC,KAAK,CAACV,UAAN,CAAiBW,IAAjB,CAAsB,IAAtB,CAAD,CAAV;AACA,aAAK,CAACZ,QAAN,GAAiB,IAAjB;AACA,eAHsB,CAGd;AACT;AACF,KAXW,CAaZ;;;AACA,SAAK,CAACA,QAAN,GAAiB,KAAjB;AACD,GAvD4B,CAyD7B;AACA;;;AACA,GAACA,QAAD,GAAY,KAAZ,CA3D6B,CA6D7B;AACA;;AACA,GAACI,KAAD,GAAS,EAAT;AAEA,GAACP,KAAD;AAjE6B","sourcesContent":["import { newBarrier } from './Barrier';\n\n/**\n * Implements a simple semaphore for async code logic.\n */\nexport default class Semaphore {\n constructor(ready) {\n this.#ready = !!ready;\n }\n\n get ready() { return this.#ready; }\n\n setReady(ready) {\n const bool = !!ready;\n if (this.#ready !== bool) {\n this.#ready = bool;\n if (bool && !this.#draining) this.#drainQueue();\n }\n }\n\n /**\n * Waits until the semaphore is ready, and marks it as non-ready (seizes it).\n * @return {Promise}\n */\n async seize() {\n await this.waitReady();\n this.setReady(false);\n }\n\n async waitReady() {\n if (!this.#ready || this.#queue.length) {\n const barrier = newBarrier();\n this.#queue.push(barrier);\n await barrier;\n }\n }\n\n // Private members below this point.\n\n /**\n * If semaphore is ready, it releases the next barrier in the queue, if any,\n * and reschedules itself for a call in the next event loop iteration.\n * Otherwise, it breaks the queue draining loop, which will be restarted\n * the next time the semaphore is set ready.\n */\n #drainQueue() {\n if (this.#ready && this.#queue.length) {\n const next = this.#queue.shift();\n next.resolve();\n\n // Re-schedules itself for the next event loop iteration.\n if (this.#queue.length) {\n setTimeout(this.#drainQueue.bind(this));\n this.#draining = true;\n return; // Exit here to avoid the drain loop termination below.\n }\n }\n\n // Cleans up for the drain loop termination.\n this.#draining = false;\n }\n\n // \"true\" when the drain queue process is running (and thus no need to start\n // a new one).\n #draining = false;\n\n // The array of barriers set for each async code flow awaiting for\n // the Semaphore to become ready.\n #queue = [];\n\n #ready;\n}\n"],"file":"Semaphore.js"}
@@ -33,7 +33,7 @@ function splitComponent({
33
33
  return ({
34
34
  children = [],
35
35
  ...props
36
- }) => /*#__PURE__*/(0, _react.createElement)(_CodeSplit.default, { ...props,
36
+ } = {}) => /*#__PURE__*/(0, _react.createElement)(_CodeSplit.default, { ...props,
37
37
  chunkName,
38
38
  getClientSide,
39
39
  placeholder,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/shared/utils/splitComponent.js"],"names":["splitComponent","chunkName","getClientSide","placeholder","serverSide","children","props","CodeSplit"],"mappings":";;;;;;;;;AAAA;;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACe,SAASA,cAAT,CAAwB;AACrCC,EAAAA,SADqC;AAErCC,EAAAA,aAFqC;AAGrCC,EAAAA,WAHqC;AAIrCC,EAAAA;AAJqC,CAAxB,EAKZ;AACD;AACA,SAAO,CAAC;AAAEC,IAAAA,QAAQ,GAAG,EAAb;AAAiB,OAAGC;AAApB,GAAD,kBAAiC,0BACtCC,kBADsC,EAEtC,EACE,GAAGD,KADL;AAEEL,IAAAA,SAFF;AAGEC,IAAAA,aAHF;AAIEC,IAAAA,WAJF;AAKEC,IAAAA;AALF,GAFsC,EAStC,GAAGC,QATmC,CAAxC;AAWD","sourcesContent":["import { createElement } from 'react';\nimport CodeSplit from 'components/CodeSplit';\n\n/**\n * Wraps a regular React component into a \"code splitting\" component,\n * i.e. all code used exclusively by that component and its sub-tree\n * will go into a separate, asynchronously loaded, code chunk for\n * the client-side.\n * @param {object} options\n * @param {string} options.chunkName\n * @param {function} options.getClientSide\n * @param {React.ElementType} [options.placeholder]\n * @param {React.ElementType} [options.serverSide]\n * @returns {React.ElementType}\n */\nexport default function splitComponent({\n chunkName,\n getClientSide,\n placeholder,\n serverSide,\n}) {\n // eslint-disable-next-line react/prop-types\n return ({ children = [], ...props }) => createElement(\n CodeSplit,\n {\n ...props,\n chunkName,\n getClientSide,\n placeholder,\n serverSide,\n },\n ...children,\n );\n}\n"],"file":"splitComponent.js"}
1
+ {"version":3,"sources":["../../../../src/shared/utils/splitComponent.js"],"names":["splitComponent","chunkName","getClientSide","placeholder","serverSide","children","props","CodeSplit"],"mappings":";;;;;;;;;AAAA;;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACe,SAASA,cAAT,CAAwB;AACrCC,EAAAA,SADqC;AAErCC,EAAAA,aAFqC;AAGrCC,EAAAA,WAHqC;AAIrCC,EAAAA;AAJqC,CAAxB,EAKZ;AACD;AACA,SAAO,CAAC;AAAEC,IAAAA,QAAQ,GAAG,EAAb;AAAiB,OAAGC;AAApB,MAA8B,EAA/B,kBAAsC,0BAC3CC,kBAD2C,EAE3C,EACE,GAAGD,KADL;AAEEL,IAAAA,SAFF;AAGEC,IAAAA,aAHF;AAIEC,IAAAA,WAJF;AAKEC,IAAAA;AALF,GAF2C,EAS3C,GAAGC,QATwC,CAA7C;AAWD","sourcesContent":["import { createElement } from 'react';\nimport CodeSplit from 'components/CodeSplit';\n\n/**\n * Wraps a regular React component into a \"code splitting\" component,\n * i.e. all code used exclusively by that component and its sub-tree\n * will go into a separate, asynchronously loaded, code chunk for\n * the client-side.\n * @param {object} options\n * @param {string} options.chunkName\n * @param {function} options.getClientSide\n * @param {React.ElementType} [options.placeholder]\n * @param {React.ElementType} [options.serverSide]\n * @returns {React.ElementType}\n */\nexport default function splitComponent({\n chunkName,\n getClientSide,\n placeholder,\n serverSide,\n}) {\n // eslint-disable-next-line react/prop-types\n return ({ children = [], ...props } = {}) => createElement(\n CodeSplit,\n {\n ...props,\n chunkName,\n getClientSide,\n placeholder,\n serverSide,\n },\n ...children,\n );\n}\n"],"file":"splitComponent.js"}
@@ -66,7 +66,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var prop
66
66
  \********************************************************/
67
67
  /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
68
68
 
69
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* binding */ ClientSide; }\n/* harmony export */ });\n/* harmony import */ var _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/slicedToArray */ \"@babel/runtime/helpers/slicedToArray\");\n/* harmony import */ var _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @babel/runtime/helpers/defineProperty */ \"@babel/runtime/helpers/defineProperty\");\n/* harmony import */ var _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _babel_runtime_helpers_objectWithoutProperties__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @babel/runtime/helpers/objectWithoutProperties */ \"@babel/runtime/helpers/objectWithoutProperties\");\n/* harmony import */ var _babel_runtime_helpers_objectWithoutProperties__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_objectWithoutProperties__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _dr_pogodin_react_global_state__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @dr.pogodin/react-global-state */ \"@dr.pogodin/react-global-state\");\n/* harmony import */ var _dr_pogodin_react_global_state__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_dr_pogodin_react_global_state__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _utils_Barrier__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../utils/Barrier */ \"./src/shared/utils/Barrier.js\");\n/* harmony import */ var _utils_isomorphy__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../utils/isomorphy */ \"./src/shared/utils/isomorphy.js\");\n/* harmony import */ var _utils_time__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../utils/time */ \"./src/shared/utils/time.js\");\n/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! react/jsx-runtime */ \"./node_modules/react/jsx-runtime.js\");\n\n\n\nvar _excluded = [\"chunkName\", \"children\", \"getClientSide\", \"placeholder\", \"serverSide\"];\n\nfunction ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }\n\nfunction _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_1___default()(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }\n\n/**\n * Client-side implementation of a split code chunk.\n */\n\n/* global document, window */\n\n/* eslint-disable react/jsx-props-no-spreading */\n\n\n\n\n\n\nfunction ClientSide(_ref) {\n var chunkName = _ref.chunkName,\n children = _ref.children,\n getClientSide = _ref.getClientSide,\n placeholder = _ref.placeholder,\n serverSide = _ref.serverSide,\n rest = _babel_runtime_helpers_objectWithoutProperties__WEBPACK_IMPORTED_MODULE_2___default()(_ref, _excluded);\n\n var _useRef = (0,react__WEBPACK_IMPORTED_MODULE_3__.useRef)({\n pendingStyles: [],\n renderInitialized: false,\n stylesInitialized: false\n }),\n heap = _useRef.current; // publicPath from buildInfo does not have a trailing slash at the end.\n\n\n var _getBuildInfo = (0,_utils_isomorphy__WEBPACK_IMPORTED_MODULE_6__.getBuildInfo)(),\n publicPath = _getBuildInfo.publicPath; // This code block initiates style loading as soon as possible; it collects\n // into heap.pendingStyles all style load promises; and heap.stylesInitialized\n // flag remains set until the styles are teared down upon unmounting.\n\n\n if (!heap.stylesInitialized) {\n heap.stylesInitialized = true;\n window.CHUNK_GROUPS[chunkName].forEach(function (asset) {\n if (!asset.endsWith('.css')) return;\n var path = \"\".concat(publicPath, \"/\").concat(asset);\n var link = document.querySelector(\"link[href=\\\"\".concat(path, \"\\\"]\"));\n\n if (!link) {\n link = document.createElement('link');\n link.setAttribute('href', path);\n link.setAttribute('rel', 'stylesheet');\n var barrier = (0,_utils_Barrier__WEBPACK_IMPORTED_MODULE_5__.newBarrier)();\n link.onload = barrier.resolve;\n heap.pendingStyles.push(barrier);\n var head = document.querySelector('head');\n head.appendChild(link);\n }\n\n if (!link.dependants) link.dependants = new Set([chunkName]);else link.dependants.add(chunkName);\n });\n } // Async loading of React component necessary to render the chunk.\n\n\n var _useAsyncData = (0,_dr_pogodin_react_global_state__WEBPACK_IMPORTED_MODULE_4__.useAsyncData)(\"dr_pogodin_react_utils___split_components.\".concat(chunkName), getClientSide, {\n maxage: _utils_time__WEBPACK_IMPORTED_MODULE_7__[\"default\"].YEAR_MS\n }),\n data = _useAsyncData.data;\n\n var createRender = function createRender() {\n var Scene = data.default || data;\n return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_8__.jsx)(\"div\", {\n \"data-chunk-name\": chunkName,\n children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_8__.jsx)(Scene, _objectSpread(_objectSpread({}, rest), {}, {\n children: children\n }))\n });\n };\n\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_3__.useState)(function () {\n // No need to await anything, we can render the final component right away.\n if (data && !heap.pendingStyles.length) {\n heap.renderInitialized = true;\n return createRender();\n } // Try to reuse the markup rendered during SSR.\n\n\n // Try to reuse the markup rendered during SSR.\n var node = document.querySelector(\"[data-chunk-name=\".concat(chunkName, \"]\"));\n\n if (node) {\n return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_8__.jsx)(\"div\", {\n /* eslint-disable react/no-danger */\n dangerouslySetInnerHTML: {\n __html: node.innerHTML || ''\n }\n /* eslint-disable react/no-danger */\n ,\n\n /* eslint-disable react/no-danger */\n \"data-chunk-name\": chunkName\n });\n } // Else render placeholder, or empty div.\n\n\n // Else render placeholder, or empty div.\n var Scene = placeholder || function () {\n return null;\n };\n\n return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_8__.jsx)(\"div\", {\n children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_8__.jsx)(Scene, _objectSpread(_objectSpread({}, rest), {}, {\n children: children\n }))\n });\n }),\n _useState2 = _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_0___default()(_useState, 2),\n render = _useState2[0],\n setRender = _useState2[1]; // At this point, if we have data, the absense of heap.renderInitialized flag\n // means we have to await styles loading; once it is done, and if we are still\n // mounted, we can set the final render.\n\n\n if (data && !heap.renderInitialized) {\n heap.renderInitialized = true;\n Promise.all(heap.pendingStyles).then(function () {\n if (heap.stylesInitialized) setRender(createRender());\n });\n } // This effectively fires only once, just before the component unmounts.\n\n\n (0,react__WEBPACK_IMPORTED_MODULE_3__.useEffect)(function () {\n return function () {\n heap.stylesInitialized = false;\n window.CHUNK_GROUPS[chunkName].forEach(function (item) {\n if (!item.endsWith('.css')) return;\n var path = \"\".concat(publicPath, \"/\").concat(item);\n var link = document.querySelector(\"link[href=\\\"\".concat(path, \"\\\"]\"));\n link.dependants.delete(chunkName);\n\n if (!link.dependants.size) {\n var head = document.querySelector('head');\n head.removeChild(link);\n }\n });\n };\n }, [chunkName, heap, publicPath]);\n return render;\n}\n\n//# sourceURL=webpack://@dr.pogodin/react-utils/./src/shared/components/CodeSplit/ClientSide.jsx?");
69
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* binding */ ClientSide; }\n/* harmony export */ });\n/* harmony import */ var _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/slicedToArray */ \"@babel/runtime/helpers/slicedToArray\");\n/* harmony import */ var _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @babel/runtime/helpers/defineProperty */ \"@babel/runtime/helpers/defineProperty\");\n/* harmony import */ var _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _babel_runtime_helpers_objectWithoutProperties__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @babel/runtime/helpers/objectWithoutProperties */ \"@babel/runtime/helpers/objectWithoutProperties\");\n/* harmony import */ var _babel_runtime_helpers_objectWithoutProperties__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_objectWithoutProperties__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _dr_pogodin_react_global_state__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @dr.pogodin/react-global-state */ \"@dr.pogodin/react-global-state\");\n/* harmony import */ var _dr_pogodin_react_global_state__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_dr_pogodin_react_global_state__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _utils_Barrier__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../utils/Barrier */ \"./src/shared/utils/Barrier.js\");\n/* harmony import */ var _utils_isomorphy__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../utils/isomorphy */ \"./src/shared/utils/isomorphy.js\");\n/* harmony import */ var _utils_time__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../utils/time */ \"./src/shared/utils/time.js\");\n/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! react/jsx-runtime */ \"./node_modules/react/jsx-runtime.js\");\n\n\n\nvar _excluded = [\"chunkName\", \"children\", \"getClientSide\", \"placeholder\", \"serverSide\"];\n\nfunction ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }\n\nfunction _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_1___default()(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }\n\n/**\n * Client-side implementation of a split code chunk.\n */\n\n/* global document, window */\n\n/* eslint-disable react/jsx-props-no-spreading */\n\n\n\n\n\n\nfunction ClientSide(_ref) {\n var chunkName = _ref.chunkName,\n children = _ref.children,\n getClientSide = _ref.getClientSide,\n placeholder = _ref.placeholder,\n serverSide = _ref.serverSide,\n rest = _babel_runtime_helpers_objectWithoutProperties__WEBPACK_IMPORTED_MODULE_2___default()(_ref, _excluded);\n\n var _useRef = (0,react__WEBPACK_IMPORTED_MODULE_3__.useRef)({\n mounted: false,\n pendingStyles: [],\n renderInitialized: false\n }),\n heap = _useRef.current; // publicPath from buildInfo does not have a trailing slash at the end.\n\n\n var _getBuildInfo = (0,_utils_isomorphy__WEBPACK_IMPORTED_MODULE_6__.getBuildInfo)(),\n publicPath = _getBuildInfo.publicPath; // This code block initiates style loading as soon as possible, even prior to\n // the component loading, and it collects all style load / failure promises\n // into heap.pendingStyles array, allowing us to wait and thus avoid flash of\n // unstyled content issue (that's why we don't rely on mini-css-extract-plugin\n // to handle CSS chunk mounting and unmounting, which it is able to do).\n\n\n if (!heap.mounted) {\n heap.mounted = true;\n window.CHUNK_GROUPS[chunkName].forEach(function (asset) {\n if (!asset.endsWith('.css')) return;\n var path = \"\".concat(publicPath, \"/\").concat(asset);\n var link = document.querySelector(\"link[href=\\\"\".concat(path, \"\\\"]\"));\n\n if (!link) {\n link = document.createElement('link');\n link.setAttribute('href', path);\n link.setAttribute('rel', 'stylesheet');\n var barrier = (0,_utils_Barrier__WEBPACK_IMPORTED_MODULE_5__.newBarrier)();\n link.onload = barrier.resolve; // Even if the style load failed, still allow to mount the component,\n // abeit with broken styling.\n\n link.onerror = barrier.resolve;\n heap.pendingStyles.push(barrier);\n var head = document.querySelector('head');\n head.appendChild(link);\n }\n\n if (!link.dependants) link.dependants = new Set([chunkName]);else link.dependants.add(chunkName);\n });\n } // Async loading of React component necessary to render the chunk.\n\n\n var _useAsyncData = (0,_dr_pogodin_react_global_state__WEBPACK_IMPORTED_MODULE_4__.useAsyncData)(\"dr_pogodin_react_utils___split_components.\".concat(chunkName), getClientSide, {\n maxage: _utils_time__WEBPACK_IMPORTED_MODULE_7__[\"default\"].YEAR_MS\n }),\n data = _useAsyncData.data;\n\n var createRender = function createRender() {\n var Scene = data.default || data;\n return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_8__.jsx)(\"div\", {\n \"data-chunk-name\": chunkName,\n children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_8__.jsx)(Scene, _objectSpread(_objectSpread({}, rest), {}, {\n children: children\n }))\n });\n };\n\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_3__.useState)(function () {\n // No need to await anything, we can render the final component right away.\n if (data && !heap.pendingStyles.length) {\n heap.renderInitialized = true;\n return createRender();\n } // Try to reuse the markup rendered during SSR.\n\n\n // Try to reuse the markup rendered during SSR.\n var node = document.querySelector(\"[data-chunk-name=\".concat(chunkName, \"]\"));\n\n if (node) {\n return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_8__.jsx)(\"div\", {\n /* eslint-disable react/no-danger */\n dangerouslySetInnerHTML: {\n __html: node.innerHTML || ''\n }\n /* eslint-disable react/no-danger */\n ,\n\n /* eslint-disable react/no-danger */\n \"data-chunk-name\": chunkName\n });\n } // Else render placeholder, or empty div.\n\n\n // Else render placeholder, or empty div.\n var Scene = placeholder || function () {\n return null;\n };\n\n return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_8__.jsx)(\"div\", {\n children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_8__.jsx)(Scene, _objectSpread(_objectSpread({}, rest), {}, {\n children: children\n }))\n });\n }),\n _useState2 = _babel_runtime_helpers_slicedToArray__WEBPACK_IMPORTED_MODULE_0___default()(_useState, 2),\n render = _useState2[0],\n setRender = _useState2[1]; // At this point, if we have data, the absense of heap.renderInitialized flag\n // means we have to await styles loading; once it is done, and if we are still\n // mounted, we can set the final render.\n\n\n if (data && !heap.renderInitialized) {\n heap.renderInitialized = true;\n Promise.all(heap.pendingStyles).then(function () {\n if (heap.mounted) setRender(createRender());\n });\n } // This effectively fires only once, just before the component unmounts.\n\n\n (0,react__WEBPACK_IMPORTED_MODULE_3__.useEffect)(function () {\n return function () {\n heap.mounted = false;\n window.CHUNK_GROUPS[chunkName].forEach(function (item) {\n if (!item.endsWith('.css')) return;\n var path = \"\".concat(publicPath, \"/\").concat(item);\n var link = document.querySelector(\"link[href=\\\"\".concat(path, \"\\\"]\"));\n link.dependants.delete(chunkName);\n\n if (!link.dependants.size) {\n var head = document.querySelector('head');\n head.removeChild(link);\n }\n });\n };\n }, [chunkName, heap, publicPath]);\n return render;\n}\n\n//# sourceURL=webpack://@dr.pogodin/react-utils/./src/shared/components/CodeSplit/ClientSide.jsx?");
70
70
 
71
71
  /***/ }),
72
72
 
@@ -246,7 +246,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
246
246
  \***************************************/
247
247
  /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
248
248
 
249
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* binding */ Semaphore; }\n/* harmony export */ });\n/* harmony import */ var _babel_runtime_helpers_asyncToGenerator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/asyncToGenerator */ \"@babel/runtime/helpers/asyncToGenerator\");\n/* harmony import */ var _babel_runtime_helpers_asyncToGenerator__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_asyncToGenerator__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @babel/runtime/helpers/classCallCheck */ \"@babel/runtime/helpers/classCallCheck\");\n/* harmony import */ var _babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @babel/runtime/helpers/createClass */ \"@babel/runtime/helpers/createClass\");\n/* harmony import */ var _babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @babel/runtime/helpers/classPrivateFieldGet */ \"@babel/runtime/helpers/classPrivateFieldGet\");\n/* harmony import */ var _babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _babel_runtime_helpers_classPrivateFieldSet__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @babel/runtime/helpers/classPrivateFieldSet */ \"@babel/runtime/helpers/classPrivateFieldSet\");\n/* harmony import */ var _babel_runtime_helpers_classPrivateFieldSet__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_classPrivateFieldSet__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @babel/runtime/regenerator */ \"@babel/runtime/regenerator\");\n/* harmony import */ var _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var _Barrier__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./Barrier */ \"./src/shared/utils/Barrier.js\");\n\n\n\n\n\n\n\nfunction _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }\n\nfunction _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); } }\n\n\n/**\n * Implements a simple semaphore for async code logic.\n */\n\nvar _barrier = /*#__PURE__*/new WeakMap();\n\nvar _ready = /*#__PURE__*/new WeakMap();\n\nvar Semaphore = /*#__PURE__*/function () {\n function Semaphore() {\n var ready = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n\n _babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1___default()(this, Semaphore);\n\n _classPrivateFieldInitSpec(this, _barrier, {\n writable: true,\n value: void 0\n });\n\n _classPrivateFieldInitSpec(this, _ready, {\n writable: true,\n value: void 0\n });\n\n _babel_runtime_helpers_classPrivateFieldSet__WEBPACK_IMPORTED_MODULE_4___default()(this, _ready, ready);\n }\n\n _babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_2___default()(Semaphore, [{\n key: \"ready\",\n get: function get() {\n return _babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3___default()(this, _ready);\n }\n }, {\n key: \"setReady\",\n value: function setReady(ready) {\n _babel_runtime_helpers_classPrivateFieldSet__WEBPACK_IMPORTED_MODULE_4___default()(this, _ready, ready);\n\n if (_babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3___default()(this, _barrier)) {\n _babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3___default()(this, _barrier).resolve();\n\n _babel_runtime_helpers_classPrivateFieldSet__WEBPACK_IMPORTED_MODULE_4___default()(this, _barrier, undefined);\n }\n }\n }, {\n key: \"waitReady\",\n value: function () {\n var _waitReady = _babel_runtime_helpers_asyncToGenerator__WEBPACK_IMPORTED_MODULE_0___default()( /*#__PURE__*/_babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_5___default().mark(function _callee() {\n return _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_5___default().wrap(function _callee$(_context) {\n while (1) {\n switch (_context.prev = _context.next) {\n case 0:\n if (_babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3___default()(this, _ready)) {\n _context.next = 6;\n break;\n }\n\n if (!_babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3___default()(this, _barrier)) _babel_runtime_helpers_classPrivateFieldSet__WEBPACK_IMPORTED_MODULE_4___default()(this, _barrier, (0,_Barrier__WEBPACK_IMPORTED_MODULE_6__.newBarrier)());\n _context.next = 4;\n return _babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3___default()(this, _barrier);\n\n case 4:\n _context.next = 0;\n break;\n\n case 6:\n case \"end\":\n return _context.stop();\n }\n }\n }, _callee, this);\n }));\n\n function waitReady() {\n return _waitReady.apply(this, arguments);\n }\n\n return waitReady;\n }()\n }]);\n\n return Semaphore;\n}();\n\n\n\n//# sourceURL=webpack://@dr.pogodin/react-utils/./src/shared/utils/Semaphore.js?");
249
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* binding */ Semaphore; }\n/* harmony export */ });\n/* harmony import */ var _babel_runtime_helpers_asyncToGenerator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/asyncToGenerator */ \"@babel/runtime/helpers/asyncToGenerator\");\n/* harmony import */ var _babel_runtime_helpers_asyncToGenerator__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_asyncToGenerator__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @babel/runtime/helpers/classCallCheck */ \"@babel/runtime/helpers/classCallCheck\");\n/* harmony import */ var _babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @babel/runtime/helpers/createClass */ \"@babel/runtime/helpers/createClass\");\n/* harmony import */ var _babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @babel/runtime/helpers/classPrivateFieldGet */ \"@babel/runtime/helpers/classPrivateFieldGet\");\n/* harmony import */ var _babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _babel_runtime_helpers_classPrivateFieldSet__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @babel/runtime/helpers/classPrivateFieldSet */ \"@babel/runtime/helpers/classPrivateFieldSet\");\n/* harmony import */ var _babel_runtime_helpers_classPrivateFieldSet__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_classPrivateFieldSet__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @babel/runtime/regenerator */ \"@babel/runtime/regenerator\");\n/* harmony import */ var _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var _Barrier__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./Barrier */ \"./src/shared/utils/Barrier.js\");\n\n\n\n\n\n\n\nfunction _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }\n\nfunction _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }\n\nfunction _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); } }\n\nfunction _classPrivateMethodGet(receiver, privateSet, fn) { if (!privateSet.has(receiver)) { throw new TypeError(\"attempted to get private field on non-instance\"); } return fn; }\n\n\n/**\n * Implements a simple semaphore for async code logic.\n */\n\nvar _drainQueue = /*#__PURE__*/new WeakSet();\n\nvar _draining = /*#__PURE__*/new WeakMap();\n\nvar _queue = /*#__PURE__*/new WeakMap();\n\nvar _ready = /*#__PURE__*/new WeakMap();\n\nvar Semaphore = /*#__PURE__*/function () {\n function Semaphore(ready) {\n _babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1___default()(this, Semaphore);\n\n _classPrivateMethodInitSpec(this, _drainQueue);\n\n _classPrivateFieldInitSpec(this, _draining, {\n writable: true,\n value: false\n });\n\n _classPrivateFieldInitSpec(this, _queue, {\n writable: true,\n value: []\n });\n\n _classPrivateFieldInitSpec(this, _ready, {\n writable: true,\n value: void 0\n });\n\n _babel_runtime_helpers_classPrivateFieldSet__WEBPACK_IMPORTED_MODULE_4___default()(this, _ready, !!ready);\n }\n\n _babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_2___default()(Semaphore, [{\n key: \"ready\",\n get: function get() {\n return _babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3___default()(this, _ready);\n }\n }, {\n key: \"setReady\",\n value: function setReady(ready) {\n var bool = !!ready;\n\n if (_babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3___default()(this, _ready) !== bool) {\n _babel_runtime_helpers_classPrivateFieldSet__WEBPACK_IMPORTED_MODULE_4___default()(this, _ready, bool);\n\n if (bool && !_babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3___default()(this, _draining)) _classPrivateMethodGet(this, _drainQueue, _drainQueue2).call(this);\n }\n }\n /**\n * Waits until the semaphore is ready, and marks it as non-ready (seizes it).\n * @return {Promise}\n */\n\n }, {\n key: \"seize\",\n value: function () {\n var _seize = _babel_runtime_helpers_asyncToGenerator__WEBPACK_IMPORTED_MODULE_0___default()( /*#__PURE__*/_babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_5___default().mark(function _callee() {\n return _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_5___default().wrap(function _callee$(_context) {\n while (1) {\n switch (_context.prev = _context.next) {\n case 0:\n _context.next = 2;\n return this.waitReady();\n\n case 2:\n this.setReady(false);\n\n case 3:\n case \"end\":\n return _context.stop();\n }\n }\n }, _callee, this);\n }));\n\n function seize() {\n return _seize.apply(this, arguments);\n }\n\n return seize;\n }()\n }, {\n key: \"waitReady\",\n value: function () {\n var _waitReady = _babel_runtime_helpers_asyncToGenerator__WEBPACK_IMPORTED_MODULE_0___default()( /*#__PURE__*/_babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_5___default().mark(function _callee2() {\n var barrier;\n return _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_5___default().wrap(function _callee2$(_context2) {\n while (1) {\n switch (_context2.prev = _context2.next) {\n case 0:\n if (!(!_babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3___default()(this, _ready) || _babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3___default()(this, _queue).length)) {\n _context2.next = 5;\n break;\n }\n\n barrier = (0,_Barrier__WEBPACK_IMPORTED_MODULE_6__.newBarrier)();\n\n _babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3___default()(this, _queue).push(barrier);\n\n _context2.next = 5;\n return barrier;\n\n case 5:\n case \"end\":\n return _context2.stop();\n }\n }\n }, _callee2, this);\n }));\n\n function waitReady() {\n return _waitReady.apply(this, arguments);\n }\n\n return waitReady;\n }() // Private members below this point.\n\n /**\n * If semaphore is ready, it releases the next barrier in the queue, if any,\n * and reschedules itself for a call in the next event loop iteration.\n * Otherwise, it breaks the queue draining loop, which will be restarted\n * the next time the semaphore is set ready.\n */\n\n }]);\n\n return Semaphore;\n}();\n\nfunction _drainQueue2() {\n if (_babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3___default()(this, _ready) && _babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3___default()(this, _queue).length) {\n var next = _babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3___default()(this, _queue).shift();\n\n next.resolve(); // Re-schedules itself for the next event loop iteration.\n\n if (_babel_runtime_helpers_classPrivateFieldGet__WEBPACK_IMPORTED_MODULE_3___default()(this, _queue).length) {\n setTimeout(_classPrivateMethodGet(this, _drainQueue, _drainQueue2).bind(this));\n\n _babel_runtime_helpers_classPrivateFieldSet__WEBPACK_IMPORTED_MODULE_4___default()(this, _draining, true);\n\n return; // Exit here to avoid the drain loop termination below.\n }\n } // Cleans up for the drain loop termination.\n\n\n _babel_runtime_helpers_classPrivateFieldSet__WEBPACK_IMPORTED_MODULE_4___default()(this, _draining, false);\n}\n\n\n\n//# sourceURL=webpack://@dr.pogodin/react-utils/./src/shared/utils/Semaphore.js?");
250
250
 
251
251
  /***/ }),
252
252
 
@@ -286,7 +286,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
286
286
  \********************************************/
287
287
  /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
288
288
 
289
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* binding */ splitComponent; }\n/* harmony export */ });\n/* harmony import */ var _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/defineProperty */ \"@babel/runtime/helpers/defineProperty\");\n/* harmony import */ var _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _babel_runtime_helpers_toConsumableArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @babel/runtime/helpers/toConsumableArray */ \"@babel/runtime/helpers/toConsumableArray\");\n/* harmony import */ var _babel_runtime_helpers_toConsumableArray__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_toConsumableArray__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _babel_runtime_helpers_objectWithoutProperties__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @babel/runtime/helpers/objectWithoutProperties */ \"@babel/runtime/helpers/objectWithoutProperties\");\n/* harmony import */ var _babel_runtime_helpers_objectWithoutProperties__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_objectWithoutProperties__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _components_CodeSplit__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../components/CodeSplit */ \"./src/shared/components/CodeSplit/index.jsx\");\n\n\n\nvar _excluded = [\"children\"];\n\nfunction ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }\n\nfunction _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0___default()(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }\n\n\n\n/**\n * Wraps a regular React component into a \"code splitting\" component,\n * i.e. all code used exclusively by that component and its sub-tree\n * will go into a separate, asynchronously loaded, code chunk for\n * the client-side.\n * @param {object} options\n * @param {string} options.chunkName\n * @param {function} options.getClientSide\n * @param {React.ElementType} [options.placeholder]\n * @param {React.ElementType} [options.serverSide]\n * @returns {React.ElementType}\n */\n\nfunction splitComponent(_ref) {\n var chunkName = _ref.chunkName,\n getClientSide = _ref.getClientSide,\n placeholder = _ref.placeholder,\n serverSide = _ref.serverSide;\n // eslint-disable-next-line react/prop-types\n return function (_ref2) {\n var _ref2$children = _ref2.children,\n children = _ref2$children === void 0 ? [] : _ref2$children,\n props = _babel_runtime_helpers_objectWithoutProperties__WEBPACK_IMPORTED_MODULE_2___default()(_ref2, _excluded);\n\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_3__.createElement.apply(void 0, [_components_CodeSplit__WEBPACK_IMPORTED_MODULE_4__[\"default\"], _objectSpread(_objectSpread({}, props), {}, {\n chunkName: chunkName,\n getClientSide: getClientSide,\n placeholder: placeholder,\n serverSide: serverSide\n })].concat(_babel_runtime_helpers_toConsumableArray__WEBPACK_IMPORTED_MODULE_1___default()(children)));\n };\n}\n\n//# sourceURL=webpack://@dr.pogodin/react-utils/./src/shared/utils/splitComponent.js?");
289
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* binding */ splitComponent; }\n/* harmony export */ });\n/* harmony import */ var _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/defineProperty */ \"@babel/runtime/helpers/defineProperty\");\n/* harmony import */ var _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _babel_runtime_helpers_toConsumableArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @babel/runtime/helpers/toConsumableArray */ \"@babel/runtime/helpers/toConsumableArray\");\n/* harmony import */ var _babel_runtime_helpers_toConsumableArray__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_toConsumableArray__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _babel_runtime_helpers_objectWithoutProperties__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @babel/runtime/helpers/objectWithoutProperties */ \"@babel/runtime/helpers/objectWithoutProperties\");\n/* harmony import */ var _babel_runtime_helpers_objectWithoutProperties__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_objectWithoutProperties__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _components_CodeSplit__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../components/CodeSplit */ \"./src/shared/components/CodeSplit/index.jsx\");\n\n\n\nvar _excluded = [\"children\"];\n\nfunction ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }\n\nfunction _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _babel_runtime_helpers_defineProperty__WEBPACK_IMPORTED_MODULE_0___default()(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }\n\n\n\n/**\n * Wraps a regular React component into a \"code splitting\" component,\n * i.e. all code used exclusively by that component and its sub-tree\n * will go into a separate, asynchronously loaded, code chunk for\n * the client-side.\n * @param {object} options\n * @param {string} options.chunkName\n * @param {function} options.getClientSide\n * @param {React.ElementType} [options.placeholder]\n * @param {React.ElementType} [options.serverSide]\n * @returns {React.ElementType}\n */\n\nfunction splitComponent(_ref) {\n var chunkName = _ref.chunkName,\n getClientSide = _ref.getClientSide,\n placeholder = _ref.placeholder,\n serverSide = _ref.serverSide;\n // eslint-disable-next-line react/prop-types\n return function () {\n var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},\n _ref2$children = _ref2.children,\n children = _ref2$children === void 0 ? [] : _ref2$children,\n props = _babel_runtime_helpers_objectWithoutProperties__WEBPACK_IMPORTED_MODULE_2___default()(_ref2, _excluded);\n\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_3__.createElement.apply(void 0, [_components_CodeSplit__WEBPACK_IMPORTED_MODULE_4__[\"default\"], _objectSpread(_objectSpread({}, props), {}, {\n chunkName: chunkName,\n getClientSide: getClientSide,\n placeholder: placeholder,\n serverSide: serverSide\n })].concat(_babel_runtime_helpers_toConsumableArray__WEBPACK_IMPORTED_MODULE_1___default()(children)));\n };\n}\n\n//# sourceURL=webpack://@dr.pogodin/react-utils/./src/shared/utils/splitComponent.js?");
290
290
 
291
291
  /***/ }),
292
292
 
@@ -1,17 +1,21 @@
1
1
  "use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.default=ClientSide;var _react=require("react");var _reactGlobalState=require("@dr.pogodin/react-global-state");var _Barrier=require("../../utils/Barrier");var _isomorphy=require("../../utils/isomorphy");var _time=_interopRequireDefault(require("../../utils/time"));var _jsxRuntime=require("react/jsx-runtime");/**
2
2
  * Client-side implementation of a split code chunk.
3
3
  */ /* global document, window */ /* eslint-disable react/jsx-props-no-spreading */function ClientSide({chunkName,children,getClientSide,placeholder,// Not used in <ClientSide>, but should not go into "...rest" either.
4
- serverSide,...rest}){const{current:heap}=(0,_react.useRef)({pendingStyles:[],renderInitialized:false,stylesInitialized:false});// publicPath from buildInfo does not have a trailing slash at the end.
5
- const{publicPath}=(0,_isomorphy.getBuildInfo)();// This code block initiates style loading as soon as possible; it collects
6
- // into heap.pendingStyles all style load promises; and heap.stylesInitialized
7
- // flag remains set until the styles are teared down upon unmounting.
8
- if(!heap.stylesInitialized){heap.stylesInitialized=true;window.CHUNK_GROUPS[chunkName].forEach(asset=>{if(!asset.endsWith(".css"))return;const path=`${publicPath}/${asset}`;let link=document.querySelector(`link[href="${path}"]`);if(!link){link=document.createElement("link");link.setAttribute("href",path);link.setAttribute("rel","stylesheet");const barrier=(0,_Barrier.newBarrier)();link.onload=barrier.resolve;heap.pendingStyles.push(barrier);const head=document.querySelector("head");head.appendChild(link)}if(!link.dependants)link.dependants=new Set([chunkName]);else link.dependants.add(chunkName)})}// Async loading of React component necessary to render the chunk.
4
+ serverSide,...rest}){const{current:heap}=(0,_react.useRef)({mounted:false,pendingStyles:[],renderInitialized:false});// publicPath from buildInfo does not have a trailing slash at the end.
5
+ const{publicPath}=(0,_isomorphy.getBuildInfo)();// This code block initiates style loading as soon as possible, even prior to
6
+ // the component loading, and it collects all style load / failure promises
7
+ // into heap.pendingStyles array, allowing us to wait and thus avoid flash of
8
+ // unstyled content issue (that's why we don't rely on mini-css-extract-plugin
9
+ // to handle CSS chunk mounting and unmounting, which it is able to do).
10
+ if(!heap.mounted){heap.mounted=true;window.CHUNK_GROUPS[chunkName].forEach(asset=>{if(!asset.endsWith(".css"))return;const path=`${publicPath}/${asset}`;let link=document.querySelector(`link[href="${path}"]`);if(!link){link=document.createElement("link");link.setAttribute("href",path);link.setAttribute("rel","stylesheet");const barrier=(0,_Barrier.newBarrier)();link.onload=barrier.resolve;// Even if the style load failed, still allow to mount the component,
11
+ // abeit with broken styling.
12
+ link.onerror=barrier.resolve;heap.pendingStyles.push(barrier);const head=document.querySelector("head");head.appendChild(link)}if(!link.dependants)link.dependants=new Set([chunkName]);else link.dependants.add(chunkName)})}// Async loading of React component necessary to render the chunk.
9
13
  const{data}=(0,_reactGlobalState.useAsyncData)(`dr_pogodin_react_utils___split_components.${chunkName}`,getClientSide,{maxage:_time.default.YEAR_MS});const createRender=()=>{const Scene=data.default||data;return/*#__PURE__*/(0,_jsxRuntime.jsx)("div",{"data-chunk-name":chunkName,children:/*#__PURE__*/(0,_jsxRuntime.jsx)(Scene,{...rest,children:children})})};const[render,setRender]=(0,_react.useState)(()=>{// No need to await anything, we can render the final component right away.
10
14
  if(data&&!heap.pendingStyles.length){heap.renderInitialized=true;return createRender()}// Try to reuse the markup rendered during SSR.
11
15
  const node=document.querySelector(`[data-chunk-name=${chunkName}]`);if(node){return/*#__PURE__*/(0,_jsxRuntime.jsx)("div",{/* eslint-disable react/no-danger */dangerouslySetInnerHTML:{__html:node.innerHTML||""}/* eslint-disable react/no-danger */,"data-chunk-name":chunkName})}// Else render placeholder, or empty div.
12
16
  const Scene=placeholder||(()=>null);return/*#__PURE__*/(0,_jsxRuntime.jsx)("div",{children:/*#__PURE__*/(0,_jsxRuntime.jsx)(Scene,{...rest,children:children})})});// At this point, if we have data, the absense of heap.renderInitialized flag
13
17
  // means we have to await styles loading; once it is done, and if we are still
14
18
  // mounted, we can set the final render.
15
- if(data&&!heap.renderInitialized){heap.renderInitialized=true;Promise.all(heap.pendingStyles).then(()=>{if(heap.stylesInitialized)setRender(createRender())})}// This effectively fires only once, just before the component unmounts.
16
- (0,_react.useEffect)(()=>()=>{heap.stylesInitialized=false;window.CHUNK_GROUPS[chunkName].forEach(item=>{if(!item.endsWith(".css"))return;const path=`${publicPath}/${item}`;const link=document.querySelector(`link[href="${path}"]`);link.dependants.delete(chunkName);if(!link.dependants.size){const head=document.querySelector("head");head.removeChild(link)}})},[chunkName,heap,publicPath]);return render}
19
+ if(data&&!heap.renderInitialized){heap.renderInitialized=true;Promise.all(heap.pendingStyles).then(()=>{if(heap.mounted)setRender(createRender())})}// This effectively fires only once, just before the component unmounts.
20
+ (0,_react.useEffect)(()=>()=>{heap.mounted=false;window.CHUNK_GROUPS[chunkName].forEach(item=>{if(!item.endsWith(".css"))return;const path=`${publicPath}/${item}`;const link=document.querySelector(`link[href="${path}"]`);link.dependants.delete(chunkName);if(!link.dependants.size){const head=document.querySelector("head");head.removeChild(link)}})},[chunkName,heap,publicPath]);return render}
17
21
  //# sourceMappingURL=ClientSide.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/shared/components/CodeSplit/ClientSide.jsx"],"names":["ClientSide","chunkName","children","getClientSide","placeholder","serverSide","rest","current","heap","pendingStyles","renderInitialized","stylesInitialized","publicPath","window","CHUNK_GROUPS","forEach","asset","endsWith","path","link","document","querySelector","createElement","setAttribute","barrier","onload","resolve","push","head","appendChild","dependants","Set","add","data","maxage","time","YEAR_MS","createRender","Scene","default","render","setRender","length","node","__html","innerHTML","Promise","all","then","item","delete","size","removeChild"],"mappings":"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","sourcesContent":["/**\n * Client-side implementation of a split code chunk.\n */\n/* global document, window */\n/* eslint-disable react/jsx-props-no-spreading */\n\nimport { useEffect, useRef, useState } from 'react';\n\nimport { useAsyncData } from '@dr.pogodin/react-global-state';\n\nimport { newBarrier } from 'utils/Barrier';\nimport { getBuildInfo } from 'utils/isomorphy';\nimport time from 'utils/time';\n\nexport default function ClientSide({\n chunkName,\n children,\n getClientSide,\n placeholder,\n\n // Not used in <ClientSide>, but should not go into \"...rest\" either.\n serverSide,\n\n ...rest\n}) {\n const { current: heap } = useRef({\n pendingStyles: [],\n renderInitialized: false,\n stylesInitialized: false,\n });\n\n // publicPath from buildInfo does not have a trailing slash at the end.\n const { publicPath } = getBuildInfo();\n\n // This code block initiates style loading as soon as possible; it collects\n // into heap.pendingStyles all style load promises; and heap.stylesInitialized\n // flag remains set until the styles are teared down upon unmounting.\n if (!heap.stylesInitialized) {\n heap.stylesInitialized = true;\n window.CHUNK_GROUPS[chunkName].forEach((asset) => {\n if (!asset.endsWith('.css')) return;\n const path = `${publicPath}/${asset}`;\n let link = document.querySelector(`link[href=\"${path}\"]`);\n if (!link) {\n link = document.createElement('link');\n link.setAttribute('href', path);\n link.setAttribute('rel', 'stylesheet');\n\n const barrier = newBarrier();\n link.onload = barrier.resolve;\n heap.pendingStyles.push(barrier);\n\n const head = document.querySelector('head');\n head.appendChild(link);\n }\n if (!link.dependants) link.dependants = new Set([chunkName]);\n else link.dependants.add(chunkName);\n });\n }\n\n // Async loading of React component necessary to render the chunk.\n const { data } = useAsyncData(\n `dr_pogodin_react_utils___split_components.${chunkName}`,\n getClientSide,\n { maxage: time.YEAR_MS },\n );\n\n const createRender = () => {\n const Scene = data.default || data;\n return (\n <div data-chunk-name={chunkName}>\n <Scene {...rest}>\n {children}\n </Scene>\n </div>\n );\n };\n\n const [render, setRender] = useState(() => {\n // No need to await anything, we can render the final component right away.\n if (data && !heap.pendingStyles.length) {\n heap.renderInitialized = true;\n return createRender();\n }\n\n // Try to reuse the markup rendered during SSR.\n const node = document.querySelector(`[data-chunk-name=${chunkName}]`);\n if (node) {\n return (\n <div\n /* eslint-disable react/no-danger */\n dangerouslySetInnerHTML={{ __html: node.innerHTML || '' }}\n /* eslint-disable react/no-danger */\n data-chunk-name={chunkName}\n />\n );\n }\n\n // Else render placeholder, or empty div.\n const Scene = placeholder || (() => null);\n return <div><Scene {...rest}>{children}</Scene></div>;\n });\n\n // At this point, if we have data, the absense of heap.renderInitialized flag\n // means we have to await styles loading; once it is done, and if we are still\n // mounted, we can set the final render.\n if (data && !heap.renderInitialized) {\n heap.renderInitialized = true;\n Promise.all(heap.pendingStyles).then(() => {\n if (heap.stylesInitialized) setRender(createRender());\n });\n }\n\n // This effectively fires only once, just before the component unmounts.\n useEffect(() => () => {\n heap.stylesInitialized = false;\n window.CHUNK_GROUPS[chunkName].forEach((item) => {\n if (!item.endsWith('.css')) return;\n const path = `${publicPath}/${item}`;\n const link = document.querySelector(`link[href=\"${path}\"]`);\n link.dependants.delete(chunkName);\n if (!link.dependants.size) {\n const head = document.querySelector('head');\n head.removeChild(link);\n }\n });\n }, [chunkName, heap, publicPath]);\n\n return render;\n}\n"],"file":"ClientSide.js"}
1
+ {"version":3,"sources":["../../../../../src/shared/components/CodeSplit/ClientSide.jsx"],"names":["ClientSide","chunkName","children","getClientSide","placeholder","serverSide","rest","current","heap","mounted","pendingStyles","renderInitialized","publicPath","window","CHUNK_GROUPS","forEach","asset","endsWith","path","link","document","querySelector","createElement","setAttribute","barrier","onload","resolve","onerror","push","head","appendChild","dependants","Set","add","data","maxage","time","YEAR_MS","createRender","Scene","default","render","setRender","length","node","__html","innerHTML","Promise","all","then","item","delete","size","removeChild"],"mappings":"oLAMA,4BAEA,gEAEA,4CACA,gDACA,8D,6CAZA;AACA;AACA,G,CACA,6B,CACA,iDAUe,QAASA,CAAAA,UAAT,CAAoB,CACjCC,SADiC,CAEjCC,QAFiC,CAGjCC,aAHiC,CAIjCC,WAJiC,CAMjC;AACAC,UAPiC,CASjC,GAAGC,IAT8B,CAApB,CAUZ,CACD,KAAM,CAAEC,OAAO,CAAEC,IAAX,EAAoB,kBAAO,CAC/BC,OAAO,CAAE,KADsB,CAE/BC,aAAa,CAAE,EAFgB,CAG/BC,iBAAiB,CAAE,KAHY,CAAP,CAA1B,CAMA;AACA,KAAM,CAAEC,UAAF,EAAiB,6BAAvB,CAEA;AACA;AACA;AACA;AACA;AACA,GAAI,CAACJ,IAAI,CAACC,OAAV,CAAmB,CACjBD,IAAI,CAACC,OAAL,CAAe,IAAf,CACAI,MAAM,CAACC,YAAP,CAAoBb,SAApB,EAA+Bc,OAA/B,CAAwCC,KAAD,EAAW,CAChD,GAAI,CAACA,KAAK,CAACC,QAAN,CAAe,MAAf,CAAL,CAA6B,OAC7B,KAAMC,CAAAA,IAAI,CAAI,GAAEN,UAAW,IAAGI,KAAM,EAApC,CACA,GAAIG,CAAAA,IAAI,CAAGC,QAAQ,CAACC,aAAT,CAAwB,cAAaH,IAAK,IAA1C,CAAX,CACA,GAAI,CAACC,IAAL,CAAW,CACTA,IAAI,CAAGC,QAAQ,CAACE,aAAT,CAAuB,MAAvB,CAAP,CACAH,IAAI,CAACI,YAAL,CAAkB,MAAlB,CAA0BL,IAA1B,EACAC,IAAI,CAACI,YAAL,CAAkB,KAAlB,CAAyB,YAAzB,EAEA,KAAMC,CAAAA,OAAO,CAAG,yBAAhB,CACAL,IAAI,CAACM,MAAL,CAAcD,OAAO,CAACE,OAAtB,CAEA;AACA;AACAP,IAAI,CAACQ,OAAL,CAAeH,OAAO,CAACE,OAAvB,CAEAlB,IAAI,CAACE,aAAL,CAAmBkB,IAAnB,CAAwBJ,OAAxB,EAEA,KAAMK,CAAAA,IAAI,CAAGT,QAAQ,CAACC,aAAT,CAAuB,MAAvB,CAAb,CACAQ,IAAI,CAACC,WAAL,CAAiBX,IAAjB,CACD,CACD,GAAI,CAACA,IAAI,CAACY,UAAV,CAAsBZ,IAAI,CAACY,UAAL,CAAkB,GAAIC,CAAAA,GAAJ,CAAQ,CAAC/B,SAAD,CAAR,CAAlB,CAAtB,IACKkB,CAAAA,IAAI,CAACY,UAAL,CAAgBE,GAAhB,CAAoBhC,SAApB,CACN,CAvBD,CAwBD,CAED;AACA,KAAM,CAAEiC,IAAF,EAAW,mCACd,6CAA4CjC,SAAU,EADxC,CAEfE,aAFe,CAGf,CAAEgC,MAAM,CAAEC,cAAKC,OAAf,CAHe,CAAjB,CAMA,KAAMC,CAAAA,YAAY,CAAG,IAAM,CACzB,KAAMC,CAAAA,KAAK,CAAGL,IAAI,CAACM,OAAL,EAAgBN,IAA9B,CACA,mBACE,2BAAK,kBAAiBjC,SAAtB,uBACE,oBAAC,KAAD,KAAWK,IAAX,UACGJ,QADH,EADF,EAMH,CATD,CAWA,KAAM,CAACuC,MAAD,CAASC,SAAT,EAAsB,oBAAS,IAAM,CACzC;AACA,GAAIR,IAAI,EAAI,CAAC1B,IAAI,CAACE,aAAL,CAAmBiC,MAAhC,CAAwC,CACtCnC,IAAI,CAACG,iBAAL,CAAyB,IAAzB,CACA,MAAO2B,CAAAA,YAAY,EACpB,CAED;AACA,KAAMM,CAAAA,IAAI,CAAGxB,QAAQ,CAACC,aAAT,CAAwB,oBAAmBpB,SAAU,GAArD,CAAb,CACA,GAAI2C,IAAJ,CAAU,CACR,mBACE,2BACE,oCACA,uBAAuB,CAAE,CAAEC,MAAM,CAAED,IAAI,CAACE,SAAL,EAAkB,EAA5B,CACzB,oCAHF,CAIE,kBAAiB7C,SAJnB,EAOH,CAED;AACA,KAAMsC,CAAAA,KAAK,CAAGnC,WAAW,GAAK,IAAM,IAAX,CAAzB,CACA,mBAAO,iDAAK,oBAAC,KAAD,KAAWE,IAAX,UAAkBJ,QAAlB,EAAL,EACR,CAvB2B,CAA5B,CAyBA;AACA;AACA;AACA,GAAIgC,IAAI,EAAI,CAAC1B,IAAI,CAACG,iBAAlB,CAAqC,CACnCH,IAAI,CAACG,iBAAL,CAAyB,IAAzB,CACAoC,OAAO,CAACC,GAAR,CAAYxC,IAAI,CAACE,aAAjB,EAAgCuC,IAAhC,CAAqC,IAAM,CACzC,GAAIzC,IAAI,CAACC,OAAT,CAAkBiC,SAAS,CAACJ,YAAY,EAAb,CAC5B,CAFD,CAGD,CAED;AACA,qBAAU,IAAM,IAAM,CACpB9B,IAAI,CAACC,OAAL,CAAe,KAAf,CACAI,MAAM,CAACC,YAAP,CAAoBb,SAApB,EAA+Bc,OAA/B,CAAwCmC,IAAD,EAAU,CAC/C,GAAI,CAACA,IAAI,CAACjC,QAAL,CAAc,MAAd,CAAL,CAA4B,OAC5B,KAAMC,CAAAA,IAAI,CAAI,GAAEN,UAAW,IAAGsC,IAAK,EAAnC,CACA,KAAM/B,CAAAA,IAAI,CAAGC,QAAQ,CAACC,aAAT,CAAwB,cAAaH,IAAK,IAA1C,CAAb,CACAC,IAAI,CAACY,UAAL,CAAgBoB,MAAhB,CAAuBlD,SAAvB,EACA,GAAI,CAACkB,IAAI,CAACY,UAAL,CAAgBqB,IAArB,CAA2B,CACzB,KAAMvB,CAAAA,IAAI,CAAGT,QAAQ,CAACC,aAAT,CAAuB,MAAvB,CAAb,CACAQ,IAAI,CAACwB,WAAL,CAAiBlC,IAAjB,CACD,CACF,CATD,CAUD,CAZD,CAYG,CAAClB,SAAD,CAAYO,IAAZ,CAAkBI,UAAlB,CAZH,EAcA,MAAO6B,CAAAA,MACR","sourcesContent":["/**\n * Client-side implementation of a split code chunk.\n */\n/* global document, window */\n/* eslint-disable react/jsx-props-no-spreading */\n\nimport { useEffect, useRef, useState } from 'react';\n\nimport { useAsyncData } from '@dr.pogodin/react-global-state';\n\nimport { newBarrier } from 'utils/Barrier';\nimport { getBuildInfo } from 'utils/isomorphy';\nimport time from 'utils/time';\n\nexport default function ClientSide({\n chunkName,\n children,\n getClientSide,\n placeholder,\n\n // Not used in <ClientSide>, but should not go into \"...rest\" either.\n serverSide,\n\n ...rest\n}) {\n const { current: heap } = useRef({\n mounted: false,\n pendingStyles: [],\n renderInitialized: false,\n });\n\n // publicPath from buildInfo does not have a trailing slash at the end.\n const { publicPath } = getBuildInfo();\n\n // This code block initiates style loading as soon as possible, even prior to\n // the component loading, and it collects all style load / failure promises\n // into heap.pendingStyles array, allowing us to wait and thus avoid flash of\n // unstyled content issue (that's why we don't rely on mini-css-extract-plugin\n // to handle CSS chunk mounting and unmounting, which it is able to do).\n if (!heap.mounted) {\n heap.mounted = true;\n window.CHUNK_GROUPS[chunkName].forEach((asset) => {\n if (!asset.endsWith('.css')) return;\n const path = `${publicPath}/${asset}`;\n let link = document.querySelector(`link[href=\"${path}\"]`);\n if (!link) {\n link = document.createElement('link');\n link.setAttribute('href', path);\n link.setAttribute('rel', 'stylesheet');\n\n const barrier = newBarrier();\n link.onload = barrier.resolve;\n\n // Even if the style load failed, still allow to mount the component,\n // abeit with broken styling.\n link.onerror = barrier.resolve;\n\n heap.pendingStyles.push(barrier);\n\n const head = document.querySelector('head');\n head.appendChild(link);\n }\n if (!link.dependants) link.dependants = new Set([chunkName]);\n else link.dependants.add(chunkName);\n });\n }\n\n // Async loading of React component necessary to render the chunk.\n const { data } = useAsyncData(\n `dr_pogodin_react_utils___split_components.${chunkName}`,\n getClientSide,\n { maxage: time.YEAR_MS },\n );\n\n const createRender = () => {\n const Scene = data.default || data;\n return (\n <div data-chunk-name={chunkName}>\n <Scene {...rest}>\n {children}\n </Scene>\n </div>\n );\n };\n\n const [render, setRender] = useState(() => {\n // No need to await anything, we can render the final component right away.\n if (data && !heap.pendingStyles.length) {\n heap.renderInitialized = true;\n return createRender();\n }\n\n // Try to reuse the markup rendered during SSR.\n const node = document.querySelector(`[data-chunk-name=${chunkName}]`);\n if (node) {\n return (\n <div\n /* eslint-disable react/no-danger */\n dangerouslySetInnerHTML={{ __html: node.innerHTML || '' }}\n /* eslint-disable react/no-danger */\n data-chunk-name={chunkName}\n />\n );\n }\n\n // Else render placeholder, or empty div.\n const Scene = placeholder || (() => null);\n return <div><Scene {...rest}>{children}</Scene></div>;\n });\n\n // At this point, if we have data, the absense of heap.renderInitialized flag\n // means we have to await styles loading; once it is done, and if we are still\n // mounted, we can set the final render.\n if (data && !heap.renderInitialized) {\n heap.renderInitialized = true;\n Promise.all(heap.pendingStyles).then(() => {\n if (heap.mounted) setRender(createRender());\n });\n }\n\n // This effectively fires only once, just before the component unmounts.\n useEffect(() => () => {\n heap.mounted = false;\n window.CHUNK_GROUPS[chunkName].forEach((item) => {\n if (!item.endsWith('.css')) return;\n const path = `${publicPath}/${item}`;\n const link = document.querySelector(`link[href=\"${path}\"]`);\n link.dependants.delete(chunkName);\n if (!link.dependants.size) {\n const head = document.querySelector('head');\n head.removeChild(link);\n }\n });\n }, [chunkName, heap, publicPath]);\n\n return render;\n}\n"],"file":"ClientSide.js"}
@@ -1,5 +1,20 @@
1
1
  "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.default=void 0;var _Barrier=require("./Barrier");/**
2
2
  * Implements a simple semaphore for async code logic.
3
- */class Semaphore{#barrier;#ready;constructor(ready=false){this.#ready=ready}get ready(){return this.#ready}setReady(ready){this.#ready=ready;if(this.#barrier){this.#barrier.resolve();this.#barrier=undefined}}async waitReady(){while(!this.#ready){if(!this.#barrier)this.#barrier=(0,_Barrier.newBarrier)();await this.#barrier;// eslint-disable-line no-await-in-loop
4
- }}}exports.default=Semaphore;
3
+ */class Semaphore{constructor(ready){this.#ready=!!ready}get ready(){return this.#ready}setReady(ready){const bool=!!ready;if(this.#ready!==bool){this.#ready=bool;if(bool&&!this.#draining)this.#drainQueue()}}/**
4
+ * Waits until the semaphore is ready, and marks it as non-ready (seizes it).
5
+ * @return {Promise}
6
+ */async seize(){await this.waitReady();this.setReady(false)}async waitReady(){if(!this.#ready||this.#queue.length){const barrier=(0,_Barrier.newBarrier)();this.#queue.push(barrier);await barrier}}// Private members below this point.
7
+ /**
8
+ * If semaphore is ready, it releases the next barrier in the queue, if any,
9
+ * and reschedules itself for a call in the next event loop iteration.
10
+ * Otherwise, it breaks the queue draining loop, which will be restarted
11
+ * the next time the semaphore is set ready.
12
+ */#drainQueue(){if(this.#ready&&this.#queue.length){const next=this.#queue.shift();next.resolve();// Re-schedules itself for the next event loop iteration.
13
+ if(this.#queue.length){setTimeout(this.#drainQueue.bind(this));this.#draining=true;return;// Exit here to avoid the drain loop termination below.
14
+ }}// Cleans up for the drain loop termination.
15
+ this.#draining=false}// "true" when the drain queue process is running (and thus no need to start
16
+ // a new one).
17
+ #draining=false;// The array of barriers set for each async code flow awaiting for
18
+ // the Semaphore to become ready.
19
+ #queue=[];#ready}exports.default=Semaphore;
5
20
  //# sourceMappingURL=Semaphore.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/shared/utils/Semaphore.js"],"names":["Semaphore","barrier","ready","constructor","setReady","resolve","undefined","waitReady"],"mappings":"6FAAA,kCAEA;AACA;AACA,GACe,KAAMA,CAAAA,SAAU,CAC7B,CAACC,OAAD,CAEA,CAACC,KAAD,CAEAC,WAAW,CAACD,KAAK,CAAG,KAAT,CAAgB,CACzB,KAAK,CAACA,KAAN,CAAcA,KACf,CAEQ,GAALA,CAAAA,KAAK,EAAG,CAAE,MAAO,MAAK,CAACA,KAAQ,CAEnCE,QAAQ,CAACF,KAAD,CAAQ,CACd,KAAK,CAACA,KAAN,CAAcA,KAAd,CACA,GAAI,KAAK,CAACD,OAAV,CAAmB,CACjB,KAAK,CAACA,OAAN,CAAcI,OAAd,GACA,KAAK,CAACJ,OAAN,CAAgBK,SACjB,CACF,CAEc,KAATC,CAAAA,SAAS,EAAG,CAChB,MAAO,CAAC,KAAK,CAACL,KAAd,CAAqB,CACnB,GAAI,CAAC,KAAK,CAACD,OAAX,CAAoB,KAAK,CAACA,OAAN,CAAgB,yBAAhB,CACpB,KAAM,MAAK,CAACA,OAAZ,CAAqB;AACtB,CACF,CAxB4B,C","sourcesContent":["import { newBarrier } from './Barrier';\n\n/**\n * Implements a simple semaphore for async code logic.\n */\nexport default class Semaphore {\n #barrier;\n\n #ready;\n\n constructor(ready = false) {\n this.#ready = ready;\n }\n\n get ready() { return this.#ready; }\n\n setReady(ready) {\n this.#ready = ready;\n if (this.#barrier) {\n this.#barrier.resolve();\n this.#barrier = undefined;\n }\n }\n\n async waitReady() {\n while (!this.#ready) {\n if (!this.#barrier) this.#barrier = newBarrier();\n await this.#barrier; // eslint-disable-line no-await-in-loop\n }\n }\n}\n"],"file":"Semaphore.js"}
1
+ {"version":3,"sources":["../../../../src/shared/utils/Semaphore.js"],"names":["Semaphore","constructor","ready","setReady","bool","draining","drainQueue","seize","waitReady","queue","length","barrier","push","next","shift","resolve","setTimeout","bind"],"mappings":"6FAAA,kCAEA;AACA;AACA,GACe,KAAMA,CAAAA,SAAU,CAC7BC,WAAW,CAACC,KAAD,CAAQ,CACjB,KAAK,CAACA,KAAN,CAAc,CAAC,CAACA,KACjB,CAEQ,GAALA,CAAAA,KAAK,EAAG,CAAE,MAAO,MAAK,CAACA,KAAQ,CAEnCC,QAAQ,CAACD,KAAD,CAAQ,CACd,KAAME,CAAAA,IAAI,CAAG,CAAC,CAACF,KAAf,CACA,GAAI,KAAK,CAACA,KAAN,GAAgBE,IAApB,CAA0B,CACxB,KAAK,CAACF,KAAN,CAAcE,IAAd,CACA,GAAIA,IAAI,EAAI,CAAC,KAAK,CAACC,QAAnB,CAA6B,KAAK,CAACC,UAAN,EAC9B,CACF,CAED;AACF;AACA;AACA,KACa,KAALC,CAAAA,KAAK,EAAG,CACZ,KAAM,MAAKC,SAAL,EAAN,CACA,KAAKL,QAAL,CAAc,KAAd,CACD,CAEc,KAATK,CAAAA,SAAS,EAAG,CAChB,GAAI,CAAC,KAAK,CAACN,KAAP,EAAgB,KAAK,CAACO,KAAN,CAAYC,MAAhC,CAAwC,CACtC,KAAMC,CAAAA,OAAO,CAAG,yBAAhB,CACA,KAAK,CAACF,KAAN,CAAYG,IAAZ,CAAiBD,OAAjB,EACA,KAAMA,CAAAA,OACP,CACF,CAED;AAEA;AACF;AACA;AACA;AACA;AACA,KACE,CAACL,UAAU,EAAG,CACZ,GAAI,KAAK,CAACJ,KAAN,EAAe,KAAK,CAACO,KAAN,CAAYC,MAA/B,CAAuC,CACrC,KAAMG,CAAAA,IAAI,CAAG,KAAK,CAACJ,KAAN,CAAYK,KAAZ,EAAb,CACAD,IAAI,CAACE,OAAL,GAEA;AACA,GAAI,KAAK,CAACN,KAAN,CAAYC,MAAhB,CAAwB,CACtBM,UAAU,CAAC,KAAK,CAACV,UAAN,CAAiBW,IAAjB,CAAsB,IAAtB,CAAD,CAAV,CACA,KAAK,CAACZ,QAAN,CAAiB,IAAjB,CACA,OAAQ;AACT,CACF,CAED;AACA,KAAK,CAACA,QAAN,CAAiB,KAClB,CAED;AACA;AACA,CAACA,QAAD,CAAY,KAAZ,CAEA;AACA;AACA,CAACI,KAAD,CAAS,EAAT,CAEA,CAACP,KAjE4B,C","sourcesContent":["import { newBarrier } from './Barrier';\n\n/**\n * Implements a simple semaphore for async code logic.\n */\nexport default class Semaphore {\n constructor(ready) {\n this.#ready = !!ready;\n }\n\n get ready() { return this.#ready; }\n\n setReady(ready) {\n const bool = !!ready;\n if (this.#ready !== bool) {\n this.#ready = bool;\n if (bool && !this.#draining) this.#drainQueue();\n }\n }\n\n /**\n * Waits until the semaphore is ready, and marks it as non-ready (seizes it).\n * @return {Promise}\n */\n async seize() {\n await this.waitReady();\n this.setReady(false);\n }\n\n async waitReady() {\n if (!this.#ready || this.#queue.length) {\n const barrier = newBarrier();\n this.#queue.push(barrier);\n await barrier;\n }\n }\n\n // Private members below this point.\n\n /**\n * If semaphore is ready, it releases the next barrier in the queue, if any,\n * and reschedules itself for a call in the next event loop iteration.\n * Otherwise, it breaks the queue draining loop, which will be restarted\n * the next time the semaphore is set ready.\n */\n #drainQueue() {\n if (this.#ready && this.#queue.length) {\n const next = this.#queue.shift();\n next.resolve();\n\n // Re-schedules itself for the next event loop iteration.\n if (this.#queue.length) {\n setTimeout(this.#drainQueue.bind(this));\n this.#draining = true;\n return; // Exit here to avoid the drain loop termination below.\n }\n }\n\n // Cleans up for the drain loop termination.\n this.#draining = false;\n }\n\n // \"true\" when the drain queue process is running (and thus no need to start\n // a new one).\n #draining = false;\n\n // The array of barriers set for each async code flow awaiting for\n // the Semaphore to become ready.\n #queue = [];\n\n #ready;\n}\n"],"file":"Semaphore.js"}
@@ -10,5 +10,5 @@
10
10
  * @param {React.ElementType} [options.serverSide]
11
11
  * @returns {React.ElementType}
12
12
  */function splitComponent({chunkName,getClientSide,placeholder,serverSide}){// eslint-disable-next-line react/prop-types
13
- return({children=[],...props})=>/*#__PURE__*/(0,_react.createElement)(_CodeSplit.default,{...props,chunkName,getClientSide,placeholder,serverSide},...children)}
13
+ return({children=[],...props}={})=>/*#__PURE__*/(0,_react.createElement)(_CodeSplit.default,{...props,chunkName,getClientSide,placeholder,serverSide},...children)}
14
14
  //# sourceMappingURL=splitComponent.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/shared/utils/splitComponent.js"],"names":["splitComponent","chunkName","getClientSide","placeholder","serverSide","children","props","CodeSplit"],"mappings":"wLAAA,4BACA,0EAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GACe,QAASA,CAAAA,cAAT,CAAwB,CACrCC,SADqC,CAErCC,aAFqC,CAGrCC,WAHqC,CAIrCC,UAJqC,CAAxB,CAKZ,CACD;AACA,MAAO,CAAC,CAAEC,QAAQ,CAAG,EAAb,CAAiB,GAAGC,KAApB,CAAD,gBAAiC,yBACtCC,kBADsC,CAEtC,CACE,GAAGD,KADL,CAEEL,SAFF,CAGEC,aAHF,CAIEC,WAJF,CAKEC,UALF,CAFsC,CAStC,GAAGC,QATmC,CAWzC","sourcesContent":["import { createElement } from 'react';\nimport CodeSplit from 'components/CodeSplit';\n\n/**\n * Wraps a regular React component into a \"code splitting\" component,\n * i.e. all code used exclusively by that component and its sub-tree\n * will go into a separate, asynchronously loaded, code chunk for\n * the client-side.\n * @param {object} options\n * @param {string} options.chunkName\n * @param {function} options.getClientSide\n * @param {React.ElementType} [options.placeholder]\n * @param {React.ElementType} [options.serverSide]\n * @returns {React.ElementType}\n */\nexport default function splitComponent({\n chunkName,\n getClientSide,\n placeholder,\n serverSide,\n}) {\n // eslint-disable-next-line react/prop-types\n return ({ children = [], ...props }) => createElement(\n CodeSplit,\n {\n ...props,\n chunkName,\n getClientSide,\n placeholder,\n serverSide,\n },\n ...children,\n );\n}\n"],"file":"splitComponent.js"}
1
+ {"version":3,"sources":["../../../../src/shared/utils/splitComponent.js"],"names":["splitComponent","chunkName","getClientSide","placeholder","serverSide","children","props","CodeSplit"],"mappings":"wLAAA,4BACA,0EAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GACe,QAASA,CAAAA,cAAT,CAAwB,CACrCC,SADqC,CAErCC,aAFqC,CAGrCC,WAHqC,CAIrCC,UAJqC,CAAxB,CAKZ,CACD;AACA,MAAO,CAAC,CAAEC,QAAQ,CAAG,EAAb,CAAiB,GAAGC,KAApB,EAA8B,EAA/B,gBAAsC,yBAC3CC,kBAD2C,CAE3C,CACE,GAAGD,KADL,CAEEL,SAFF,CAGEC,aAHF,CAIEC,WAJF,CAKEC,UALF,CAF2C,CAS3C,GAAGC,QATwC,CAW9C","sourcesContent":["import { createElement } from 'react';\nimport CodeSplit from 'components/CodeSplit';\n\n/**\n * Wraps a regular React component into a \"code splitting\" component,\n * i.e. all code used exclusively by that component and its sub-tree\n * will go into a separate, asynchronously loaded, code chunk for\n * the client-side.\n * @param {object} options\n * @param {string} options.chunkName\n * @param {function} options.getClientSide\n * @param {React.ElementType} [options.placeholder]\n * @param {React.ElementType} [options.serverSide]\n * @returns {React.ElementType}\n */\nexport default function splitComponent({\n chunkName,\n getClientSide,\n placeholder,\n serverSide,\n}) {\n // eslint-disable-next-line react/prop-types\n return ({ children = [], ...props } = {}) => createElement(\n CodeSplit,\n {\n ...props,\n chunkName,\n getClientSide,\n placeholder,\n serverSide,\n },\n ...children,\n );\n}\n"],"file":"splitComponent.js"}