navigation-stack 0.3.1 → 0.5.0

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.
Files changed (257) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +611 -163
  3. package/data-storage/package.json +6 -0
  4. package/karma.conf.cjs +21 -4
  5. package/lib/cjs/NavigationStack.js +88 -0
  6. package/lib/cjs/data-storage/DataStorage.js +71 -0
  7. package/lib/cjs/data-storage/LocationDataStorage.js +29 -0
  8. package/lib/cjs/data-storage/index.js +9 -0
  9. package/lib/cjs/debug.js +12 -0
  10. package/lib/cjs/environment/InMemoryEnvironment.js +15 -0
  11. package/lib/cjs/environment/WebBrowserEnvironment.js +15 -0
  12. package/lib/cjs/environment/data-storage/InMemoryDataStorage.js +27 -0
  13. package/lib/cjs/environment/data-storage/WebBrowserDataStorage.js +21 -0
  14. package/lib/cjs/environment/scroll-position/InMemoryScrollPosition.js +44 -0
  15. package/lib/cjs/environment/scroll-position/WebBrowserScrollPosition.js +60 -0
  16. package/lib/cjs/getLocationFromInternalLocation.js +14 -0
  17. package/lib/cjs/index.js +20 -16
  18. package/lib/cjs/navigationBlockers.js +28 -23
  19. package/lib/cjs/{normalizeInputLocation.js → parseInputLocation.js} +25 -9
  20. package/lib/cjs/{ActionTypes.js → redux/ActionTypes.js} +1 -1
  21. package/lib/cjs/redux/ActionTypesInternal.js +8 -0
  22. package/lib/cjs/{Actions.js → redux/Actions.js} +5 -4
  23. package/lib/cjs/redux/createMiddlewares.js +60 -0
  24. package/lib/cjs/redux/index.js +13 -0
  25. package/lib/cjs/redux/internalLocationReducer.js +14 -0
  26. package/lib/cjs/redux/middleware/createAddInputLocationBasePathMiddleware.js +32 -0
  27. package/lib/cjs/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.js +113 -0
  28. package/lib/cjs/redux/middleware/createProgrammaticNavigationBlockerMiddleware.js +94 -0
  29. package/lib/cjs/redux/middleware/createRemoveOutputLocationBasePathMiddleware.js +30 -0
  30. package/lib/cjs/redux/middleware/createUpdateInternalLocationMiddleware.js +73 -0
  31. package/lib/cjs/{middleware/navigationActionMiddleware.js → redux/middleware/navigationOperationMiddleware.js} +11 -8
  32. package/lib/cjs/{middleware/normalizeInputLocationMiddleware.js → redux/middleware/parseInputLocationMiddleware.js} +6 -4
  33. package/lib/cjs/redux/middleware/updateLocationMiddleware.js +34 -0
  34. package/lib/cjs/scroll-position/PageScrollPositionSetter.js +97 -0
  35. package/lib/cjs/scroll-position/ScrollPositionAutoSaver.js +141 -0
  36. package/lib/cjs/scroll-position/ScrollPositionRestoration.js +407 -0
  37. package/lib/cjs/scroll-position/ScrollPositionSaver.js +87 -0
  38. package/lib/cjs/scroll-position/ScrollPositionSetter.js +16 -0
  39. package/lib/cjs/scroll-position/constants.js +5 -0
  40. package/lib/cjs/scroll-position/index.js +7 -0
  41. package/lib/cjs/scroll-position/scheduleNextTick.js +11 -0
  42. package/lib/cjs/session/InMemorySession.js +22 -0
  43. package/lib/cjs/session/ServerSideRenderSession.js +17 -0
  44. package/lib/cjs/session/Session.js +202 -0
  45. package/lib/cjs/session/WebBrowserSession.js +20 -0
  46. package/lib/cjs/session/key/createSessionKey.js +23 -0
  47. package/lib/cjs/session/lifecycle/InMemorySessionLifecycle.js +19 -0
  48. package/lib/cjs/session/lifecycle/WebBrowserSessionLifecycle.js +128 -0
  49. package/lib/cjs/session/lifecycle/page-lifecycle/PageLifecycle.js +269 -0
  50. package/lib/cjs/session/lifecycle/page-lifecycle/PageLifecycleInstance.js +8 -0
  51. package/lib/cjs/session/lifecycle/page-lifecycle/supportsConstructableEventTarget.js +33 -0
  52. package/lib/cjs/session/navigation/InMemoryNavigation.js +104 -0
  53. package/lib/cjs/session/navigation/ServerSideNavigation.js +61 -0
  54. package/lib/cjs/session/navigation/WebBrowserNavigation.js +221 -0
  55. package/lib/cjs/session/navigation/error/NavigationOutOfBoundsError.js +12 -0
  56. package/lib/cjs/session/navigation/error/ServerSideNavigationError.js +21 -0
  57. package/lib/cjs/session/navigation/operation/operations.js +11 -0
  58. package/lib/cjs/session/subscription/Subscription.js +81 -0
  59. package/lib/data-storage/index.d.ts +35 -0
  60. package/lib/esm/NavigationStack.js +81 -0
  61. package/lib/esm/data-storage/DataStorage.js +65 -0
  62. package/lib/esm/data-storage/LocationDataStorage.js +22 -0
  63. package/lib/esm/data-storage/index.js +2 -0
  64. package/lib/esm/debug.js +7 -0
  65. package/lib/esm/environment/InMemoryEnvironment.js +8 -0
  66. package/lib/esm/environment/WebBrowserEnvironment.js +8 -0
  67. package/lib/esm/environment/data-storage/InMemoryDataStorage.js +21 -0
  68. package/lib/esm/environment/data-storage/WebBrowserDataStorage.js +15 -0
  69. package/lib/esm/environment/scroll-position/InMemoryScrollPosition.js +38 -0
  70. package/lib/esm/environment/scroll-position/WebBrowserScrollPosition.js +54 -0
  71. package/lib/esm/getLocationFromInternalLocation.js +9 -0
  72. package/lib/esm/index.js +10 -8
  73. package/lib/esm/navigationBlockers.js +28 -23
  74. package/lib/esm/{normalizeInputLocation.js → parseInputLocation.js} +24 -8
  75. package/lib/esm/{ActionTypes.js → redux/ActionTypes.js} +1 -1
  76. package/lib/esm/redux/ActionTypesInternal.js +3 -0
  77. package/lib/esm/{Actions.js → redux/Actions.js} +5 -4
  78. package/lib/esm/redux/createMiddlewares.js +54 -0
  79. package/lib/esm/redux/index.js +4 -0
  80. package/lib/esm/redux/internalLocationReducer.js +8 -0
  81. package/lib/esm/redux/middleware/createAddInputLocationBasePathMiddleware.js +27 -0
  82. package/lib/esm/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.js +108 -0
  83. package/lib/esm/redux/middleware/createProgrammaticNavigationBlockerMiddleware.js +88 -0
  84. package/lib/esm/redux/middleware/createRemoveOutputLocationBasePathMiddleware.js +25 -0
  85. package/lib/esm/redux/middleware/createUpdateInternalLocationMiddleware.js +68 -0
  86. package/lib/esm/{middleware/navigationActionMiddleware.js → redux/middleware/navigationOperationMiddleware.js} +10 -7
  87. package/lib/esm/{middleware/normalizeInputLocationMiddleware.js → redux/middleware/parseInputLocationMiddleware.js} +5 -3
  88. package/lib/esm/redux/middleware/updateLocationMiddleware.js +28 -0
  89. package/lib/esm/scroll-position/PageScrollPositionSetter.js +91 -0
  90. package/lib/esm/scroll-position/ScrollPositionAutoSaver.js +134 -0
  91. package/lib/esm/scroll-position/ScrollPositionRestoration.js +400 -0
  92. package/lib/esm/scroll-position/ScrollPositionSaver.js +80 -0
  93. package/lib/esm/scroll-position/ScrollPositionSetter.js +10 -0
  94. package/lib/esm/scroll-position/constants.js +1 -0
  95. package/lib/esm/scroll-position/index.js +1 -0
  96. package/lib/esm/scroll-position/scheduleNextTick.js +6 -0
  97. package/lib/esm/session/InMemorySession.js +15 -0
  98. package/lib/esm/session/ServerSideRenderSession.js +11 -0
  99. package/lib/esm/session/Session.js +195 -0
  100. package/lib/esm/session/WebBrowserSession.js +13 -0
  101. package/lib/esm/session/key/createSessionKey.js +18 -0
  102. package/lib/esm/session/lifecycle/InMemorySessionLifecycle.js +13 -0
  103. package/lib/esm/session/lifecycle/WebBrowserSessionLifecycle.js +120 -0
  104. package/lib/esm/session/lifecycle/page-lifecycle/PageLifecycle.js +263 -0
  105. package/lib/esm/session/lifecycle/page-lifecycle/PageLifecycleInstance.js +2 -0
  106. package/lib/esm/session/lifecycle/page-lifecycle/supportsConstructableEventTarget.js +30 -0
  107. package/lib/esm/session/navigation/InMemoryNavigation.js +97 -0
  108. package/lib/esm/session/navigation/ServerSideNavigation.js +54 -0
  109. package/lib/esm/session/navigation/WebBrowserNavigation.js +213 -0
  110. package/lib/esm/session/navigation/error/NavigationOutOfBoundsError.js +6 -0
  111. package/lib/esm/session/navigation/error/ServerSideNavigationError.js +14 -0
  112. package/lib/esm/session/navigation/operation/operations.js +6 -0
  113. package/lib/esm/session/subscription/Subscription.js +75 -0
  114. package/lib/index.d.ts +179 -157
  115. package/lib/redux/index.d.ts +90 -0
  116. package/lib/scroll-position/index.d.ts +107 -0
  117. package/package.json +9 -5
  118. package/redux/package.json +6 -0
  119. package/scroll-position/package.json +6 -0
  120. package/src/NavigationStack.js +100 -0
  121. package/src/data-storage/DataStorage.js +69 -0
  122. package/src/data-storage/LocationDataStorage.js +23 -0
  123. package/src/data-storage/index.js +2 -0
  124. package/src/debug.js +8 -0
  125. package/src/environment/InMemoryEnvironment.js +9 -0
  126. package/src/environment/WebBrowserEnvironment.js +9 -0
  127. package/src/environment/data-storage/InMemoryDataStorage.js +23 -0
  128. package/src/environment/data-storage/WebBrowserDataStorage.js +17 -0
  129. package/src/environment/scroll-position/InMemoryScrollPosition.js +45 -0
  130. package/src/environment/scroll-position/WebBrowserScrollPosition.js +72 -0
  131. package/src/getLocationFromInternalLocation.js +7 -0
  132. package/src/index.js +10 -8
  133. package/src/navigationBlockers.js +31 -27
  134. package/src/{normalizeInputLocation.js → parseInputLocation.js} +23 -8
  135. package/src/{ActionTypes.js → redux/ActionTypes.js} +1 -1
  136. package/src/redux/ActionTypesInternal.js +3 -0
  137. package/src/{Actions.js → redux/Actions.js} +4 -3
  138. package/src/redux/createMiddlewares.js +65 -0
  139. package/src/redux/index.js +4 -0
  140. package/src/redux/internalLocationReducer.js +9 -0
  141. package/src/redux/middleware/createAddInputLocationBasePathMiddleware.js +27 -0
  142. package/src/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.js +119 -0
  143. package/src/redux/middleware/createProgrammaticNavigationBlockerMiddleware.js +94 -0
  144. package/src/redux/middleware/createRemoveOutputLocationBasePathMiddleware.js +26 -0
  145. package/src/redux/middleware/createUpdateInternalLocationMiddleware.js +72 -0
  146. package/src/{middleware/navigationActionMiddleware.js → redux/middleware/navigationOperationMiddleware.js} +10 -3
  147. package/src/{middleware/normalizeInputLocationMiddleware.js → redux/middleware/parseInputLocationMiddleware.js} +5 -3
  148. package/src/redux/middleware/updateLocationMiddleware.js +28 -0
  149. package/src/scroll-position/PageScrollPositionSetter.js +110 -0
  150. package/src/scroll-position/ScrollPositionAutoSaver.js +168 -0
  151. package/src/scroll-position/ScrollPositionRestoration.js +551 -0
  152. package/src/scroll-position/ScrollPositionSaver.js +120 -0
  153. package/src/scroll-position/ScrollPositionSetter.js +16 -0
  154. package/src/scroll-position/constants.js +1 -0
  155. package/src/scroll-position/index.js +1 -0
  156. package/src/scroll-position/scheduleNextTick.js +6 -0
  157. package/src/session/InMemorySession.js +13 -0
  158. package/src/session/ServerSideRenderSession.js +9 -0
  159. package/src/session/Session.js +238 -0
  160. package/src/session/WebBrowserSession.js +13 -0
  161. package/src/session/key/createSessionKey.js +18 -0
  162. package/src/session/lifecycle/InMemorySessionLifecycle.js +13 -0
  163. package/src/session/lifecycle/WebBrowserSessionLifecycle.js +126 -0
  164. package/src/session/lifecycle/page-lifecycle/PageLifecycle.js +291 -0
  165. package/src/session/lifecycle/page-lifecycle/PageLifecycleInstance.js +3 -0
  166. package/src/session/lifecycle/page-lifecycle/supportsConstructableEventTarget.js +32 -0
  167. package/src/session/navigation/InMemoryNavigation.js +78 -0
  168. package/src/session/navigation/ServerSideNavigation.js +43 -0
  169. package/src/session/navigation/WebBrowserNavigation.js +224 -0
  170. package/src/session/navigation/error/NavigationOutOfBoundsError.js +7 -0
  171. package/src/session/navigation/error/ServerSideNavigationError.js +18 -0
  172. package/src/session/navigation/operation/operations.js +6 -0
  173. package/src/session/subscription/Subscription.js +76 -0
  174. package/test/NavigationStack.test.js +296 -0
  175. package/test/{LocationDataStorage.test.js → data-storage/LocationDataStorage.test.js} +3 -3
  176. package/test/data-storage/index.test.js +8 -0
  177. package/test/index.js +12 -0
  178. package/test/index.test.js +8 -7
  179. package/test/{helpers.js → middlewareTestUtil.js} +9 -12
  180. package/test/{normalizeInputLocation.test.js → parseInputLocationMiddleware.test.js} +9 -9
  181. package/test/{Action.test.js → redux/Action.test.js} +7 -6
  182. package/test/{ActionTypes.test.js → redux/ActionTypes.test.js} +2 -2
  183. package/test/redux/createMiddlewares.test.js +96 -0
  184. package/test/redux/index.test.js +10 -0
  185. package/test/{locationReducer.test.js → redux/locationReducer.test.js} +4 -7
  186. package/test/redux/middleware/createAddInputLocationBasePathMiddleware.test.js +40 -0
  187. package/test/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.test.js +264 -0
  188. package/test/redux/middleware/createProgrammaticNavigationBlockerMiddleware.test.js +312 -0
  189. package/test/redux/middleware/createRemoveOutputLocationBasePathMiddleware.test.js +51 -0
  190. package/test/{middleware/navigationActionMiddleware.test.js → redux/middleware/navigationOperationMiddleware.test.js} +16 -12
  191. package/test/{middleware/normalizeInputLocationMiddleware.test.js → redux/middleware/parseInputLocationMiddleware.test.js} +4 -4
  192. package/test/scroll-position/ScrollPositionRestoration.test.js +435 -0
  193. package/test/scroll-position/addScrollableContainer.js +39 -0
  194. package/test/scroll-position/addScrollableContainerWithAnchors.js +56 -0
  195. package/test/scroll-position/createApp.js +132 -0
  196. package/test/scroll-position/delay.js +9 -0
  197. package/test/scroll-position/mockPageLifecycle.js +17 -0
  198. package/test/scroll-position/runApp.js +24 -0
  199. package/test/scroll-position/withScrollableContainerAtIndexPageWithDisabledAutomaticScrollPositionRestoration.js +72 -0
  200. package/test/session/InMemorySession.test.js +348 -0
  201. package/test/session/ServerSession.test.js +17 -9
  202. package/test/session/WebBrowserSession.test.js +265 -0
  203. package/test/testUtil.js +3 -0
  204. package/types/data-storage/index.d.ts +35 -0
  205. package/types/index.d.ts +179 -157
  206. package/types/redux/index.d.ts +90 -0
  207. package/types/scroll-position/index.d.ts +107 -0
  208. package/types/tsconfig.json +1 -1
  209. package/lib/cjs/LocationDataStorage.js +0 -61
  210. package/lib/cjs/addBeforeLocationChangeListener.js +0 -7
  211. package/lib/cjs/beforeLocationChangeListeners.js +0 -51
  212. package/lib/cjs/createMiddlewares.js +0 -47
  213. package/lib/cjs/middleware/createBasePathMiddleware.js +0 -24
  214. package/lib/cjs/middleware/createBeforeLocationChangeListenerMiddleware.js +0 -39
  215. package/lib/cjs/middleware/createLocationMiddleware.js +0 -56
  216. package/lib/cjs/middleware/createNavigationBlockerMiddleware.js +0 -161
  217. package/lib/cjs/middleware/createTransformLocationMiddleware.js +0 -38
  218. package/lib/cjs/onlyAllowedOnClientSide.js +0 -10
  219. package/lib/cjs/session/BrowserSession.js +0 -235
  220. package/lib/cjs/session/MemorySession.js +0 -223
  221. package/lib/cjs/session/ServerSession.js +0 -65
  222. package/lib/esm/LocationDataStorage.js +0 -54
  223. package/lib/esm/addBeforeLocationChangeListener.js +0 -2
  224. package/lib/esm/beforeLocationChangeListeners.js +0 -44
  225. package/lib/esm/createMiddlewares.js +0 -41
  226. package/lib/esm/middleware/createBasePathMiddleware.js +0 -19
  227. package/lib/esm/middleware/createBeforeLocationChangeListenerMiddleware.js +0 -34
  228. package/lib/esm/middleware/createLocationMiddleware.js +0 -50
  229. package/lib/esm/middleware/createNavigationBlockerMiddleware.js +0 -156
  230. package/lib/esm/middleware/createTransformLocationMiddleware.js +0 -33
  231. package/lib/esm/onlyAllowedOnClientSide.js +0 -5
  232. package/lib/esm/session/BrowserSession.js +0 -229
  233. package/lib/esm/session/MemorySession.js +0 -217
  234. package/lib/esm/session/ServerSession.js +0 -58
  235. package/src/LocationDataStorage.js +0 -60
  236. package/src/addBeforeLocationChangeListener.js +0 -2
  237. package/src/beforeLocationChangeListeners.js +0 -54
  238. package/src/createMiddlewares.js +0 -45
  239. package/src/middleware/createBasePathMiddleware.js +0 -20
  240. package/src/middleware/createBeforeLocationChangeListenerMiddleware.js +0 -40
  241. package/src/middleware/createLocationMiddleware.js +0 -55
  242. package/src/middleware/createNavigationBlockerMiddleware.js +0 -168
  243. package/src/middleware/createTransformLocationMiddleware.js +0 -29
  244. package/src/onlyAllowedOnClientSide.js +0 -5
  245. package/src/session/BrowserSession.js +0 -235
  246. package/src/session/MemorySession.js +0 -219
  247. package/src/session/ServerSession.js +0 -67
  248. package/test/createMiddlewares.test.js +0 -62
  249. package/test/middleware/createBasePathMiddleware.test.js +0 -67
  250. package/test/middleware/createBeforeLocationChangeListenerMiddleware.test.js +0 -141
  251. package/test/middleware/createNavigationBlockerMiddleware.test.js +0 -471
  252. package/test/middleware/createTransformLocationMiddleware.test.js +0 -44
  253. package/test/session/BrowserSession.test.js +0 -182
  254. package/test/session/MemorySession.test.js +0 -244
  255. /package/lib/cjs/{locationReducer.js → redux/locationReducer.js} +0 -0
  256. /package/lib/esm/{locationReducer.js → redux/locationReducer.js} +0 -0
  257. /package/src/{locationReducer.js → redux/locationReducer.js} +0 -0
