@javascriptcommon/react-native-webview 13.19.0 → 13.19.1
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.
|
@@ -178,6 +178,7 @@ public class RNCWebView extends WebView implements LifecycleEventListener {
|
|
|
178
178
|
public static void enqueueBgScript(String script) {
|
|
179
179
|
RNCWebView v = EMBED_INSTANCE;
|
|
180
180
|
if (v != null && script != null) {
|
|
181
|
+
v.noteActivity();
|
|
181
182
|
v.pendingBgScripts.add(script);
|
|
182
183
|
v.bgInjectHandler.post(v.drainRunnable); // immediate drain (FIFO)
|
|
183
184
|
}
|
|
@@ -213,10 +214,39 @@ public class RNCWebView extends WebView implements LifecycleEventListener {
|
|
|
213
214
|
private static final long KEEP_ALIVE_INTERVAL_MS = 200;
|
|
214
215
|
private boolean keepAliveRunning = false;
|
|
215
216
|
|
|
217
|
+
// The tick only earns its keep while the page has something to do: a track
|
|
218
|
+
// playing (the page reports its position every second), loading, or being
|
|
219
|
+
// driven by the app. Paused, it ran on for as long as the process lived —
|
|
220
|
+
// five evaluations a second, each waking the renderer and the main thread,
|
|
221
|
+
// with the screen off, for nothing. So it stops after this long without any
|
|
222
|
+
// activity (a script from the app, a message from the page) and the next
|
|
223
|
+
// one starts it again, on the same main-thread handler and before that
|
|
224
|
+
// script is drained, so a play or a navigate never lands on a renderer the
|
|
225
|
+
// tick was supposed to be keeping awake.
|
|
226
|
+
private static final long KEEP_ALIVE_IDLE_MS = 60_000;
|
|
227
|
+
private volatile long lastActivityAt = 0;
|
|
228
|
+
|
|
229
|
+
private final Runnable resumeKeepAliveRunnable = new Runnable() {
|
|
230
|
+
@Override
|
|
231
|
+
public void run() { if (contentBlockerEnabled) startKeepAlive(); }
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
/** Something is happening on the embed page: keep (or start) the tick. Any thread. */
|
|
235
|
+
void noteActivity() {
|
|
236
|
+
lastActivityAt = android.os.SystemClock.elapsedRealtime();
|
|
237
|
+
if (contentBlockerEnabled && !keepAliveRunning) {
|
|
238
|
+
bgInjectHandler.postAtFrontOfQueue(resumeKeepAliveRunnable);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
216
242
|
private final Runnable keepAliveRunnable = new Runnable() {
|
|
217
243
|
@Override
|
|
218
244
|
public void run() {
|
|
219
245
|
if (!keepAliveRunning) return;
|
|
246
|
+
if (android.os.SystemClock.elapsedRealtime() - lastActivityAt > KEEP_ALIVE_IDLE_MS) {
|
|
247
|
+
stopKeepAlive();
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
220
250
|
// Throws once the WebView is destroyed; the flag above normally gets
|
|
221
251
|
// there first, but a destroy racing this tick must not take the app.
|
|
222
252
|
try { evaluateJavascript("1+1", null); } catch (Throwable ignored) { }
|
|
@@ -227,6 +257,7 @@ public class RNCWebView extends WebView implements LifecycleEventListener {
|
|
|
227
257
|
private void startKeepAlive() {
|
|
228
258
|
if (keepAliveRunning) return;
|
|
229
259
|
keepAliveRunning = true;
|
|
260
|
+
lastActivityAt = android.os.SystemClock.elapsedRealtime();
|
|
230
261
|
// Logged because there is no way to tell from outside whether the tick
|
|
231
262
|
// is running: it evaluates a script with no observable effect, which is
|
|
232
263
|
// the whole point of it. One line at each edge, never per tick.
|
|
@@ -457,6 +488,9 @@ public class RNCWebView extends WebView implements LifecycleEventListener {
|
|
|
457
488
|
}
|
|
458
489
|
|
|
459
490
|
protected void evaluateJavascriptWithFallback(String script) {
|
|
491
|
+
// The app driving the page (injectJavaScript, the frame-gated channel)
|
|
492
|
+
// is activity too; the keep-alive's own "1+1" does not come through here.
|
|
493
|
+
noteActivity();
|
|
460
494
|
evaluateJavascript(script, null);
|
|
461
495
|
}
|
|
462
496
|
|
|
@@ -486,6 +520,7 @@ public class RNCWebView extends WebView implements LifecycleEventListener {
|
|
|
486
520
|
}
|
|
487
521
|
|
|
488
522
|
public void onMessage(String message, String sourceUrl) {
|
|
523
|
+
noteActivity();
|
|
489
524
|
ThemedReactContext reactContext = getThemedReactContext();
|
|
490
525
|
RNCWebView mWebView = this;
|
|
491
526
|
|
|
@@ -576,6 +611,10 @@ public class RNCWebView extends WebView implements LifecycleEventListener {
|
|
|
576
611
|
}
|
|
577
612
|
|
|
578
613
|
protected void cleanupCallbacksAndDestroy() {
|
|
614
|
+
// A message from the page racing the teardown must not start the tick
|
|
615
|
+
// again on a destroyed view (noteActivity is gated on this flag).
|
|
616
|
+
contentBlockerEnabled = false;
|
|
617
|
+
bgInjectHandler.removeCallbacks(resumeKeepAliveRunnable);
|
|
579
618
|
stopKeepAlive();
|
|
580
619
|
bgInjectHandler.removeCallbacks(drainRunnable);
|
|
581
620
|
if (EMBED_INSTANCE == this) EMBED_INSTANCE = null;
|
package/apple/RNCWebViewImpl.m
CHANGED
|
@@ -315,6 +315,7 @@ RCTAutoInsetsProtocol>
|
|
|
315
315
|
|
|
316
316
|
- (void)dealloc
|
|
317
317
|
{
|
|
318
|
+
[self stopKeepWebViewActiveTimer];
|
|
318
319
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
319
320
|
if (@available(iOS 11.0, *)) {
|
|
320
321
|
[self.webView.configuration.websiteDataStore.httpCookieStore removeObserver:self];
|
|
@@ -548,6 +549,35 @@ RCTAutoInsetsProtocol>
|
|
|
548
549
|
}
|
|
549
550
|
}
|
|
550
551
|
|
|
552
|
+
// The keep-alive tick belongs to one WKWebView. It used to be created with
|
|
553
|
+
// `target:self` and never invalidated: a scheduled NSTimer retains its target,
|
|
554
|
+
// so destroyWebView (Fabric's prepareForRecycle) left it firing 5 times a
|
|
555
|
+
// second for the rest of the process, kept this view alive with it, and a
|
|
556
|
+
// recycled view that built a new WKWebView started a second one next to it.
|
|
557
|
+
// Every WebView the app ever mounted (the embed engine, each rebuilt
|
|
558
|
+
// extraction page, sign-in and import pages) added a tick that never stopped.
|
|
559
|
+
// Now the timer holds the view weakly, there is at most one per view, and it
|
|
560
|
+
// ends with the WKWebView it keeps alive.
|
|
561
|
+
- (void)startKeepWebViewActiveTimer {
|
|
562
|
+
[self stopKeepWebViewActiveTimer];
|
|
563
|
+
__weak RNCWebViewImpl *weakSelf = self;
|
|
564
|
+
self.keepWebViewActiveTimer = [NSTimer scheduledTimerWithTimeInterval:0.2
|
|
565
|
+
repeats:YES
|
|
566
|
+
block:^(NSTimer *timer) {
|
|
567
|
+
RNCWebViewImpl *strongSelf = weakSelf;
|
|
568
|
+
if (strongSelf == nil) {
|
|
569
|
+
[timer invalidate];
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
[strongSelf _keepWKWebViewActive:timer];
|
|
573
|
+
}];
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
- (void)stopKeepWebViewActiveTimer {
|
|
577
|
+
[self.keepWebViewActiveTimer invalidate];
|
|
578
|
+
self.keepWebViewActiveTimer = nil;
|
|
579
|
+
}
|
|
580
|
+
|
|
551
581
|
- (void)didMoveToWindow
|
|
552
582
|
{
|
|
553
583
|
if (self.window != nil && _webView == nil) {
|
|
@@ -612,11 +642,7 @@ RCTAutoInsetsProtocol>
|
|
|
612
642
|
[self setKeyboardDisplayRequiresUserAction: _savedKeyboardDisplayRequiresUserAction];
|
|
613
643
|
[self visitSource];
|
|
614
644
|
|
|
615
|
-
self
|
|
616
|
-
target:self
|
|
617
|
-
selector:@selector(_keepWKWebViewActive:)
|
|
618
|
-
userInfo:nil
|
|
619
|
-
repeats:YES];
|
|
645
|
+
[self startKeepWebViewActiveTimer];
|
|
620
646
|
}
|
|
621
647
|
|
|
622
648
|
#if !TARGET_OS_OSX
|
|
@@ -655,6 +681,7 @@ RCTAutoInsetsProtocol>
|
|
|
655
681
|
- (void)removeFromSuperview
|
|
656
682
|
#endif
|
|
657
683
|
{
|
|
684
|
+
[self stopKeepWebViewActiveTimer];
|
|
658
685
|
if (_webView) {
|
|
659
686
|
[_webView.configuration.userContentController removeScriptMessageHandlerForName:HistoryShimName];
|
|
660
687
|
[_webView.configuration.userContentController removeScriptMessageHandlerForName:MessageHandlerName];
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"Thibault Malbranche <malbranche.thibault@gmail.com>"
|
|
11
11
|
],
|
|
12
12
|
"license": "MIT",
|
|
13
|
-
"version": "13.19.
|
|
13
|
+
"version": "13.19.1",
|
|
14
14
|
"homepage": "https://github.com/react-native-webview/react-native-webview#readme",
|
|
15
15
|
"scripts": {
|
|
16
16
|
"android": "react-native run-android",
|