react-native-instant-webview 0.1.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 (64) hide show
  1. package/README.md +170 -0
  2. package/lib/commonjs/PooledWebView.js +112 -0
  3. package/lib/commonjs/PooledWebView.js.map +1 -0
  4. package/lib/commonjs/WebViewManager.js +102 -0
  5. package/lib/commonjs/WebViewManager.js.map +1 -0
  6. package/lib/commonjs/WebViewPoolProvider.js +102 -0
  7. package/lib/commonjs/WebViewPoolProvider.js.map +1 -0
  8. package/lib/commonjs/WebViewSlot.js +91 -0
  9. package/lib/commonjs/WebViewSlot.js.map +1 -0
  10. package/lib/commonjs/constants.js +51 -0
  11. package/lib/commonjs/constants.js.map +1 -0
  12. package/lib/commonjs/index.js +41 -0
  13. package/lib/commonjs/index.js.map +1 -0
  14. package/lib/commonjs/types.js +6 -0
  15. package/lib/commonjs/types.js.map +1 -0
  16. package/lib/commonjs/usePooledWebView.js +54 -0
  17. package/lib/commonjs/usePooledWebView.js.map +1 -0
  18. package/lib/module/PooledWebView.js +105 -0
  19. package/lib/module/PooledWebView.js.map +1 -0
  20. package/lib/module/WebViewManager.js +96 -0
  21. package/lib/module/WebViewManager.js.map +1 -0
  22. package/lib/module/WebViewPoolProvider.js +92 -0
  23. package/lib/module/WebViewPoolProvider.js.map +1 -0
  24. package/lib/module/WebViewSlot.js +84 -0
  25. package/lib/module/WebViewSlot.js.map +1 -0
  26. package/lib/module/constants.js +45 -0
  27. package/lib/module/constants.js.map +1 -0
  28. package/lib/module/index.js +5 -0
  29. package/lib/module/index.js.map +1 -0
  30. package/lib/module/types.js +2 -0
  31. package/lib/module/types.js.map +1 -0
  32. package/lib/module/usePooledWebView.js +48 -0
  33. package/lib/module/usePooledWebView.js.map +1 -0
  34. package/lib/typescript/PooledWebView.d.ts +5 -0
  35. package/lib/typescript/PooledWebView.d.ts.map +1 -0
  36. package/lib/typescript/WebViewManager.d.ts +21 -0
  37. package/lib/typescript/WebViewManager.d.ts.map +1 -0
  38. package/lib/typescript/WebViewPoolProvider.d.ts +6 -0
  39. package/lib/typescript/WebViewPoolProvider.d.ts.map +1 -0
  40. package/lib/typescript/WebViewSlot.d.ts +13 -0
  41. package/lib/typescript/WebViewSlot.d.ts.map +1 -0
  42. package/lib/typescript/__mocks__/react-native-webview.d.ts +12 -0
  43. package/lib/typescript/__mocks__/react-native-webview.d.ts.map +1 -0
  44. package/lib/typescript/__mocks__/react-native.d.ts +18 -0
  45. package/lib/typescript/__mocks__/react-native.d.ts.map +1 -0
  46. package/lib/typescript/constants.d.ts +9 -0
  47. package/lib/typescript/constants.d.ts.map +1 -0
  48. package/lib/typescript/index.d.ts +6 -0
  49. package/lib/typescript/index.d.ts.map +1 -0
  50. package/lib/typescript/types.d.ts +62 -0
  51. package/lib/typescript/types.d.ts.map +1 -0
  52. package/lib/typescript/usePooledWebView.d.ts +3 -0
  53. package/lib/typescript/usePooledWebView.d.ts.map +1 -0
  54. package/package.json +87 -0
  55. package/src/PooledWebView.tsx +105 -0
  56. package/src/WebViewManager.ts +120 -0
  57. package/src/WebViewPoolProvider.tsx +138 -0
  58. package/src/WebViewSlot.tsx +107 -0
  59. package/src/__mocks__/react-native-webview.tsx +16 -0
  60. package/src/__mocks__/react-native.ts +14 -0
  61. package/src/constants.ts +46 -0
  62. package/src/index.tsx +17 -0
  63. package/src/types.ts +72 -0
  64. package/src/usePooledWebView.ts +58 -0
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.HIDDEN_STYLE = exports.DEFAULT_POOL_CONFIG = exports.CLEANUP_SCRIPT = exports.BLANK_HTML_SOURCE = void 0;
7
+ const DEFAULT_POOL_CONFIG = exports.DEFAULT_POOL_CONFIG = {
8
+ poolSize: 3,
9
+ cleanupOnReturn: true
10
+ };
11
+ const HIDDEN_STYLE = exports.HIDDEN_STYLE = {
12
+ position: 'absolute',
13
+ width: 1,
14
+ height: 1,
15
+ left: -9999,
16
+ top: -9999,
17
+ opacity: 0
18
+ };
19
+
20
+ // Blank HTML source used for idle/cleaning WebViews.
21
+ // Using { html } instead of { uri: 'about:blank' } because
22
+ // react-native-webview's native code may route 'about:blank'
23
+ // through loadFileURL: which throws NSInvalidArgumentException.
24
+ const BLANK_HTML_SOURCE = exports.BLANK_HTML_SOURCE = {
25
+ html: ''
26
+ };
27
+
28
+ // Cleanup script injected into WebView when returning to pool.
29
+ // Resets scroll position, clears timers, and removes all body content.
30
+ // The body.innerHTML = '' is intentional — it clears the WebView DOM
31
+ // as part of the pool cleanup process (no user content involved).
32
+ const CLEANUP_SCRIPT = exports.CLEANUP_SCRIPT = `
33
+ (function() {
34
+ try {
35
+ window.scrollTo(0, 0);
36
+ var highestTimeoutId = setTimeout(function(){}, 0);
37
+ for (var i = 0; i < highestTimeoutId; i++) {
38
+ clearTimeout(i);
39
+ }
40
+ var highestIntervalId = setInterval(function(){}, 0);
41
+ for (var j = 0; j < highestIntervalId; j++) {
42
+ clearInterval(j);
43
+ }
44
+ if (document.body) {
45
+ document.body.innerHTML = '';
46
+ }
47
+ } catch(e) {}
48
+ true;
49
+ })();
50
+ `;
51
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["DEFAULT_POOL_CONFIG","exports","poolSize","cleanupOnReturn","HIDDEN_STYLE","position","width","height","left","top","opacity","BLANK_HTML_SOURCE","html","CLEANUP_SCRIPT"],"sourceRoot":"../../src","sources":["constants.ts"],"mappings":";;;;;;AAGO,MAAMA,mBAA+B,GAAAC,OAAA,CAAAD,mBAAA,GAAG;EAC7CE,QAAQ,EAAE,CAAC;EACXC,eAAe,EAAE;AACnB,CAAC;AAEM,MAAMC,YAAuB,GAAAH,OAAA,CAAAG,YAAA,GAAG;EACrCC,QAAQ,EAAE,UAAU;EACpBC,KAAK,EAAE,CAAC;EACRC,MAAM,EAAE,CAAC;EACTC,IAAI,EAAE,CAAC,IAAI;EACXC,GAAG,EAAE,CAAC,IAAI;EACVC,OAAO,EAAE;AACX,CAAC;;AAED;AACA;AACA;AACA;AACO,MAAMC,iBAAiB,GAAAV,OAAA,CAAAU,iBAAA,GAAG;EAAEC,IAAI,EAAE;AAAG,CAAU;;AAEtD;AACA;AACA;AACA;AACO,MAAMC,cAAc,GAAAZ,OAAA,CAAAY,cAAA,GAAG;AAC9B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC","ignoreList":[]}
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "PooledWebView", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _PooledWebView.default;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "WebViewManager", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _WebViewManager.default;
16
+ }
17
+ });
18
+ Object.defineProperty(exports, "WebViewPoolProvider", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _WebViewPoolProvider.WebViewPoolProvider;
22
+ }
23
+ });
24
+ Object.defineProperty(exports, "usePooledWebView", {
25
+ enumerable: true,
26
+ get: function () {
27
+ return _usePooledWebView.usePooledWebView;
28
+ }
29
+ });
30
+ Object.defineProperty(exports, "useWebViewPool", {
31
+ enumerable: true,
32
+ get: function () {
33
+ return _WebViewPoolProvider.useWebViewPool;
34
+ }
35
+ });
36
+ var _WebViewPoolProvider = require("./WebViewPoolProvider");
37
+ var _PooledWebView = _interopRequireDefault(require("./PooledWebView"));
38
+ var _usePooledWebView = require("./usePooledWebView");
39
+ var _WebViewManager = _interopRequireDefault(require("./WebViewManager"));
40
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
41
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_WebViewPoolProvider","require","_PooledWebView","_interopRequireDefault","_usePooledWebView","_WebViewManager","e","__esModule","default"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,oBAAA,GAAAC,OAAA;AACA,IAAAC,cAAA,GAAAC,sBAAA,CAAAF,OAAA;AACA,IAAAG,iBAAA,GAAAH,OAAA;AACA,IAAAI,eAAA,GAAAF,sBAAA,CAAAF,OAAA;AAA6D,SAAAE,uBAAAG,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA","ignoreList":[]}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../src","sources":["types.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.usePooledWebView = usePooledWebView;
7
+ var _react = require("react");
8
+ var _WebViewPoolProvider = require("./WebViewPoolProvider");
9
+ let hookBorrowerIdCounter = 0;
10
+ function usePooledWebView() {
11
+ const pool = (0, _WebViewPoolProvider.useWebViewPool)();
12
+ const instanceIdRef = (0, _react.useRef)(null);
13
+ const webViewRefRef = (0, _react.useRef)(null);
14
+ const [instanceId, setInstanceId] = (0, _react.useState)(null);
15
+ (0, _react.useEffect)(() => {
16
+ return () => {
17
+ if (instanceIdRef.current) {
18
+ pool.release(instanceIdRef.current);
19
+ instanceIdRef.current = null;
20
+ webViewRefRef.current = null;
21
+ }
22
+ };
23
+ }, [pool]);
24
+ const borrow = (0, _react.useCallback)(() => {
25
+ if (instanceIdRef.current) {
26
+ return {
27
+ instanceId: instanceIdRef.current,
28
+ webViewRef: webViewRefRef.current
29
+ };
30
+ }
31
+ const borrowerId = `hook-borrower-${++hookBorrowerIdCounter}`;
32
+ const result = pool.borrow(borrowerId);
33
+ if (!result) return null;
34
+ instanceIdRef.current = result.instanceId;
35
+ webViewRefRef.current = result.webViewRef;
36
+ setInstanceId(result.instanceId);
37
+ return result;
38
+ }, [pool]);
39
+ const release = (0, _react.useCallback)(() => {
40
+ if (instanceIdRef.current) {
41
+ pool.release(instanceIdRef.current);
42
+ instanceIdRef.current = null;
43
+ webViewRefRef.current = null;
44
+ setInstanceId(null);
45
+ }
46
+ }, [pool]);
47
+ return {
48
+ borrow,
49
+ release,
50
+ instanceId,
51
+ webViewRef: webViewRefRef.current
52
+ };
53
+ }
54
+ //# sourceMappingURL=usePooledWebView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_react","require","_WebViewPoolProvider","hookBorrowerIdCounter","usePooledWebView","pool","useWebViewPool","instanceIdRef","useRef","webViewRefRef","instanceId","setInstanceId","useState","useEffect","current","release","borrow","useCallback","webViewRef","borrowerId","result"],"sourceRoot":"../../src","sources":["usePooledWebView.ts"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAGA,IAAAC,oBAAA,GAAAD,OAAA;AAGA,IAAIE,qBAAqB,GAAG,CAAC;AAEtB,SAASC,gBAAgBA,CAAA,EAA2B;EACzD,MAAMC,IAAI,GAAG,IAAAC,mCAAc,EAAC,CAAC;EAC7B,MAAMC,aAAa,GAAG,IAAAC,aAAM,EAAgB,IAAI,CAAC;EACjD,MAAMC,aAAa,GAAG,IAAAD,aAAM,EAAmC,IAAI,CAAC;EACpE,MAAM,CAACE,UAAU,EAAEC,aAAa,CAAC,GAAG,IAAAC,eAAQ,EAAgB,IAAI,CAAC;EAEjE,IAAAC,gBAAS,EAAC,MAAM;IACd,OAAO,MAAM;MACX,IAAIN,aAAa,CAACO,OAAO,EAAE;QACzBT,IAAI,CAACU,OAAO,CAACR,aAAa,CAACO,OAAO,CAAC;QACnCP,aAAa,CAACO,OAAO,GAAG,IAAI;QAC5BL,aAAa,CAACK,OAAO,GAAG,IAAI;MAC9B;IACF,CAAC;EACH,CAAC,EAAE,CAACT,IAAI,CAAC,CAAC;EAEV,MAAMW,MAAM,GAAG,IAAAC,kBAAW,EAAC,MAAM;IAC/B,IAAIV,aAAa,CAACO,OAAO,EAAE;MACzB,OAAO;QACLJ,UAAU,EAAEH,aAAa,CAACO,OAAO;QACjCI,UAAU,EAAET,aAAa,CAACK;MAC5B,CAAC;IACH;IAEA,MAAMK,UAAU,GAAG,iBAAiB,EAAEhB,qBAAqB,EAAE;IAC7D,MAAMiB,MAAM,GAAGf,IAAI,CAACW,MAAM,CAACG,UAAU,CAAC;IACtC,IAAI,CAACC,MAAM,EAAE,OAAO,IAAI;IAExBb,aAAa,CAACO,OAAO,GAAGM,MAAM,CAACV,UAAU;IACzCD,aAAa,CAACK,OAAO,GAAGM,MAAM,CAACF,UAAU;IACzCP,aAAa,CAACS,MAAM,CAACV,UAAU,CAAC;IAChC,OAAOU,MAAM;EACf,CAAC,EAAE,CAACf,IAAI,CAAC,CAAC;EAEV,MAAMU,OAAO,GAAG,IAAAE,kBAAW,EAAC,MAAM;IAChC,IAAIV,aAAa,CAACO,OAAO,EAAE;MACzBT,IAAI,CAACU,OAAO,CAACR,aAAa,CAACO,OAAO,CAAC;MACnCP,aAAa,CAACO,OAAO,GAAG,IAAI;MAC5BL,aAAa,CAACK,OAAO,GAAG,IAAI;MAC5BH,aAAa,CAAC,IAAI,CAAC;IACrB;EACF,CAAC,EAAE,CAACN,IAAI,CAAC,CAAC;EAEV,OAAO;IACLW,MAAM;IACND,OAAO;IACPL,UAAU;IACVQ,UAAU,EAAET,aAAa,CAACK;EAC5B,CAAC;AACH","ignoreList":[]}
@@ -0,0 +1,105 @@
1
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
3
+ import { View } from 'react-native';
4
+ import { WebView } from 'react-native-webview';
5
+ import { useWebViewPool } from './WebViewPoolProvider';
6
+ let borrowerIdCounter = 0;
7
+ const PooledWebView = ({
8
+ poolKey,
9
+ containerStyle,
10
+ onPoolExhausted,
11
+ onBorrowed,
12
+ onReturned,
13
+ source,
14
+ ...webViewProps
15
+ }) => {
16
+ const pool = useWebViewPool();
17
+ const instanceIdRef = useRef(null);
18
+ const placeholderRef = useRef(null);
19
+ const borrowerIdRef = useRef(poolKey ?? `borrower-${++borrowerIdCounter}`);
20
+ const propsRef = useRef({
21
+ source,
22
+ ...webViewProps
23
+ });
24
+ const [borrowed, setBorrowed] = useState(false);
25
+ const [fallback, setFallback] = useState(false);
26
+
27
+ // Keep propsRef in sync without triggering re-renders
28
+ propsRef.current = {
29
+ source,
30
+ ...webViewProps
31
+ };
32
+
33
+ // Borrow on mount
34
+ useEffect(() => {
35
+ const result = pool.borrow(borrowerIdRef.current);
36
+ if (!result) {
37
+ setFallback(true);
38
+ onPoolExhausted?.();
39
+ return;
40
+ }
41
+ instanceIdRef.current = result.instanceId;
42
+ pool.setInstanceProps(result.instanceId, propsRef.current);
43
+ setBorrowed(true);
44
+ onBorrowed?.(result.instanceId);
45
+ return () => {
46
+ const id = instanceIdRef.current;
47
+ if (id) {
48
+ pool.setInstanceLayout(id, null);
49
+ pool.release(id);
50
+ onReturned?.(id);
51
+ instanceIdRef.current = null;
52
+ }
53
+ };
54
+ // eslint-disable-next-line react-hooks/exhaustive-deps
55
+ }, []);
56
+
57
+ // Update props when source changes (the primary prop that changes)
58
+ useEffect(() => {
59
+ const id = instanceIdRef.current;
60
+ if (!id || !borrowed) return;
61
+ pool.setInstanceProps(id, propsRef.current);
62
+ // Only re-sync when source actually changes
63
+ // eslint-disable-next-line react-hooks/exhaustive-deps
64
+ }, [source]);
65
+
66
+ // Measure placeholder position
67
+ const handleLayout = useCallback(_event => {
68
+ const id = instanceIdRef.current;
69
+ if (!id || !placeholderRef.current) return;
70
+ placeholderRef.current.measureInWindow((x, y, width, height) => {
71
+ if (width > 0 && height > 0) {
72
+ pool.setInstanceLayout(id, {
73
+ top: y,
74
+ left: x,
75
+ width,
76
+ height
77
+ });
78
+ }
79
+ });
80
+ }, [pool]);
81
+
82
+ // Pool exhausted — fall back to a regular WebView
83
+ if (fallback) {
84
+ return /*#__PURE__*/React.createElement(View, {
85
+ style: [{
86
+ flex: 1
87
+ }, containerStyle]
88
+ }, /*#__PURE__*/React.createElement(WebView, _extends({
89
+ source: source
90
+ }, webViewProps, {
91
+ style: {
92
+ flex: 1
93
+ }
94
+ })));
95
+ }
96
+ return /*#__PURE__*/React.createElement(View, {
97
+ ref: placeholderRef,
98
+ style: [{
99
+ flex: 1
100
+ }, containerStyle],
101
+ onLayout: handleLayout
102
+ });
103
+ };
104
+ export default /*#__PURE__*/React.memo(PooledWebView);
105
+ //# sourceMappingURL=PooledWebView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","useCallback","useEffect","useRef","useState","View","WebView","useWebViewPool","borrowerIdCounter","PooledWebView","poolKey","containerStyle","onPoolExhausted","onBorrowed","onReturned","source","webViewProps","pool","instanceIdRef","placeholderRef","borrowerIdRef","propsRef","borrowed","setBorrowed","fallback","setFallback","current","result","borrow","instanceId","setInstanceProps","id","setInstanceLayout","release","handleLayout","_event","measureInWindow","x","y","width","height","top","left","createElement","style","flex","_extends","ref","onLayout","memo"],"sourceRoot":"../../src","sources":["PooledWebView.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,96 @@
1
+ import { createRef } from 'react';
2
+ import { DEFAULT_POOL_CONFIG } from './constants';
3
+ class WebViewManager {
4
+ static instance = null;
5
+ config = DEFAULT_POOL_CONFIG;
6
+ instances = [];
7
+ listeners = new Set();
8
+ initialized = false;
9
+ constructor() {}
10
+ static getInstance() {
11
+ if (!WebViewManager.instance) {
12
+ WebViewManager.instance = new WebViewManager();
13
+ }
14
+ return WebViewManager.instance;
15
+ }
16
+ static resetInstance() {
17
+ WebViewManager.instance = null;
18
+ }
19
+ initialize(config) {
20
+ if (this.initialized) return;
21
+ this.config = {
22
+ ...DEFAULT_POOL_CONFIG,
23
+ ...config
24
+ };
25
+ this.instances = [];
26
+ for (let i = 0; i < this.config.poolSize; i++) {
27
+ this.instances.push({
28
+ id: `webview-pool-${i}`,
29
+ status: 'idle',
30
+ webViewRef: /*#__PURE__*/createRef(),
31
+ borrowerId: null,
32
+ createdAt: Date.now(),
33
+ borrowedAt: null
34
+ });
35
+ }
36
+ this.initialized = true;
37
+ this.notify();
38
+ }
39
+ borrow(borrowerId) {
40
+ const idle = this.instances.find(inst => inst.status === 'idle');
41
+ if (!idle) return null;
42
+ idle.status = 'borrowed';
43
+ idle.borrowerId = borrowerId;
44
+ idle.borrowedAt = Date.now();
45
+ this.notify();
46
+ return {
47
+ instanceId: idle.id,
48
+ webViewRef: idle.webViewRef
49
+ };
50
+ }
51
+ release(instanceId) {
52
+ const inst = this.instances.find(i => i.id === instanceId);
53
+ if (!inst || inst.status !== 'borrowed') return;
54
+ if (this.config.cleanupOnReturn) {
55
+ inst.status = 'cleaning';
56
+ } else {
57
+ inst.status = 'idle';
58
+ inst.borrowerId = null;
59
+ inst.borrowedAt = null;
60
+ }
61
+ this.notify();
62
+ }
63
+ markIdle(instanceId) {
64
+ const inst = this.instances.find(i => i.id === instanceId);
65
+ if (!inst) return;
66
+ inst.status = 'idle';
67
+ inst.borrowerId = null;
68
+ inst.borrowedAt = null;
69
+ this.notify();
70
+ }
71
+ getState() {
72
+ return {
73
+ instances: [...this.instances],
74
+ availableCount: this.instances.filter(i => i.status === 'idle').length,
75
+ borrowedCount: this.instances.filter(i => i.status === 'borrowed').length,
76
+ initialized: this.initialized
77
+ };
78
+ }
79
+ getConfig() {
80
+ return {
81
+ ...this.config
82
+ };
83
+ }
84
+ subscribe(listener) {
85
+ this.listeners.add(listener);
86
+ return () => {
87
+ this.listeners.delete(listener);
88
+ };
89
+ }
90
+ notify() {
91
+ const state = this.getState();
92
+ this.listeners.forEach(listener => listener(state));
93
+ }
94
+ }
95
+ export default WebViewManager;
96
+ //# sourceMappingURL=WebViewManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createRef","DEFAULT_POOL_CONFIG","WebViewManager","instance","config","instances","listeners","Set","initialized","constructor","getInstance","resetInstance","initialize","i","poolSize","push","id","status","webViewRef","borrowerId","createdAt","Date","now","borrowedAt","notify","borrow","idle","find","inst","instanceId","release","cleanupOnReturn","markIdle","getState","availableCount","filter","length","borrowedCount","getConfig","subscribe","listener","add","delete","state","forEach"],"sourceRoot":"../../src","sources":["WebViewManager.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,92 @@
1
+ import React, { createContext, useCallback, useContext, useEffect, useRef, useState } from 'react';
2
+ import { View, StyleSheet } from 'react-native';
3
+ import { DEFAULT_POOL_CONFIG } from './constants';
4
+ import WebViewManager from './WebViewManager';
5
+ import WebViewSlot from './WebViewSlot';
6
+ const WebViewPoolContext = /*#__PURE__*/createContext(null);
7
+ export function useWebViewPool() {
8
+ const ctx = useContext(WebViewPoolContext);
9
+ if (!ctx) {
10
+ throw new Error('useWebViewPool must be used within a WebViewPoolProvider');
11
+ }
12
+ return ctx;
13
+ }
14
+ export const WebViewPoolProvider = ({
15
+ config,
16
+ children
17
+ }) => {
18
+ const managerRef = useRef(WebViewManager.getInstance());
19
+ const mergedConfig = useRef({
20
+ ...DEFAULT_POOL_CONFIG,
21
+ ...config
22
+ }).current;
23
+ const [poolState, setPoolState] = useState(() => {
24
+ const mgr = managerRef.current;
25
+ mgr.initialize(mergedConfig);
26
+ return mgr.getState();
27
+ });
28
+ const layoutsRef = useRef(new Map());
29
+ const propsRef = useRef(new Map());
30
+ const [, forceRender] = useState(0);
31
+ useEffect(() => {
32
+ const mgr = managerRef.current;
33
+ const unsub = mgr.subscribe(state => {
34
+ setPoolState(state);
35
+ });
36
+ return unsub;
37
+ }, []);
38
+ const borrow = useCallback(borrowerId => {
39
+ return managerRef.current.borrow(borrowerId);
40
+ }, []);
41
+ const release = useCallback(instanceId => {
42
+ layoutsRef.current.delete(instanceId);
43
+ propsRef.current.delete(instanceId);
44
+ managerRef.current.release(instanceId);
45
+ }, []);
46
+ const setInstanceLayout = useCallback((instanceId, layout) => {
47
+ layoutsRef.current.set(instanceId, layout);
48
+ forceRender(c => c + 1);
49
+ }, []);
50
+ const setInstanceProps = useCallback((instanceId, props) => {
51
+ propsRef.current.set(instanceId, props);
52
+ // No forceRender here — the slot reads from propsRef on next render
53
+ // triggered by the Manager's state change (borrow/release).
54
+ }, []);
55
+ const getInstanceLayout = useCallback(instanceId => {
56
+ return layoutsRef.current.get(instanceId) ?? null;
57
+ }, []);
58
+ const getInstanceProps = useCallback(instanceId => {
59
+ return propsRef.current.get(instanceId);
60
+ }, []);
61
+ const handleCleanupComplete = useCallback(instanceId => {
62
+ managerRef.current.markIdle(instanceId);
63
+ }, []);
64
+ const contextValue = {
65
+ state: poolState,
66
+ borrow,
67
+ release,
68
+ setInstanceLayout,
69
+ setInstanceProps,
70
+ getInstanceLayout,
71
+ getInstanceProps
72
+ };
73
+ return /*#__PURE__*/React.createElement(WebViewPoolContext.Provider, {
74
+ value: contextValue
75
+ }, /*#__PURE__*/React.createElement(View, {
76
+ style: styles.container
77
+ }, children, poolState.instances.map(instance => /*#__PURE__*/React.createElement(WebViewSlot, {
78
+ key: instance.id,
79
+ instance: instance,
80
+ layout: layoutsRef.current.get(instance.id) ?? null,
81
+ instanceProps: propsRef.current.get(instance.id),
82
+ config: mergedConfig,
83
+ onCleanupComplete: handleCleanupComplete
84
+ }))));
85
+ };
86
+ const styles = StyleSheet.create({
87
+ container: {
88
+ flex: 1
89
+ }
90
+ });
91
+ export default WebViewPoolProvider;
92
+ //# sourceMappingURL=WebViewPoolProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","createContext","useCallback","useContext","useEffect","useRef","useState","View","StyleSheet","DEFAULT_POOL_CONFIG","WebViewManager","WebViewSlot","WebViewPoolContext","useWebViewPool","ctx","Error","WebViewPoolProvider","config","children","managerRef","getInstance","mergedConfig","current","poolState","setPoolState","mgr","initialize","getState","layoutsRef","Map","propsRef","forceRender","unsub","subscribe","state","borrow","borrowerId","release","instanceId","delete","setInstanceLayout","layout","set","c","setInstanceProps","props","getInstanceLayout","get","getInstanceProps","handleCleanupComplete","markIdle","contextValue","createElement","Provider","value","style","styles","container","instances","map","instance","key","id","instanceProps","onCleanupComplete","create","flex"],"sourceRoot":"../../src","sources":["WebViewPoolProvider.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,84 @@
1
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
+ import { View } from 'react-native';
4
+ import { WebView } from 'react-native-webview';
5
+ import { BLANK_HTML_SOURCE, CLEANUP_SCRIPT, HIDDEN_STYLE } from './constants';
6
+ const WebViewSlot = ({
7
+ instance,
8
+ layout,
9
+ instanceProps,
10
+ config,
11
+ onCleanupComplete
12
+ }) => {
13
+ const isVisible = instance.status === 'borrowed' && layout != null;
14
+ const prevStatusRef = useRef(instance.status);
15
+
16
+ // Track whether this slot has ever had a WebView rendered.
17
+ // On first borrow the WebView is created with a valid user source,
18
+ // avoiding the Fabric crash where didMoveToWindow fires before
19
+ // the source prop is applied (causing loadFileURL: with nil URL).
20
+ // After the first borrow, the WebView stays alive through
21
+ // cleaning → idle cycles.
22
+ const [hasWebView, setHasWebView] = useState(false);
23
+ useEffect(() => {
24
+ if (instance.status === 'borrowed' && !hasWebView) {
25
+ setHasWebView(true);
26
+ }
27
+ }, [instance.status, hasWebView]);
28
+
29
+ // When entering cleaning state, inject cleanup script then mark idle
30
+ useEffect(() => {
31
+ if (prevStatusRef.current !== 'cleaning' && instance.status === 'cleaning') {
32
+ const ref = instance.webViewRef.current;
33
+ if (ref) {
34
+ const script = config.customCleanupScript ?? CLEANUP_SCRIPT;
35
+ ref.injectJavaScript(script);
36
+ }
37
+ const timer = setTimeout(() => {
38
+ onCleanupComplete(instance.id);
39
+ }, 100);
40
+ return () => clearTimeout(timer);
41
+ }
42
+ prevStatusRef.current = instance.status;
43
+ }, [instance.status, instance.id, instance.webViewRef, config.customCleanupScript, onCleanupComplete]);
44
+ const containerStyle = useMemo(() => {
45
+ if (!isVisible || !layout) {
46
+ return HIDDEN_STYLE;
47
+ }
48
+ return {
49
+ position: 'absolute',
50
+ top: layout.top,
51
+ left: layout.left,
52
+ width: layout.width,
53
+ height: layout.height
54
+ };
55
+ }, [isVisible, layout]);
56
+ const handleNavigationStateChange = useCallback(navState => {
57
+ instanceProps?.onNavigationStateChange?.(navState);
58
+ }, [instanceProps]);
59
+ const source = useMemo(() => {
60
+ if (instance.status === 'borrowed' && instanceProps?.source) {
61
+ return instanceProps.source;
62
+ }
63
+ return BLANK_HTML_SOURCE;
64
+ }, [instance.status, instanceProps?.source]);
65
+
66
+ // Don't render WebView until the first borrow.
67
+ // This avoids the Fabric crash where didMoveToWindow → visitSource
68
+ // fires before _source prop is applied on the native side.
69
+ const shouldRenderWebView = hasWebView;
70
+ return /*#__PURE__*/React.createElement(View, {
71
+ style: containerStyle,
72
+ pointerEvents: isVisible ? 'auto' : 'none'
73
+ }, shouldRenderWebView && /*#__PURE__*/React.createElement(WebView, _extends({
74
+ ref: instance.webViewRef
75
+ }, instance.status === 'borrowed' ? instanceProps : undefined, {
76
+ source: source,
77
+ onNavigationStateChange: handleNavigationStateChange,
78
+ style: {
79
+ flex: 1
80
+ }
81
+ }, config.defaultWebViewProps || {})));
82
+ };
83
+ export default /*#__PURE__*/React.memo(WebViewSlot);
84
+ //# sourceMappingURL=WebViewSlot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","useCallback","useEffect","useMemo","useRef","useState","View","WebView","BLANK_HTML_SOURCE","CLEANUP_SCRIPT","HIDDEN_STYLE","WebViewSlot","instance","layout","instanceProps","config","onCleanupComplete","isVisible","status","prevStatusRef","hasWebView","setHasWebView","current","ref","webViewRef","script","customCleanupScript","injectJavaScript","timer","setTimeout","id","clearTimeout","containerStyle","position","top","left","width","height","handleNavigationStateChange","navState","onNavigationStateChange","source","shouldRenderWebView","createElement","style","pointerEvents","_extends","undefined","flex","defaultWebViewProps","memo"],"sourceRoot":"../../src","sources":["WebViewSlot.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,45 @@
1
+ export const DEFAULT_POOL_CONFIG = {
2
+ poolSize: 3,
3
+ cleanupOnReturn: true
4
+ };
5
+ export const HIDDEN_STYLE = {
6
+ position: 'absolute',
7
+ width: 1,
8
+ height: 1,
9
+ left: -9999,
10
+ top: -9999,
11
+ opacity: 0
12
+ };
13
+
14
+ // Blank HTML source used for idle/cleaning WebViews.
15
+ // Using { html } instead of { uri: 'about:blank' } because
16
+ // react-native-webview's native code may route 'about:blank'
17
+ // through loadFileURL: which throws NSInvalidArgumentException.
18
+ export const BLANK_HTML_SOURCE = {
19
+ html: ''
20
+ };
21
+
22
+ // Cleanup script injected into WebView when returning to pool.
23
+ // Resets scroll position, clears timers, and removes all body content.
24
+ // The body.innerHTML = '' is intentional — it clears the WebView DOM
25
+ // as part of the pool cleanup process (no user content involved).
26
+ export const CLEANUP_SCRIPT = `
27
+ (function() {
28
+ try {
29
+ window.scrollTo(0, 0);
30
+ var highestTimeoutId = setTimeout(function(){}, 0);
31
+ for (var i = 0; i < highestTimeoutId; i++) {
32
+ clearTimeout(i);
33
+ }
34
+ var highestIntervalId = setInterval(function(){}, 0);
35
+ for (var j = 0; j < highestIntervalId; j++) {
36
+ clearInterval(j);
37
+ }
38
+ if (document.body) {
39
+ document.body.innerHTML = '';
40
+ }
41
+ } catch(e) {}
42
+ true;
43
+ })();
44
+ `;
45
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["DEFAULT_POOL_CONFIG","poolSize","cleanupOnReturn","HIDDEN_STYLE","position","width","height","left","top","opacity","BLANK_HTML_SOURCE","html","CLEANUP_SCRIPT"],"sourceRoot":"../../src","sources":["constants.ts"],"mappings":"AAGA,OAAO,MAAMA,mBAA+B,GAAG;EAC7CC,QAAQ,EAAE,CAAC;EACXC,eAAe,EAAE;AACnB,CAAC;AAED,OAAO,MAAMC,YAAuB,GAAG;EACrCC,QAAQ,EAAE,UAAU;EACpBC,KAAK,EAAE,CAAC;EACRC,MAAM,EAAE,CAAC;EACTC,IAAI,EAAE,CAAC,IAAI;EACXC,GAAG,EAAE,CAAC,IAAI;EACVC,OAAO,EAAE;AACX,CAAC;;AAED;AACA;AACA;AACA;AACA,OAAO,MAAMC,iBAAiB,GAAG;EAAEC,IAAI,EAAE;AAAG,CAAU;;AAEtD;AACA;AACA;AACA;AACA,OAAO,MAAMC,cAAc,GAAG;AAC9B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC","ignoreList":[]}
@@ -0,0 +1,5 @@
1
+ export { WebViewPoolProvider, useWebViewPool } from './WebViewPoolProvider';
2
+ export { default as PooledWebView } from './PooledWebView';
3
+ export { usePooledWebView } from './usePooledWebView';
4
+ export { default as WebViewManager } from './WebViewManager';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["WebViewPoolProvider","useWebViewPool","default","PooledWebView","usePooledWebView","WebViewManager"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"AAAA,SAASA,mBAAmB,EAAEC,cAAc,QAAQ,uBAAuB;AAC3E,SAASC,OAAO,IAAIC,aAAa,QAAQ,iBAAiB;AAC1D,SAASC,gBAAgB,QAAQ,oBAAoB;AACrD,SAASF,OAAO,IAAIG,cAAc,QAAQ,kBAAkB","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../src","sources":["types.ts"],"mappings":"","ignoreList":[]}