@@ -0,0 +1,6 @@
1
+ {
2
+ "private": true,
3
+ "name": "navigation-stack/data-storage",
4
+ "main": "./../lib/cjs/data-storage/index.js",
5
+ "module": "./../lib/esm/data-storage/index.js"
6
+ }
package/karma.conf.cjs CHANGED
@@ -14,7 +14,7 @@ module.exports = (config) => {
14
14
  const { env } = process;
15
15
 
16
16
  config.set({
17
- frameworks: ['mocha', 'webpack', 'sinon-chai'],
17
+ frameworks: ['webpack', 'mocha', 'sinon-chai'],
18
18
 
19
19
  files: ['test/index.js', { pattern: 'test/**/*.test.js', watched: false }],
20
20
 
@@ -26,16 +26,32 @@ module.exports = (config) => {
26
26
  mode: 'development',
27
27
  module: {
28
28
  rules: [
29
- { test: /\.js$/, exclude: /node_modules/, use: 'babel-loader' },
29
+ {
30
+ test: /\.js$/,
31
+ exclude: /node_modules/,
32
+ use: {
33
+ loader: 'babel-loader',
34
+ },
35
+ },
30
36
  ],
31
37
  },
32
38
  plugins: [
33
39
  new webpack.DefinePlugin({
34
40
  __DEV__: true,
35
41
  }),
42
+ new webpack.ProvidePlugin({
43
+ process: 'process/browser',
44
+ }),
36
45
  ],
37
46
  },
38
47
 
48
+ resolve: {
49
+ fallback: {
50
+ process: require.resolve('process/browser'),
51
+ util: require.resolve('util/'),
52
+ },
53
+ },
54
+
39
55
  webpackMiddleware: {
40
56
  noInfo: true,
41
57
  },
@@ -53,11 +69,12 @@ module.exports = (config) => {
53
69
 
54
70
  customLaunchers: {
55
71
  ChromeCi: {
56
- base: 'ChromeHeadless',
72
+ // base: 'ChromeHeadless',
73
+ base: 'Chrome',
57
74
  flags: ['--no-sandbox'],
58
75
  },
59
76
  },
60
77
 
61
- browsers: env.BROWSER ? env.BROWSER.split(',') : ['Chrome'],
78
+ browsers: env.BROWSER ? env.BROWSER.split(',') : ['Chrome', 'Firefox'],
62
79
  });
63
80
  };
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+ var _redux = require("redux");
6
+ var _Actions = _interopRequireDefault(require("./redux/Actions"));
7
+ var _createMiddlewares = _interopRequireDefault(require("./redux/createMiddlewares"));
8
+ var _locationReducer = _interopRequireDefault(require("./redux/locationReducer"));
9
+ var _ScrollPositionRestoration = _interopRequireDefault(require("./scroll-position/ScrollPositionRestoration"));
10
+ const _excluded = ["maintainScrollPosition"];
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
13
+ function getCreateMiddlewaresOptions(navigationStackOptions) {
14
+ if (!navigationStackOptions) {
15
+ return undefined;
16
+ }
17
+ // eslint-disable-next-line no-unused-vars
18
+ const restOptions = _objectWithoutPropertiesLoose(navigationStackOptions, _excluded);
19
+ return restOptions;
20
+ }
21
+ class NavigationStack {
22
+ constructor(session, options) {
23
+ this._session = session;
24
+
25
+ // Create a Redux store.
26
+ this._store = (0, _redux.createStore)(_locationReducer.default, (0, _redux.applyMiddleware)(...(0, _createMiddlewares.default)(session, getCreateMiddlewaresOptions(options))));
27
+
28
+ // Create `ScrollPositionRestoration`.
29
+ if (options && options.maintainScrollPosition) {
30
+ this._scrollPositionRestoration = new _ScrollPositionRestoration.default(session);
31
+ }
32
+ }
33
+ addScrollableContainer(scrollableContainerKey, scrollableContainer) {
34
+ if (!this._scrollPositionRestoration) {
35
+ throw new Error('`maintainScrollPosition: true` option not passed');
36
+ }
37
+ return this._scrollPositionRestoration.addScrollableContainer(scrollableContainerKey, scrollableContainer);
38
+ }
39
+ subscribe(listener) {
40
+ // Subscribe to any potential Redux state changes.
41
+ return this._store.subscribe(() => {
42
+ // Initially, calls the listener when setting the initial location.
43
+ // After that, calls it on any location change.
44
+ const location = this.current();
45
+ if (!this._latestLocation || location !== this._latestLocation) {
46
+ this._latestLocation = location;
47
+ listener(location);
48
+ }
49
+ });
50
+ }
51
+ init(initialLocation) {
52
+ if (this._latestLocation) {
53
+ throw new Error('Already initialized');
54
+ }
55
+ this._store.dispatch(_Actions.default.init(initialLocation));
56
+ this._latestLocation = this.current();
57
+ }
58
+ current() {
59
+ return this._store.getState();
60
+ }
61
+ push(location) {
62
+ this._store.dispatch(_Actions.default.push(location));
63
+ }
64
+ replace(location) {
65
+ this._store.dispatch(_Actions.default.replace(location));
66
+ }
67
+ shift(delta) {
68
+ this._store.dispatch(_Actions.default.shift(delta));
69
+ }
70
+ stop() {
71
+ if (this._scrollPositionRestoration) {
72
+ this._scrollPositionRestoration.stop();
73
+ }
74
+ this._store.dispatch(_Actions.default.stop());
75
+ }
76
+ locationRendered() {
77
+ if (this._scrollPositionRestoration) {
78
+ const location = this.current();
79
+ if (!location) {
80
+ throw new Error('Not initialized');
81
+ }
82
+ return this._scrollPositionRestoration.locationRendered(location);
83
+ }
84
+ return Promise.resolve();
85
+ }
86
+ }
87
+ exports.default = NavigationStack;
88
+ module.exports = exports.default;
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+ class DataStorage {
6
+ constructor(session, {
7
+ namespace
8
+ }) {
9
+ if (!session.key) {
10
+ throw new Error('`DataStorage` requires a `session.key`');
11
+ }
12
+ this._sessionKey = session.key;
13
+ this._dataStorage = session.environment.dataStorage;
14
+ this._namespace = namespace;
15
+ }
16
+ get(key) {
17
+ const storageKey = this._getStorageKey(key);
18
+ try {
19
+ const value = this._dataStorage.get(storageKey);
20
+ // === null is probably sufficient.
21
+ if (value === null) {
22
+ return undefined;
23
+ }
24
+
25
+ // We want to catch JSON parse errors in case someone separately threw
26
+ // junk into sessionStorage under our namespace.
27
+ return JSON.parse(value);
28
+ } catch (error) {
29
+ // eslint-disable-next-line no-console
30
+ console.error('[navigation-stack] Could not read data from storage');
31
+
32
+ // Pretend that the entry doesn't exist.
33
+ return undefined;
34
+ }
35
+ }
36
+ set(key, value) {
37
+ const storageKey = this._getStorageKey(key);
38
+ if (value === undefined) {
39
+ try {
40
+ this._dataStorage.remove(storageKey);
41
+ } catch (error) {
42
+ // No need to handle errors here.
43
+ // eslint-disable-next-line no-console
44
+ console.error('[navigation-stack] Could not delete data from storage');
45
+ }
46
+ return;
47
+ }
48
+
49
+ // Unlike with read, we want to fail on invalid values here, since the
50
+ // value here is provided by the caller of this method.
51
+ const valueString = JSON.stringify(value);
52
+ try {
53
+ this._dataStorage.set(storageKey, valueString);
54
+ } catch (error) {
55
+ // No need to handle errors here either. If it didn't work, it didn't
56
+ // work. We make no guarantees about actually saving the value.
57
+ // eslint-disable-next-line no-console
58
+ console.error('[navigation-stack] Could not save data in storage');
59
+ }
60
+ }
61
+
62
+ // It could also implement a method that would clean up any data written so far,
63
+ // but so far it doesn't seem to be required by any real-world use case.
64
+ // cleanUp() {}
65
+
66
+ _getStorageKey(key) {
67
+ return `${this._sessionKey}|${this.namespace}|${key}`;
68
+ }
69
+ }
70
+ exports.default = DataStorage;
71
+ module.exports = exports.default;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+ var _DataStorage = _interopRequireDefault(require("./DataStorage"));
6
+ var _getLocationUrl = _interopRequireDefault(require("../getLocationUrl"));
7
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
+ class LocationDataStorage {
9
+ constructor(session, {
10
+ namespace
11
+ }) {
12
+ this._storage = new _DataStorage.default(session, {
13
+ namespace
14
+ });
15
+ this._getFallbackLocationKey = _getLocationUrl.default;
16
+ }
17
+ get(location, key) {
18
+ return this._storage.get(this._getKey(location, key));
19
+ }
20
+ set(location, key, value) {
21
+ this._storage.set(this._getKey(location, key), value);
22
+ }
23
+ _getKey(location, key) {
24
+ const locationKey = location.key || this._getFallbackLocationKey(location);
25
+ return `${locationKey}|${key}`;
26
+ }
27
+ }
28
+ exports.default = LocationDataStorage;
29
+ module.exports = exports.default;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.LocationDataStorage = exports.DataStorage = void 0;
5
+ var _DataStorage = _interopRequireDefault(require("./DataStorage"));
6
+ exports.DataStorage = _DataStorage.default;
7
+ var _LocationDataStorage = _interopRequireDefault(require("./LocationDataStorage"));
8
+ exports.LocationDataStorage = _LocationDataStorage.default;
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = debug;
5
+ const DEBUG = false;
6
+ function debug(...args) {
7
+ if (DEBUG) {
8
+ // eslint-disable-next-line no-console
9
+ console.log(...args);
10
+ }
11
+ }
12
+ module.exports = exports.default;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+ var _InMemoryDataStorage = _interopRequireDefault(require("./data-storage/InMemoryDataStorage"));
6
+ var _InMemoryScrollPosition = _interopRequireDefault(require("./scroll-position/InMemoryScrollPosition"));
7
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
+ class InMemoryEnvironment {
9
+ constructor() {
10
+ this.dataStorage = new _InMemoryDataStorage.default();
11
+ this.scrollPosition = new _InMemoryScrollPosition.default();
12
+ }
13
+ }
14
+ exports.default = InMemoryEnvironment;
15
+ module.exports = exports.default;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+ var _WebBrowserDataStorage = _interopRequireDefault(require("./data-storage/WebBrowserDataStorage"));
6
+ var _WebBrowserScrollPosition = _interopRequireDefault(require("./scroll-position/WebBrowserScrollPosition"));
7
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
+ class WebBrowserEnvironment {
9
+ constructor() {
10
+ this.dataStorage = new _WebBrowserDataStorage.default();
11
+ this.scrollPosition = new _WebBrowserScrollPosition.default();
12
+ }
13
+ }
14
+ exports.default = WebBrowserEnvironment;
15
+ module.exports = exports.default;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+ class InMemoryDataStorage {
6
+ constructor() {
7
+ this._state = {};
8
+ }
9
+
10
+ // Returns either a `string` value or `null` if the key doesn't exist.
11
+ get(key) {
12
+ if (key in this._state) {
13
+ return this._state[key];
14
+ }
15
+ return null;
16
+ }
17
+ remove(key) {
18
+ if (key in this._state) {
19
+ delete this._state[key];
20
+ }
21
+ }
22
+ set(key, value) {
23
+ this._state[key] = value;
24
+ }
25
+ }
26
+ exports.default = InMemoryDataStorage;
27
+ module.exports = exports.default;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+ class WebBrowserDataStorage {
6
+ // Returns either a `string` value or `null` if the key doesn't exist.
7
+ get(key) {
8
+ // `sessionStorage` persists across page reloads, and so does web browser navigation history.
9
+ return window.sessionStorage.getItem(key);
10
+ }
11
+ remove(key) {
12
+ // `sessionStorage` persists across page reloads, and so does web browser navigation history.
13
+ window.sessionStorage.removeItem(key);
14
+ }
15
+ set(key, value) {
16
+ // `sessionStorage` persists across page reloads, and so does web browser navigation history.
17
+ window.sessionStorage.setItem(key, value);
18
+ }
19
+ }
20
+ exports.default = WebBrowserDataStorage;
21
+ module.exports = exports.default;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+ class InMemoryScrollPosition {
6
+ constructor() {
7
+ this.init();
8
+ }
9
+ getPageScrollPosition() {
10
+ return this._pageScrollPosition || [0, 0];
11
+ }
12
+ setPageScrollPosition(scrollPosition) {
13
+ this._pageScrollPosition = scrollPosition;
14
+ }
15
+
16
+ // eslint-disable-next-line no-unused-vars
17
+ setPageScrollPositionAtAnchor(anchor) {
18
+ this.setPageScrollPosition([0, 0]);
19
+ }
20
+ getScrollableContainerScrollPosition(key) {
21
+ return this._scrollableContainerScrollPositions[key] || [0, 0];
22
+ }
23
+ setScrollableContainerScrollPosition(key, scrollPosition) {
24
+ this._scrollableContainerScrollPositions[key] = scrollPosition;
25
+ }
26
+
27
+ // eslint-disable-next-line no-unused-vars
28
+ addPageScrollListener(listener) {
29
+ return () => {};
30
+ }
31
+
32
+ // eslint-disable-next-line no-unused-vars
33
+ addScrollableContainerScrollListener(scrollableContainerElement, listener) {
34
+ return () => {};
35
+ }
36
+ enableAutomaticScrollRestoration() {}
37
+ disableAutomaticScrollRestoration() {}
38
+ init() {
39
+ this._pageScrollPosition = undefined;
40
+ this._scrollableContainerScrollPositions = {};
41
+ }
42
+ }
43
+ exports.default = InMemoryScrollPosition;
44
+ module.exports = exports.default;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+ class WebBrowserScrollPosition {
6
+ getPageScrollPosition() {
7
+ return [window.pageXOffset, window.pageYOffset];
8
+ }
9
+ setPageScrollPosition(scrollPosition) {
10
+ const [scrollX, scrollY] = scrollPosition;
11
+ window.scrollTo(scrollX, scrollY);
12
+ }
13
+ setPageScrollPositionAtAnchor(anchor) {
14
+ const anchorElement = document.getElementById(anchor) || document.getElementsByName(anchor)[0];
15
+ if (anchorElement) {
16
+ // By default it scrolls the element into view
17
+ // so that it's visible at the top of the window.
18
+ anchorElement.scrollIntoView();
19
+ } else {
20
+ this.setPageScrollPosition([0, 0]);
21
+ }
22
+ }
23
+ getScrollableContainerScrollPosition(scrollableContainerElement) {
24
+ return [scrollableContainerElement.scrollLeft, scrollableContainerElement.scrollTop];
25
+ }
26
+ setScrollableContainerScrollPosition(scrollableContainerElement, scrollPosition) {
27
+ const [scrollX, scrollY] = scrollPosition;
28
+ scrollableContainerElement.scrollLeft = scrollX;
29
+ scrollableContainerElement.scrollTop = scrollY;
30
+ }
31
+ addPageScrollListener(listener) {
32
+ // eslint-disable-next-line no-unused-vars
33
+ const scrollListener = event => {
34
+ listener();
35
+ };
36
+ window.addEventListener('scroll', scrollListener);
37
+ return () => {
38
+ window.removeEventListener('scroll', scrollListener);
39
+ };
40
+ }
41
+ addScrollableContainerScrollListener(scrollableContainerElement, listener) {
42
+ // eslint-disable-next-line no-unused-vars
43
+ const scrollListener = event => {
44
+ listener();
45
+ };
46
+ scrollableContainerElement.addEventListener('scroll', scrollListener);
47
+ return () => {
48
+ scrollableContainerElement.removeEventListener('scroll', scrollListener);
49
+ };
50
+ }
51
+ enableAutomaticScrollRestoration() {
52
+ window.history.scrollRestoration = 'auto';
53
+ }
54
+ disableAutomaticScrollRestoration() {
55
+ window.history.scrollRestoration = 'manual';
56
+ }
57
+ init() {}
58
+ }
59
+ exports.default = WebBrowserScrollPosition;
60
+ module.exports = exports.default;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = getLocationFromInternalLocation;
5
+ const _excluded = ["operation", "delta"];
6
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
7
+ // Converts `LocationInternal` object to a publicly-visible `Location` object.
8
+ // It hides non-essential properties of location such as `operation` and `delta`.
9
+ function getLocationFromInternalLocation(internalLocation) {
10
+ // eslint-disable-next-line no-unused-vars
11
+ const location = _objectWithoutPropertiesLoose(internalLocation, _excluded);
12
+ return location;
13
+ }
14
+ module.exports = exports.default;
package/lib/cjs/index.js CHANGED
@@ -1,11 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  exports.__esModule = true;
4
- exports.removeBasePath = exports.parseLocationUrl = exports.locationReducer = exports.getLocationUrl = exports.createMiddlewares = exports.addNavigationBlocker = exports.addBasePath = exports.ServerSession = exports.MemorySession = exports.LocationDataStorage = exports.BrowserSession = exports.Actions = exports.ActionTypes = void 0;
5
- var _Actions = _interopRequireDefault(require("./Actions"));
6
- exports.Actions = _Actions.default;
7
- var _ActionTypes = _interopRequireDefault(require("./ActionTypes"));
8
- exports.ActionTypes = _ActionTypes.default;
4
+ exports.removeBasePath = exports.parseLocationUrl = exports.parseInputLocation = exports.getLocationUrl = exports.addNavigationBlocker = exports.addBasePath = exports.WebBrowserSession = exports.Session = exports.ServerSideRenderSession = exports.ServerSideNavigationError = exports.NavigationStack = exports.NavigationOutOfBoundsError = exports.LocationDataStorage = exports.InMemorySession = exports.DataStorage = void 0;
9
5
  var _basePath = require("./basePath");
10
6
  exports.addBasePath = _basePath.addBasePath;
11
7
  exports.removeBasePath = _basePath.removeBasePath;
@@ -15,16 +11,24 @@ var _getLocationUrl = _interopRequireDefault(require("./getLocationUrl"));
15
11
  exports.getLocationUrl = _getLocationUrl.default;
16
12
  var _parseLocationUrl = _interopRequireDefault(require("./parseLocationUrl"));
17
13
  exports.parseLocationUrl = _parseLocationUrl.default;
18
- var _createMiddlewares = _interopRequireDefault(require("./createMiddlewares"));
19
- exports.createMiddlewares = _createMiddlewares.default;
20
- var _locationReducer = _interopRequireDefault(require("./locationReducer"));
21
- exports.locationReducer = _locationReducer.default;
22
- var _LocationDataStorage = _interopRequireDefault(require("./LocationDataStorage"));
14
+ var _parseInputLocation = _interopRequireDefault(require("./parseInputLocation"));
15
+ exports.parseInputLocation = _parseInputLocation.default;
16
+ var _NavigationStack = _interopRequireDefault(require("./NavigationStack"));
17
+ exports.NavigationStack = _NavigationStack.default;
18
+ var _DataStorage = _interopRequireDefault(require("./data-storage/DataStorage"));
19
+ exports.DataStorage = _DataStorage.default;
20
+ var _LocationDataStorage = _interopRequireDefault(require("./data-storage/LocationDataStorage"));
23
21
  exports.LocationDataStorage = _LocationDataStorage.default;
24
- var _BrowserSession = _interopRequireDefault(require("./session/BrowserSession"));
25
- exports.BrowserSession = _BrowserSession.default;
26
- var _MemorySession = _interopRequireDefault(require("./session/MemorySession"));
27
- exports.MemorySession = _MemorySession.default;
28
- var _ServerSession = _interopRequireDefault(require("./session/ServerSession"));
29
- exports.ServerSession = _ServerSession.default;
22
+ var _Session = _interopRequireDefault(require("./session/Session"));
23
+ exports.Session = _Session.default;
24
+ var _InMemorySession = _interopRequireDefault(require("./session/InMemorySession"));
25
+ exports.InMemorySession = _InMemorySession.default;
26
+ var _WebBrowserSession = _interopRequireDefault(require("./session/WebBrowserSession"));
27
+ exports.WebBrowserSession = _WebBrowserSession.default;
28
+ var _ServerSideRenderSession = _interopRequireDefault(require("./session/ServerSideRenderSession"));
29
+ exports.ServerSideRenderSession = _ServerSideRenderSession.default;
30
+ var _ServerSideNavigationError = _interopRequireDefault(require("./session/navigation/error/ServerSideNavigationError"));
31
+ exports.ServerSideNavigationError = _ServerSideNavigationError.default;
32
+ var _NavigationOutOfBoundsError = _interopRequireDefault(require("./session/navigation/error/NavigationOutOfBoundsError"));
33
+ exports.NavigationOutOfBoundsError = _NavigationOutOfBoundsError.default;
30
34
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -5,6 +5,7 @@ exports.addNavigationBlocker = addNavigationBlocker;
5
5
  exports.getNavigationBlockers = getNavigationBlockers;
6
6
  exports.removeAllNavigationBlockers = removeAllNavigationBlockers;
7
7
  exports.runNavigationBlockers = runNavigationBlockers;
8
+ var _debug = _interopRequireDefault(require("./debug"));
8
9
  var _isPromise = _interopRequireDefault(require("./isPromise"));
9
10
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
11
  /* eslint-disable no-underscore-dangle */
@@ -24,12 +25,12 @@ function removeNavigationBlockerFromTheList(blocker, session) {
24
25
  }
25
26
  }
