@lingxia/bridge 0.9.0 → 0.11.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.
- package/dist/bridge-runtime.es2020.js +1 -1
- package/dist/bridge-runtime.es5.js +1 -1
- package/dist/es2020/bridge.js +225 -24
- package/dist/es2020/index.js +1 -0
- package/dist/es2020/runtime-env.js +31 -1
- package/dist/es2020/ui/action-sheet.js +2 -2
- package/dist/es5/bridge.js +274 -62
- package/dist/es5/index.js +1 -0
- package/dist/es5/runtime-env.js +32 -1
- package/dist/es5/ui/action-sheet.js +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/runtime-env.d.ts +6 -1
- package/dist/types.d.ts +8 -1
- package/package.json +2 -2
package/dist/es5/bridge.js
CHANGED
|
@@ -84,7 +84,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
84
84
|
import { BRIDGE_ERROR } from "./types";
|
|
85
85
|
import { toBridgeError, toNativeError } from "./invocation";
|
|
86
86
|
import { installNativeComponentCoverageMonitor } from "./nativecomponents/coverage-monitor";
|
|
87
|
-
import { BRIDGE_CONFIG, getCommunicationMethod, getPlatformOS, isAndroid, isHarmony, isIOS, isMacOS, isDesktop, } from "./runtime-env";
|
|
87
|
+
import { BRIDGE_CONFIG, getCommunicationMethod, getPlatformOS, isAndroid, isHarmony, isIOS, isMacOS, isWindows, isDesktop, isApple, isDevSession, isRunner, } from "./runtime-env";
|
|
88
88
|
var NATIVE_HANDLER_NAME = "LingXia";
|
|
89
89
|
var GLOBAL_RECEIVER_NAME = "__LingXiaRecvMessage";
|
|
90
90
|
var DEFAULT_TIMEOUT_MS = 5000;
|
|
@@ -93,6 +93,7 @@ var HANDSHAKE_MAX_RETRIES = 3;
|
|
|
93
93
|
var LOG_PREFIX = "[LX.Bridge]";
|
|
94
94
|
var MESSAGE_PORT_TYPE = "messageport";
|
|
95
95
|
var JS_INTERFACE_TYPE = "jsinterface";
|
|
96
|
+
var WEB_MESSAGE_TYPE = "webmessage";
|
|
96
97
|
var OUTBOX_LIMIT = 256;
|
|
97
98
|
var APPLE_DOWNSTREAM_URL = BRIDGE_CONFIG.appleDownstreamURL;
|
|
98
99
|
var APPLE_RECONNECT_BASE_MS = 200;
|
|
@@ -158,11 +159,22 @@ function activateReceiver(receiver) {
|
|
|
158
159
|
function isDebugEnabled(flag) {
|
|
159
160
|
return debugFlags.all || debugFlags[flag];
|
|
160
161
|
}
|
|
162
|
+
// `log` is the bridge's own protocol/lifecycle trace. Native log capture
|
|
163
|
+
// forwards whatever the page emits to `console`, so the bridge itself decides
|
|
164
|
+
// whether to surface this framework chatter: only in a `lingxia dev` session
|
|
165
|
+
// (or when a debug flag is set). Shipped apps stay quiet, leaving the captured
|
|
166
|
+
// stream to the page's own output plus bridge warnings/errors.
|
|
161
167
|
function log() {
|
|
162
168
|
var args = [];
|
|
163
169
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
164
170
|
args[_i] = arguments[_i];
|
|
165
171
|
}
|
|
172
|
+
if (!isDevSession() &&
|
|
173
|
+
!debugFlags.all &&
|
|
174
|
+
!debugFlags.proto &&
|
|
175
|
+
!debugFlags.data) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
166
178
|
console.log.apply(console, __spreadArray([LOG_PREFIX], __read(args), false));
|
|
167
179
|
}
|
|
168
180
|
function warn() {
|
|
@@ -217,6 +229,17 @@ var appleDownstreamTask = null;
|
|
|
217
229
|
var appleDownstreamAbortController = null;
|
|
218
230
|
var appleReconnectTimer = null;
|
|
219
231
|
var appleReconnectDelayMs = APPLE_RECONNECT_BASE_MS;
|
|
232
|
+
var appleDownstreamDisposed = false;
|
|
233
|
+
// Highest transport frame seq processed. Sent as `?from=` on reconnect so the
|
|
234
|
+
// host replays the gap; survives reconnects so a WebKit-replaced stream resumes
|
|
235
|
+
// without losing frames or tearing down the bridge session.
|
|
236
|
+
var appleLastFrameSeq = 0;
|
|
237
|
+
// Liveness tracking: the host heartbeats an idle connection, so a gap longer
|
|
238
|
+
// than a couple of heartbeats means the connection is silently dead and we
|
|
239
|
+
// reconnect proactively instead of waiting for a read error that may never come.
|
|
240
|
+
var APPLE_DOWNSTREAM_STALE_MS = 35000;
|
|
241
|
+
var appleLastFrameAt = 0;
|
|
242
|
+
var appleWatchdogTimer = null;
|
|
220
243
|
var portInitState = {
|
|
221
244
|
listenerInstalled: false,
|
|
222
245
|
promise: null,
|
|
@@ -261,6 +284,23 @@ function clearAppleReconnectTimer() {
|
|
|
261
284
|
appleReconnectTimer = null;
|
|
262
285
|
}
|
|
263
286
|
}
|
|
287
|
+
function disposeAppleDownstream(reason) {
|
|
288
|
+
if (!useAppleDownstreamTransport() || appleDownstreamDisposed)
|
|
289
|
+
return;
|
|
290
|
+
appleDownstreamDisposed = true;
|
|
291
|
+
clearAppleReconnectTimer();
|
|
292
|
+
if (appleWatchdogTimer !== null) {
|
|
293
|
+
clearInterval(appleWatchdogTimer);
|
|
294
|
+
appleWatchdogTimer = null;
|
|
295
|
+
}
|
|
296
|
+
if (typeof document !== "undefined") {
|
|
297
|
+
document.removeEventListener("visibilitychange", handleAppleVisibilityChange);
|
|
298
|
+
}
|
|
299
|
+
appleForcedReconnectPending = false;
|
|
300
|
+
appleDownstreamAbortController === null || appleDownstreamAbortController === void 0 ? void 0 : appleDownstreamAbortController.abort();
|
|
301
|
+
appleDownstreamConnected = false;
|
|
302
|
+
resetHandshakeState(reason, true);
|
|
303
|
+
}
|
|
264
304
|
function closeActiveChannelsFromTransport(reason) {
|
|
265
305
|
var e_2, _a;
|
|
266
306
|
try {
|
|
@@ -334,7 +374,7 @@ function processAppleDownstreamBuffer(buffer) {
|
|
|
334
374
|
if (!line)
|
|
335
375
|
continue;
|
|
336
376
|
try {
|
|
337
|
-
|
|
377
|
+
handleAppleDownstreamFrame(JSON.parse(line));
|
|
338
378
|
}
|
|
339
379
|
catch (e) {
|
|
340
380
|
warn("Apple downstream parse error:", e, line);
|
|
@@ -342,9 +382,42 @@ function processAppleDownstreamBuffer(buffer) {
|
|
|
342
382
|
}
|
|
343
383
|
return remaining;
|
|
344
384
|
}
|
|
385
|
+
// Unwrap the transport envelope: {"lxff":seq,"m":<message>} carries a business
|
|
386
|
+
// message with its frame seq; {"lxreset":true} means the host cannot replay our
|
|
387
|
+
// resume point and we must re-handshake.
|
|
388
|
+
function handleAppleDownstreamFrame(frame) {
|
|
389
|
+
if (!frame || typeof frame !== "object")
|
|
390
|
+
return;
|
|
391
|
+
// Any frame — data, heartbeat, or reset — proves the connection is alive.
|
|
392
|
+
appleLastFrameAt = Date.now();
|
|
393
|
+
var record = frame;
|
|
394
|
+
if (record.lxshutdown === true) {
|
|
395
|
+
disposeAppleDownstream("Apple downstream closed");
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
if (record.lxhb !== undefined)
|
|
399
|
+
return; // heartbeat: liveness only, nothing to dispatch
|
|
400
|
+
if (record.lxreset === true) {
|
|
401
|
+
appleLastFrameSeq = 0;
|
|
402
|
+
resetHandshakeState("Apple downstream reset", true);
|
|
403
|
+
startHandshake();
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
if (typeof record.lxff === "number") {
|
|
407
|
+
// Replayed frames after a reconnect can repeat the last-seen seq; ignore
|
|
408
|
+
// anything we have already processed so the session is not double-fed.
|
|
409
|
+
if (record.lxff <= appleLastFrameSeq)
|
|
410
|
+
return;
|
|
411
|
+
appleLastFrameSeq = record.lxff;
|
|
412
|
+
handleIncomingMessage(record.m);
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
// Legacy/un-enveloped line (e.g. a bare keepalive); pass through.
|
|
416
|
+
handleIncomingMessage(frame);
|
|
417
|
+
}
|
|
345
418
|
function runAppleDownstream() {
|
|
346
419
|
return __awaiter(this, void 0, void 0, function () {
|
|
347
|
-
var controller, response, reader, decoder, buffered, _a, value, done, tail, e_5;
|
|
420
|
+
var controller, separator, url, response, reader, decoder, buffered, _a, value, done, tail, e_5;
|
|
348
421
|
return __generator(this, function (_b) {
|
|
349
422
|
switch (_b.label) {
|
|
350
423
|
case 0:
|
|
@@ -353,7 +426,9 @@ function runAppleDownstream() {
|
|
|
353
426
|
}
|
|
354
427
|
controller = new AbortController();
|
|
355
428
|
appleDownstreamAbortController = controller;
|
|
356
|
-
|
|
429
|
+
separator = APPLE_DOWNSTREAM_URL.includes("?") ? "&" : "?";
|
|
430
|
+
url = "".concat(APPLE_DOWNSTREAM_URL).concat(separator, "from=").concat(appleLastFrameSeq);
|
|
431
|
+
return [4 /*yield*/, fetch(url, {
|
|
357
432
|
method: "GET",
|
|
358
433
|
cache: "no-store",
|
|
359
434
|
headers: { Accept: "application/x-ndjson" },
|
|
@@ -364,11 +439,16 @@ function runAppleDownstream() {
|
|
|
364
439
|
if (!response.ok) {
|
|
365
440
|
throw new Error("Apple downstream HTTP ".concat(response.status));
|
|
366
441
|
}
|
|
442
|
+
if (response.headers.get("X-LingXia-Bridge-Shutdown") === "1") {
|
|
443
|
+
disposeAppleDownstream("Apple downstream closed");
|
|
444
|
+
return [2 /*return*/];
|
|
445
|
+
}
|
|
367
446
|
if (!response.body) {
|
|
368
447
|
throw new Error("Apple downstream response body unavailable");
|
|
369
448
|
}
|
|
370
449
|
appleDownstreamConnected = true;
|
|
371
450
|
appleReconnectDelayMs = APPLE_RECONNECT_BASE_MS;
|
|
451
|
+
appleLastFrameAt = Date.now();
|
|
372
452
|
if (isDebugEnabled("proto"))
|
|
373
453
|
log("Apple downstream connected");
|
|
374
454
|
startHandshake();
|
|
@@ -394,7 +474,7 @@ function runAppleDownstream() {
|
|
|
394
474
|
tail = buffered.trim();
|
|
395
475
|
if (tail) {
|
|
396
476
|
try {
|
|
397
|
-
|
|
477
|
+
handleAppleDownstreamFrame(JSON.parse(tail));
|
|
398
478
|
}
|
|
399
479
|
catch (e) {
|
|
400
480
|
warn("Apple downstream trailing parse error:", e, tail);
|
|
@@ -417,13 +497,18 @@ function runAppleDownstream() {
|
|
|
417
497
|
});
|
|
418
498
|
});
|
|
419
499
|
}
|
|
420
|
-
function scheduleAppleDownstreamReconnect(reason) {
|
|
421
|
-
if (
|
|
500
|
+
function scheduleAppleDownstreamReconnect(reason, immediate) {
|
|
501
|
+
if (immediate === void 0) { immediate = false; }
|
|
502
|
+
if (!useAppleDownstreamTransport() || appleDownstreamDisposed)
|
|
422
503
|
return;
|
|
423
504
|
clearAppleReconnectTimer();
|
|
424
|
-
var delay = appleReconnectDelayMs;
|
|
425
|
-
|
|
426
|
-
|
|
505
|
+
var delay = immediate ? 0 : appleReconnectDelayMs;
|
|
506
|
+
if (!immediate) {
|
|
507
|
+
appleReconnectDelayMs = Math.min(appleReconnectDelayMs * 2, APPLE_RECONNECT_MAX_MS);
|
|
508
|
+
}
|
|
509
|
+
var message = immediate
|
|
510
|
+
? "Apple downstream completed, reconnecting immediately: ".concat(reason)
|
|
511
|
+
: "Apple downstream disconnected, retrying in ".concat(delay, "ms: ").concat(reason);
|
|
427
512
|
if (delay <= APPLE_RECONNECT_BASE_MS) {
|
|
428
513
|
log(message);
|
|
429
514
|
}
|
|
@@ -436,12 +521,16 @@ function scheduleAppleDownstreamReconnect(reason) {
|
|
|
436
521
|
}, delay);
|
|
437
522
|
}
|
|
438
523
|
function ensureAppleDownstream() {
|
|
439
|
-
if (!useAppleDownstreamTransport())
|
|
524
|
+
if (!useAppleDownstreamTransport() || appleDownstreamDisposed)
|
|
440
525
|
return;
|
|
441
526
|
if (appleDownstreamTask)
|
|
442
527
|
return;
|
|
443
528
|
clearAppleReconnectTimer();
|
|
529
|
+
var completedCleanly = false;
|
|
444
530
|
appleDownstreamTask = runAppleDownstream()
|
|
531
|
+
.then(function () {
|
|
532
|
+
completedCleanly = true;
|
|
533
|
+
})
|
|
445
534
|
.catch(function (e) {
|
|
446
535
|
if (appleDownstreamAbortController === null || appleDownstreamAbortController === void 0 ? void 0 : appleDownstreamAbortController.signal.aborted)
|
|
447
536
|
return;
|
|
@@ -452,13 +541,72 @@ function ensureAppleDownstream() {
|
|
|
452
541
|
var aborted = (_a = appleDownstreamAbortController === null || appleDownstreamAbortController === void 0 ? void 0 : appleDownstreamAbortController.signal.aborted) !== null && _a !== void 0 ? _a : false;
|
|
453
542
|
appleDownstreamTask = null;
|
|
454
543
|
appleDownstreamAbortController = null;
|
|
455
|
-
var wasConnected = appleDownstreamConnected;
|
|
456
544
|
appleDownstreamConnected = false;
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
545
|
+
// A dropped transport is not a dead session: reconnect resumes from the
|
|
546
|
+
// last seq and the host replays the gap, so the handshake and in-flight
|
|
547
|
+
// streams stay intact. Only a host-sent reset (handled on the frame path)
|
|
548
|
+
// or a real abort tears things down.
|
|
549
|
+
if (!aborted && !appleDownstreamDisposed) {
|
|
550
|
+
// Native intentionally completes bootstrap/replay responses to flush
|
|
551
|
+
// WebKit. Reconnect without the failure backoff so a live stream can
|
|
552
|
+
// catch up and settle onto a long-lived downstream.
|
|
553
|
+
scheduleAppleDownstreamReconnect("stream closed", completedCleanly);
|
|
554
|
+
}
|
|
460
555
|
});
|
|
461
556
|
}
|
|
557
|
+
// Drop the current downstream and reconnect, exactly as WebKit does when it
|
|
558
|
+
// replaces the streaming fetch. The reconnect carries the real `from=<lastSeq>`,
|
|
559
|
+
// so nothing is lost. Driven by the staleness watchdog and the foreground
|
|
560
|
+
// handler, and exposed as a dev hook for repro harnesses. A no-op off Apple.
|
|
561
|
+
var appleForcedReconnectPending = false;
|
|
562
|
+
function forceDownstreamReconnect() {
|
|
563
|
+
if (!useAppleDownstreamTransport() || appleDownstreamDisposed)
|
|
564
|
+
return;
|
|
565
|
+
// Coalesce a burst of triggers (rapid foreground toggles, repeated calls)
|
|
566
|
+
// into a single reconnect so they cannot stack concurrent fetches.
|
|
567
|
+
if (appleForcedReconnectPending)
|
|
568
|
+
return;
|
|
569
|
+
appleForcedReconnectPending = true;
|
|
570
|
+
var task = appleDownstreamTask;
|
|
571
|
+
appleDownstreamAbortController === null || appleDownstreamAbortController === void 0 ? void 0 : appleDownstreamAbortController.abort();
|
|
572
|
+
var reconnect = function () {
|
|
573
|
+
appleForcedReconnectPending = false;
|
|
574
|
+
ensureAppleDownstream();
|
|
575
|
+
};
|
|
576
|
+
if (task)
|
|
577
|
+
task.finally(reconnect);
|
|
578
|
+
else
|
|
579
|
+
reconnect();
|
|
580
|
+
}
|
|
581
|
+
// A silently dead connection (half-open socket) never surfaces a read error, so
|
|
582
|
+
// poll for heartbeat staleness and reconnect when the host has gone quiet.
|
|
583
|
+
function startAppleWatchdog() {
|
|
584
|
+
if (!useAppleDownstreamTransport() ||
|
|
585
|
+
appleDownstreamDisposed ||
|
|
586
|
+
appleWatchdogTimer !== null)
|
|
587
|
+
return;
|
|
588
|
+
appleWatchdogTimer = setInterval(function () {
|
|
589
|
+
// No `connected` guard: a reconnect that hung before delivering a frame
|
|
590
|
+
// also goes stale, and forcing a reconnect aborts and retries it.
|
|
591
|
+
if (appleLastFrameAt === 0)
|
|
592
|
+
return;
|
|
593
|
+
if (Date.now() - appleLastFrameAt > APPLE_DOWNSTREAM_STALE_MS) {
|
|
594
|
+
warn("Apple downstream stale (no heartbeat), forcing reconnect");
|
|
595
|
+
forceDownstreamReconnect();
|
|
596
|
+
}
|
|
597
|
+
}, 5000);
|
|
598
|
+
}
|
|
599
|
+
// WebKit suspends/throttles a backgrounded webview and may tear the stream
|
|
600
|
+
// down; reconnect the moment it returns so the UI is never left stale.
|
|
601
|
+
function handleAppleVisibilityChange() {
|
|
602
|
+
if (document.visibilityState === "visible")
|
|
603
|
+
forceDownstreamReconnect();
|
|
604
|
+
}
|
|
605
|
+
function installAppleForegroundReconnect() {
|
|
606
|
+
if (!useAppleDownstreamTransport() || typeof document === "undefined")
|
|
607
|
+
return;
|
|
608
|
+
document.addEventListener("visibilitychange", handleAppleVisibilityChange);
|
|
609
|
+
}
|
|
462
610
|
function getMessagePort() {
|
|
463
611
|
var _a, _b;
|
|
464
612
|
if (messagePort)
|
|
@@ -506,7 +654,8 @@ function postToNative(message) {
|
|
|
506
654
|
messagePort.postMessage(messageString);
|
|
507
655
|
return;
|
|
508
656
|
}
|
|
509
|
-
if (communicationMethod === JS_INTERFACE_TYPE
|
|
657
|
+
if ((communicationMethod === JS_INTERFACE_TYPE ||
|
|
658
|
+
communicationMethod === WEB_MESSAGE_TYPE) &&
|
|
510
659
|
((_c = window.LingXiaProxy) === null || _c === void 0 ? void 0 : _c.postMessage)) {
|
|
511
660
|
window.LingXiaProxy.postMessage(messageString);
|
|
512
661
|
return;
|
|
@@ -540,6 +689,9 @@ function createStreamHandle(id, cancelFn) {
|
|
|
540
689
|
var _a;
|
|
541
690
|
var listeners = createListenerBuckets();
|
|
542
691
|
var done = false;
|
|
692
|
+
// Only buffer for the async iterator; long-lived streams consumed via
|
|
693
|
+
// .on("data") would otherwise accumulate payloads forever.
|
|
694
|
+
var iteratorRequested = false;
|
|
543
695
|
var resolveResult = function () { };
|
|
544
696
|
var rejectResult = function () { };
|
|
545
697
|
var pendingData = [];
|
|
@@ -562,6 +714,7 @@ function createStreamHandle(id, cancelFn) {
|
|
|
562
714
|
}
|
|
563
715
|
},
|
|
564
716
|
_a[Symbol.asyncIterator] = function () {
|
|
717
|
+
iteratorRequested = true;
|
|
565
718
|
return {
|
|
566
719
|
next: function () {
|
|
567
720
|
if (pendingData.length > 0) {
|
|
@@ -591,7 +744,7 @@ function createStreamHandle(id, cancelFn) {
|
|
|
591
744
|
if (pendingReads.length > 0) {
|
|
592
745
|
pendingReads.shift().resolve({ done: false, value: payload });
|
|
593
746
|
}
|
|
594
|
-
else {
|
|
747
|
+
else if (iteratorRequested) {
|
|
595
748
|
pendingData.push(payload);
|
|
596
749
|
}
|
|
597
750
|
try {
|
|
@@ -678,6 +831,9 @@ function createChannel(id, sendFn, closeFn) {
|
|
|
678
831
|
var open = false;
|
|
679
832
|
var outboundSeq = 0;
|
|
680
833
|
var closed = false;
|
|
834
|
+
// Only buffer for the async iterator or pre-first-listener replay;
|
|
835
|
+
// otherwise a listener-driven channel would accumulate payloads forever.
|
|
836
|
+
var iteratorRequested = false;
|
|
681
837
|
var pendingData = [];
|
|
682
838
|
var pendingReads = [];
|
|
683
839
|
var channel = (_a = {
|
|
@@ -693,8 +849,35 @@ function createChannel(id, sendFn, closeFn) {
|
|
|
693
849
|
sendFn(payload, outboundSeq++);
|
|
694
850
|
},
|
|
695
851
|
on: function (event, listener) {
|
|
696
|
-
|
|
852
|
+
var e_9, _a;
|
|
853
|
+
if (event === "data") {
|
|
697
854
|
listeners.data.add(listener);
|
|
855
|
+
// Flush data buffered before this listener attached. The host can send
|
|
856
|
+
// ch.data immediately after the open ack, before the consumer (e.g. a
|
|
857
|
+
// wrapped channel's onMessage) attaches its listener; without this those
|
|
858
|
+
// early events would sit in pendingData and never reach the listener.
|
|
859
|
+
if (pendingData.length > 0) {
|
|
860
|
+
var buffered = pendingData.splice(0);
|
|
861
|
+
try {
|
|
862
|
+
for (var buffered_1 = __values(buffered), buffered_1_1 = buffered_1.next(); !buffered_1_1.done; buffered_1_1 = buffered_1.next()) {
|
|
863
|
+
var payload = buffered_1_1.value;
|
|
864
|
+
try {
|
|
865
|
+
listener(payload);
|
|
866
|
+
}
|
|
867
|
+
catch (e) {
|
|
868
|
+
warn("Channel listener failed:", e);
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
catch (e_9_1) { e_9 = { error: e_9_1 }; }
|
|
873
|
+
finally {
|
|
874
|
+
try {
|
|
875
|
+
if (buffered_1_1 && !buffered_1_1.done && (_a = buffered_1.return)) _a.call(buffered_1);
|
|
876
|
+
}
|
|
877
|
+
finally { if (e_9) throw e_9.error; }
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
}
|
|
698
881
|
if (event === "close")
|
|
699
882
|
listeners.close.add(listener);
|
|
700
883
|
if (event === "error")
|
|
@@ -703,6 +886,7 @@ function createChannel(id, sendFn, closeFn) {
|
|
|
703
886
|
}
|
|
704
887
|
},
|
|
705
888
|
_a[Symbol.asyncIterator] = function () {
|
|
889
|
+
iteratorRequested = true;
|
|
706
890
|
return {
|
|
707
891
|
next: function () {
|
|
708
892
|
if (pendingData.length > 0) {
|
|
@@ -729,13 +913,13 @@ function createChannel(id, sendFn, closeFn) {
|
|
|
729
913
|
channel._emitClose(code, reason);
|
|
730
914
|
},
|
|
731
915
|
_a._emitData = function (payload) {
|
|
732
|
-
var
|
|
916
|
+
var e_10, _a;
|
|
733
917
|
if (!open)
|
|
734
918
|
return;
|
|
735
919
|
if (pendingReads.length > 0) {
|
|
736
920
|
pendingReads.shift().resolve({ done: false, value: payload });
|
|
737
921
|
}
|
|
738
|
-
else {
|
|
922
|
+
else if (iteratorRequested || listeners.data.size === 0) {
|
|
739
923
|
pendingData.push(payload);
|
|
740
924
|
}
|
|
741
925
|
try {
|
|
@@ -749,16 +933,16 @@ function createChannel(id, sendFn, closeFn) {
|
|
|
749
933
|
}
|
|
750
934
|
}
|
|
751
935
|
}
|
|
752
|
-
catch (
|
|
936
|
+
catch (e_10_1) { e_10 = { error: e_10_1 }; }
|
|
753
937
|
finally {
|
|
754
938
|
try {
|
|
755
939
|
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
756
940
|
}
|
|
757
|
-
finally { if (
|
|
941
|
+
finally { if (e_10) throw e_10.error; }
|
|
758
942
|
}
|
|
759
943
|
},
|
|
760
944
|
_a._emitClose = function (code, reason) {
|
|
761
|
-
var
|
|
945
|
+
var e_11, _a;
|
|
762
946
|
closed = true;
|
|
763
947
|
while (pendingReads.length > 0) {
|
|
764
948
|
pendingReads.shift().resolve({ done: true, value: undefined });
|
|
@@ -774,16 +958,16 @@ function createChannel(id, sendFn, closeFn) {
|
|
|
774
958
|
}
|
|
775
959
|
}
|
|
776
960
|
}
|
|
777
|
-
catch (
|
|
961
|
+
catch (e_11_1) { e_11 = { error: e_11_1 }; }
|
|
778
962
|
finally {
|
|
779
963
|
try {
|
|
780
964
|
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
781
965
|
}
|
|
782
|
-
finally { if (
|
|
966
|
+
finally { if (e_11) throw e_11.error; }
|
|
783
967
|
}
|
|
784
968
|
},
|
|
785
969
|
_a._reject = function (err) {
|
|
786
|
-
var
|
|
970
|
+
var e_12, _a;
|
|
787
971
|
closed = true;
|
|
788
972
|
while (pendingReads.length > 0) {
|
|
789
973
|
pendingReads.shift().reject(err);
|
|
@@ -799,12 +983,12 @@ function createChannel(id, sendFn, closeFn) {
|
|
|
799
983
|
}
|
|
800
984
|
}
|
|
801
985
|
}
|
|
802
|
-
catch (
|
|
986
|
+
catch (e_12_1) { e_12 = { error: e_12_1 }; }
|
|
803
987
|
finally {
|
|
804
988
|
try {
|
|
805
989
|
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
806
990
|
}
|
|
807
|
-
finally { if (
|
|
991
|
+
finally { if (e_12) throw e_12.error; }
|
|
808
992
|
}
|
|
809
993
|
},
|
|
810
994
|
_a._markOpen = function () {
|
|
@@ -851,10 +1035,19 @@ function isTransportReady() {
|
|
|
851
1035
|
if (useAppleDownstreamTransport())
|
|
852
1036
|
return appleDownstreamConnected;
|
|
853
1037
|
return (communicationMethod === "webkit" ||
|
|
854
|
-
communicationMethod === JS_INTERFACE_TYPE
|
|
1038
|
+
communicationMethod === JS_INTERFACE_TYPE ||
|
|
1039
|
+
communicationMethod === WEB_MESSAGE_TYPE);
|
|
855
1040
|
}
|
|
856
1041
|
function canSendAppMessages() {
|
|
857
|
-
|
|
1042
|
+
if (!handshakeDone)
|
|
1043
|
+
return false;
|
|
1044
|
+
// Apple upstream posts through WKScriptMessageHandler independently of the
|
|
1045
|
+
// downstream fetch. During a replay reconnect, native retains responses by
|
|
1046
|
+
// sequence, so treating that short gap as an unsendable session can strand
|
|
1047
|
+
// requests in the outbox with no second `ready` event to flush them.
|
|
1048
|
+
if (useAppleDownstreamTransport())
|
|
1049
|
+
return true;
|
|
1050
|
+
return isTransportReady();
|
|
858
1051
|
}
|
|
859
1052
|
function rejectPendingRequest(reqId, err) {
|
|
860
1053
|
var _a;
|
|
@@ -1000,7 +1193,7 @@ function startHandshake() {
|
|
|
1000
1193
|
helloSent = true;
|
|
1001
1194
|
postToNative(hello);
|
|
1002
1195
|
handshakeTimer = setTimeout(function () {
|
|
1003
|
-
var
|
|
1196
|
+
var e_13, _a;
|
|
1004
1197
|
if (handshakeDone)
|
|
1005
1198
|
return;
|
|
1006
1199
|
handshakeRetryCount++;
|
|
@@ -1032,12 +1225,12 @@ function startHandshake() {
|
|
|
1032
1225
|
});
|
|
1033
1226
|
}
|
|
1034
1227
|
}
|
|
1035
|
-
catch (
|
|
1228
|
+
catch (e_13_1) { e_13 = { error: e_13_1 }; }
|
|
1036
1229
|
finally {
|
|
1037
1230
|
try {
|
|
1038
1231
|
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
1039
1232
|
}
|
|
1040
|
-
finally { if (
|
|
1233
|
+
finally { if (e_13) throw e_13.error; }
|
|
1041
1234
|
}
|
|
1042
1235
|
}
|
|
1043
1236
|
}, HANDSHAKE_TIMEOUT_MS);
|
|
@@ -1088,7 +1281,7 @@ function getContainerAndKey(root, pointer, autoCreate) {
|
|
|
1088
1281
|
return { container: current, key: segments[segments.length - 1] };
|
|
1089
1282
|
}
|
|
1090
1283
|
function applyJsonPatch(target, ops) {
|
|
1091
|
-
var
|
|
1284
|
+
var e_14, _a, e_15, _b;
|
|
1092
1285
|
try {
|
|
1093
1286
|
for (var ops_1 = __values(ops), ops_1_1 = ops_1.next(); !ops_1_1.done; ops_1_1 = ops_1.next()) {
|
|
1094
1287
|
var op = ops_1_1.value;
|
|
@@ -1096,17 +1289,17 @@ function applyJsonPatch(target, ops) {
|
|
|
1096
1289
|
var _c = getContainerAndKey(target, op.path, autoCreate), container = _c.container, key = _c.key;
|
|
1097
1290
|
if (key === "$root") {
|
|
1098
1291
|
try {
|
|
1099
|
-
for (var _d = (
|
|
1292
|
+
for (var _d = (e_15 = void 0, __values(Object.keys(target))), _e = _d.next(); !_e.done; _e = _d.next()) {
|
|
1100
1293
|
var k = _e.value;
|
|
1101
1294
|
delete target[k];
|
|
1102
1295
|
}
|
|
1103
1296
|
}
|
|
1104
|
-
catch (
|
|
1297
|
+
catch (e_15_1) { e_15 = { error: e_15_1 }; }
|
|
1105
1298
|
finally {
|
|
1106
1299
|
try {
|
|
1107
1300
|
if (_e && !_e.done && (_b = _d.return)) _b.call(_d);
|
|
1108
1301
|
}
|
|
1109
|
-
finally { if (
|
|
1302
|
+
finally { if (e_15) throw e_15.error; }
|
|
1110
1303
|
}
|
|
1111
1304
|
if (op.op !== "remove") {
|
|
1112
1305
|
var v = op.value;
|
|
@@ -1136,12 +1329,12 @@ function applyJsonPatch(target, ops) {
|
|
|
1136
1329
|
obj[key] = op.value;
|
|
1137
1330
|
}
|
|
1138
1331
|
}
|
|
1139
|
-
catch (
|
|
1332
|
+
catch (e_14_1) { e_14 = { error: e_14_1 }; }
|
|
1140
1333
|
finally {
|
|
1141
1334
|
try {
|
|
1142
1335
|
if (ops_1_1 && !ops_1_1.done && (_a = ops_1.return)) _a.call(ops_1);
|
|
1143
1336
|
}
|
|
1144
|
-
finally { if (
|
|
1337
|
+
finally { if (e_14) throw e_14.error; }
|
|
1145
1338
|
}
|
|
1146
1339
|
}
|
|
1147
1340
|
function notifyStateSubscribers(initial) {
|
|
@@ -1199,8 +1392,8 @@ function applySnapshotFromResult(result) {
|
|
|
1199
1392
|
return true;
|
|
1200
1393
|
}
|
|
1201
1394
|
function handleIncomingMessage(msg) {
|
|
1202
|
-
var
|
|
1203
|
-
var _b, _c;
|
|
1395
|
+
var e_16, _a;
|
|
1396
|
+
var _b, _c, _d, _e;
|
|
1204
1397
|
// Handle native component events (from Android NativeBridge.sendEventToView)
|
|
1205
1398
|
if (msg && typeof msg === "object") {
|
|
1206
1399
|
var obj = msg;
|
|
@@ -1241,17 +1434,17 @@ function handleIncomingMessage(msg) {
|
|
|
1241
1434
|
handshakeRetryCount = 0;
|
|
1242
1435
|
if (message.hostMethods) {
|
|
1243
1436
|
try {
|
|
1244
|
-
for (var
|
|
1245
|
-
var
|
|
1437
|
+
for (var _f = __values(Object.entries(message.hostMethods)), _g = _f.next(); !_g.done; _g = _f.next()) {
|
|
1438
|
+
var _h = __read(_g.value, 2), k = _h[0], v = _h[1];
|
|
1246
1439
|
hostMethodKinds[k] = v;
|
|
1247
1440
|
}
|
|
1248
1441
|
}
|
|
1249
|
-
catch (
|
|
1442
|
+
catch (e_16_1) { e_16 = { error: e_16_1 }; }
|
|
1250
1443
|
finally {
|
|
1251
1444
|
try {
|
|
1252
|
-
if (
|
|
1445
|
+
if (_g && !_g.done && (_a = _f.return)) _a.call(_f);
|
|
1253
1446
|
}
|
|
1254
|
-
finally { if (
|
|
1447
|
+
finally { if (e_16) throw e_16.error; }
|
|
1255
1448
|
}
|
|
1256
1449
|
}
|
|
1257
1450
|
if (isDebugEnabled("proto"))
|
|
@@ -1291,7 +1484,15 @@ function handleIncomingMessage(msg) {
|
|
|
1291
1484
|
if (pendingReq.has(message.id)) {
|
|
1292
1485
|
var req = pendingReq.get(message.id);
|
|
1293
1486
|
if ((req === null || req === void 0 ? void 0 : req.mode) === "stream" && req.stream) {
|
|
1294
|
-
|
|
1487
|
+
// The first frame proves the handler is live. Long-lived streams
|
|
1488
|
+
// (bookmarks.watch, proxy.watch) are idle between pushes, so the
|
|
1489
|
+
// request timeout must not treat silence as death — disarm it for
|
|
1490
|
+
// good instead of re-arming per frame.
|
|
1491
|
+
if (req.timerId !== null) {
|
|
1492
|
+
clearTimeout(req.timerId);
|
|
1493
|
+
req.timerId = null;
|
|
1494
|
+
}
|
|
1495
|
+
req.timeoutMs = 0;
|
|
1295
1496
|
req.stream._emitData(message.payload);
|
|
1296
1497
|
}
|
|
1297
1498
|
else {
|
|
@@ -1369,8 +1570,10 @@ function handleIncomingMessage(msg) {
|
|
|
1369
1570
|
case "ch.close": {
|
|
1370
1571
|
var pendingChannel = pendingChannels.get(message.id);
|
|
1371
1572
|
if (pendingChannel) {
|
|
1372
|
-
|
|
1373
|
-
|
|
1573
|
+
rejectPendingChannel(message.id, {
|
|
1574
|
+
code: (_d = message.code) !== null && _d !== void 0 ? _d : BRIDGE_ERROR.STREAM_CLOSED,
|
|
1575
|
+
message: (_e = message.reason) !== null && _e !== void 0 ? _e : "Channel closed before opening",
|
|
1576
|
+
});
|
|
1374
1577
|
return;
|
|
1375
1578
|
}
|
|
1376
1579
|
var channel_3 = activeChannels.get(message.id);
|
|
@@ -1720,7 +1923,10 @@ export var LingXiaBridge = {
|
|
|
1720
1923
|
isIOS: isIOS,
|
|
1721
1924
|
isAndroid: isAndroid,
|
|
1722
1925
|
isMacOS: isMacOS,
|
|
1926
|
+
isWindows: isWindows,
|
|
1723
1927
|
isDesktop: isDesktop,
|
|
1928
|
+
isApple: isApple,
|
|
1929
|
+
isRunner: isRunner,
|
|
1724
1930
|
getOS: getPlatformOS,
|
|
1725
1931
|
},
|
|
1726
1932
|
dom: {
|
|
@@ -1778,23 +1984,23 @@ function wrapNativeStream(handle) {
|
|
|
1778
1984
|
var eventListeners = new Set();
|
|
1779
1985
|
var errorListeners = new Set();
|
|
1780
1986
|
handle.on("data", function (event) {
|
|
1781
|
-
var
|
|
1987
|
+
var e_17, _a;
|
|
1782
1988
|
try {
|
|
1783
1989
|
for (var eventListeners_1 = __values(eventListeners), eventListeners_1_1 = eventListeners_1.next(); !eventListeners_1_1.done; eventListeners_1_1 = eventListeners_1.next()) {
|
|
1784
1990
|
var listener = eventListeners_1_1.value;
|
|
1785
1991
|
listener(event);
|
|
1786
1992
|
}
|
|
1787
1993
|
}
|
|
1788
|
-
catch (
|
|
1994
|
+
catch (e_17_1) { e_17 = { error: e_17_1 }; }
|
|
1789
1995
|
finally {
|
|
1790
1996
|
try {
|
|
1791
1997
|
if (eventListeners_1_1 && !eventListeners_1_1.done && (_a = eventListeners_1.return)) _a.call(eventListeners_1);
|
|
1792
1998
|
}
|
|
1793
|
-
finally { if (
|
|
1999
|
+
finally { if (e_17) throw e_17.error; }
|
|
1794
2000
|
}
|
|
1795
2001
|
});
|
|
1796
2002
|
handle.on("error", function (error) {
|
|
1797
|
-
var
|
|
2003
|
+
var e_18, _a;
|
|
1798
2004
|
var nativeError = toNativeError(error);
|
|
1799
2005
|
try {
|
|
1800
2006
|
for (var errorListeners_1 = __values(errorListeners), errorListeners_1_1 = errorListeners_1.next(); !errorListeners_1_1.done; errorListeners_1_1 = errorListeners_1.next()) {
|
|
@@ -1802,12 +2008,12 @@ function wrapNativeStream(handle) {
|
|
|
1802
2008
|
listener(nativeError);
|
|
1803
2009
|
}
|
|
1804
2010
|
}
|
|
1805
|
-
catch (
|
|
2011
|
+
catch (e_18_1) { e_18 = { error: e_18_1 }; }
|
|
1806
2012
|
finally {
|
|
1807
2013
|
try {
|
|
1808
2014
|
if (errorListeners_1_1 && !errorListeners_1_1.done && (_a = errorListeners_1.return)) _a.call(errorListeners_1);
|
|
1809
2015
|
}
|
|
1810
|
-
finally { if (
|
|
2016
|
+
finally { if (e_18) throw e_18.error; }
|
|
1811
2017
|
}
|
|
1812
2018
|
});
|
|
1813
2019
|
return {
|
|
@@ -1833,23 +2039,23 @@ function wrapNativeChannel(channel) {
|
|
|
1833
2039
|
var messageListeners = new Set();
|
|
1834
2040
|
var closeListeners = new Set();
|
|
1835
2041
|
channel.on("data", function (message) {
|
|
1836
|
-
var
|
|
2042
|
+
var e_19, _a;
|
|
1837
2043
|
try {
|
|
1838
2044
|
for (var messageListeners_1 = __values(messageListeners), messageListeners_1_1 = messageListeners_1.next(); !messageListeners_1_1.done; messageListeners_1_1 = messageListeners_1.next()) {
|
|
1839
2045
|
var listener = messageListeners_1_1.value;
|
|
1840
2046
|
listener(message);
|
|
1841
2047
|
}
|
|
1842
2048
|
}
|
|
1843
|
-
catch (
|
|
2049
|
+
catch (e_19_1) { e_19 = { error: e_19_1 }; }
|
|
1844
2050
|
finally {
|
|
1845
2051
|
try {
|
|
1846
2052
|
if (messageListeners_1_1 && !messageListeners_1_1.done && (_a = messageListeners_1.return)) _a.call(messageListeners_1);
|
|
1847
2053
|
}
|
|
1848
|
-
finally { if (
|
|
2054
|
+
finally { if (e_19) throw e_19.error; }
|
|
1849
2055
|
}
|
|
1850
2056
|
});
|
|
1851
2057
|
channel.on("close", function (code, reason) {
|
|
1852
|
-
var
|
|
2058
|
+
var e_20, _a;
|
|
1853
2059
|
var event = { code: code, reason: reason };
|
|
1854
2060
|
try {
|
|
1855
2061
|
for (var closeListeners_1 = __values(closeListeners), closeListeners_1_1 = closeListeners_1.next(); !closeListeners_1_1.done; closeListeners_1_1 = closeListeners_1.next()) {
|
|
@@ -1857,12 +2063,12 @@ function wrapNativeChannel(channel) {
|
|
|
1857
2063
|
listener(event);
|
|
1858
2064
|
}
|
|
1859
2065
|
}
|
|
1860
|
-
catch (
|
|
2066
|
+
catch (e_20_1) { e_20 = { error: e_20_1 }; }
|
|
1861
2067
|
finally {
|
|
1862
2068
|
try {
|
|
1863
2069
|
if (closeListeners_1_1 && !closeListeners_1_1.done && (_a = closeListeners_1.return)) _a.call(closeListeners_1);
|
|
1864
2070
|
}
|
|
1865
|
-
finally { if (
|
|
2071
|
+
finally { if (e_20) throw e_20.error; }
|
|
1866
2072
|
}
|
|
1867
2073
|
});
|
|
1868
2074
|
return {
|
|
@@ -1909,19 +2115,25 @@ export function initBridge() {
|
|
|
1909
2115
|
activateReceiver(LingXiaBridge._receiveEvaluateMessage);
|
|
1910
2116
|
if (useAppleDownstreamTransport()) {
|
|
1911
2117
|
ensureAppleDownstream();
|
|
2118
|
+
startAppleWatchdog();
|
|
2119
|
+
installAppleForegroundReconnect();
|
|
1912
2120
|
}
|
|
1913
2121
|
else if (communicationMethod === MESSAGE_PORT_TYPE) {
|
|
1914
2122
|
installMessagePortInitListener();
|
|
1915
2123
|
getMessagePort().catch(function (e) { return warn("Port init failed:", e); });
|
|
1916
2124
|
}
|
|
1917
2125
|
else if (communicationMethod === "webkit" ||
|
|
1918
|
-
communicationMethod === JS_INTERFACE_TYPE
|
|
2126
|
+
communicationMethod === JS_INTERFACE_TYPE ||
|
|
2127
|
+
communicationMethod === WEB_MESSAGE_TYPE) {
|
|
1919
2128
|
startHandshake();
|
|
1920
2129
|
}
|
|
1921
2130
|
else {
|
|
1922
2131
|
warn("Unknown method");
|
|
1923
2132
|
}
|
|
1924
2133
|
window.LingXiaBridge = LingXiaBridge;
|
|
2134
|
+
// Dev hook so repro/test pages can simulate a WebKit stream replacement.
|
|
2135
|
+
window.__lxForceDownstreamReconnect =
|
|
2136
|
+
forceDownstreamReconnect;
|
|
1925
2137
|
installNativeComponentCoverageMonitor({
|
|
1926
2138
|
os: getPlatformOS(),
|
|
1927
2139
|
send: sendNativeComponentMessage,
|