26
27
  function removeAllNavigationBlockers(session) {
27
- if (getNavigationBlockers(session).some(blocker => blocker.beforeDestroy)) {
28
- if (!session._removeBeforeDestroyListener) {
29
- throw new Error('`_removeBeforeDestroyListener` property not found in the `session`');
28
+ if (getNavigationBlockers(session).some(blocker => blocker.beforeTermination)) {
29
+ if (!session._removeTerminationBlocker) {
30
+ throw new Error('`_removeTerminationBlocker` property not found in the `session`');
30
31
  }
31
- session._removeBeforeDestroyListener();
32
- session._removeBeforeDestroyListener = undefined;
32
+ session._removeTerminationBlocker();
33
+ session._removeTerminationBlocker = undefined;
33
34
  }
34
35
  session._navigationBlockersList = [];
35
36
  }
@@ -80,45 +81,47 @@ function runNavigationBlockers(navigationBlockers, toLocation) {
80
81
  if ((0, _isPromise.default)(result)) {
81
82
  return result.then(resultValue => {
82
83
  if (resultValue) {
84
+ (0, _debug.default)('Navigation blocked', toLocation.pathname);
83
85
  return resultValue;
84
86
  }
85
87
  return next();
86
88
  });
87
89
  }
88
90
  if (result) {
91
+ (0, _debug.default)('Navigation blocked', toLocation.pathname);
89
92
  return result;
90
93
  }
91
94
  return next();
92
95
  }
93
96
 
94
97
  /* istanbul ignore next: not testable with Karma */
95
- function onBeforeDestroy(session) {
98
+ function terminationBlocker(session) {
96
99
  const result = runNavigationBlockers(getNavigationBlockers(session), null);
97
100
 
98
- // If no blocker returned anything, don't prevent the "unload" event.
101
+ // If no blocker returned anything, so don't prevent the navigation.
99
102
  if (!result) {
100
103
  return undefined;
101
104
  }
102
105
 
103
106
  // Web browsers don't allow displaying a custom modal in "beforeunload" phase.
104
107
  // They only allow displaying a standard one, with the default text.
105
- // Hence, "asynchronous" blockers should be ignored.
108
+ // Hence, "asynchronous" blockers should be ignored because web browsers won't wait for those to finish anyway.
106
109
  // https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event
107
110
  if ((0, _isPromise.default)(result)) {
108
111
  return undefined;
109
112
  }
110
113
 
111
- // Prevent the "unload" event.
114
+ // Block the navigation.
112
115
  return true;
113
116
  }
114
117
  function addNavigationBlocker(session, blocker) {
115
- // All navigation blockers also run on `beforeDestroy` event.
118
+ // All navigation blockers also run on `beforeTermination` event.
116
119
  // If required, this could be a parameter of this function.
117
120
  // The rationale could be that adding a `beforeunload` listener
118
121
  // disables web page caching in some browsers like Firefox.
119
- const beforeDestroy = true;
122
+ const beforeTermination = true;
120
123
 
121
- // If it's the first "beforeDestroy" blocker, add the global `onBeforeDestroy` listener.
124
+ // If it's the first "beforeTermination" blocker, add a `terminationBlocker`.
122
125
  //
123
126
  // Sidenote: Add the "beforeunload" event listener only as needed, as its presence
124
127
  // prevents the page from being added to the page navigation cache:
@@ -128,27 +131,29 @@ function addNavigationBlocker(session, blocker) {
128
131
  // and this is bad for performance."
129
132
  //
130
133
  // https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event
131
- if (beforeDestroy && !getNavigationBlockers(session).some(navigationBlocker => navigationBlocker.beforeDestroy)) {
132
- if (session._removeBeforeDestroyListener) {
133
- throw new Error('Unexpected `_removeBeforeDestroyListener` property found in the `session`');
134
+ if (beforeTermination && !getNavigationBlockers(session).some(navigationBlocker => navigationBlocker.beforeTermination)) {
135
+ if (session._removeTerminationBlocker) {
136
+ throw new Error('Unexpected `_removeTerminationBlocker` property found in the `session`');
134
137
  }
135
- session._removeBeforeDestroyListener = session.addBeforeDestroyListener(() => onBeforeDestroy(session));
138
+ session._removeTerminationBlocker = session.lifecycle.addTerminationBlocker(() => {
139
+ return terminationBlocker(session);
140
+ });
136
141
  }
137
142
  const newNavigationBlocker = {
138
143
  blocker,
139
- beforeDestroy
144
+ beforeTermination
140
145
  };
141
146
  addNavigationBlockerToTheList(newNavigationBlocker, session);
142
147
  return () => {
143
148
  removeNavigationBlockerFromTheList(newNavigationBlocker, session);
144
149
 
145
- // If it was the last "beforeDestroy" blocker, remove the global `onBeforeDestroy` listener.
146
- if (beforeDestroy && !getNavigationBlockers(session).some(navigationBlocker => navigationBlocker.beforeDestroy)) {
147
- if (!session._removeBeforeDestroyListener) {
148
- throw new Error('`_removeBeforeDestroyListener` property not found in the `session`');
150
+ // If it was the last "beforeTermination" blocker, remove navigation blocker.
151
+ if (beforeTermination && !getNavigationBlockers(session).some(navigationBlocker => navigationBlocker.beforeTermination)) {
152
+ if (!session._removeTerminationBlocker) {
153
+ throw new Error('`_removeTerminationBlocker` property not found in the `session`');
149
154
  }
150
- session._removeBeforeDestroyListener();
151
- session._removeBeforeDestroyListener = undefined;
155
+ session._removeTerminationBlocker();
156
+ session._removeTerminationBlocker = undefined;
152
157
  }
153
158
  };
154
159
  }