@gurezo/web-serial-rxjs 4.0.5 → 4.1.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/index.mjs +283 -211
- package/dist/index.mjs.map +4 -4
- package/dist/internal/newline-tokenizer.d.ts +1 -1
- package/dist/session/create-serial-session.d.ts.map +1 -1
- package/dist/session/internal/port-teardown.d.ts +53 -0
- package/dist/session/internal/port-teardown.d.ts.map +1 -1
- package/dist/session/internal/session-error-reporter.d.ts +4 -6
- package/dist/session/internal/session-error-reporter.d.ts.map +1 -1
- package/dist/session/internal/session-lifecycle.d.ts +4 -1
- package/dist/session/internal/session-lifecycle.d.ts.map +1 -1
- package/dist/session/read-pump.d.ts +4 -3
- package/dist/session/read-pump.d.ts.map +1 -1
- package/dist/session/send-queue.d.ts +2 -1
- package/dist/session/send-queue.d.ts.map +1 -1
- package/dist/session/serial-session-options.d.ts +0 -31
- package/dist/session/serial-session-options.d.ts.map +1 -1
- package/dist/session/session-runtime.d.ts +0 -6
- package/dist/session/session-runtime.d.ts.map +1 -1
- package/dist/terminal/create-terminal-buffer.d.ts +0 -38
- package/dist/terminal/create-terminal-buffer.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -182,7 +182,13 @@ var SerialErrorCode = {
|
|
|
182
182
|
};
|
|
183
183
|
|
|
184
184
|
// src/terminal/create-terminal-buffer.ts
|
|
185
|
-
import {
|
|
185
|
+
import {
|
|
186
|
+
ReplaySubject,
|
|
187
|
+
finalize,
|
|
188
|
+
map,
|
|
189
|
+
scan,
|
|
190
|
+
share
|
|
191
|
+
} from "rxjs";
|
|
186
192
|
|
|
187
193
|
// src/errors/serial-error-context.ts
|
|
188
194
|
var CAUSE_CONTEXT_CODES = /* @__PURE__ */ new Set([
|
|
@@ -445,19 +451,46 @@ function createAnsiStripper() {
|
|
|
445
451
|
}
|
|
446
452
|
|
|
447
453
|
// src/terminal/create-terminal-buffer.ts
|
|
448
|
-
|
|
454
|
+
var emptyTerminalState = {
|
|
455
|
+
completed: "",
|
|
456
|
+
currentLine: ""
|
|
457
|
+
};
|
|
458
|
+
function createTerminalParser(options = {}) {
|
|
459
|
+
const stripAnsi = options.stripAnsi ?? false;
|
|
449
460
|
const tokenizer = createNewlineTokenizer("terminal");
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
return {
|
|
461
|
+
let ansiStripper = stripAnsi ? createAnsiStripper() : null;
|
|
462
|
+
let completed = "";
|
|
463
|
+
const resetAnsiStripper = () => {
|
|
464
|
+
ansiStripper = stripAnsi ? createAnsiStripper() : null;
|
|
465
|
+
};
|
|
466
|
+
const getState = () => ({
|
|
459
467
|
completed,
|
|
460
468
|
currentLine: tokenizer.getPendingText()
|
|
469
|
+
});
|
|
470
|
+
const restoreState = (state) => {
|
|
471
|
+
completed = state.completed;
|
|
472
|
+
tokenizer.restorePending(state.currentLine);
|
|
473
|
+
};
|
|
474
|
+
const reset = () => {
|
|
475
|
+
completed = "";
|
|
476
|
+
tokenizer.clear();
|
|
477
|
+
resetAnsiStripper();
|
|
478
|
+
};
|
|
479
|
+
const feed = (chunk) => {
|
|
480
|
+
const normalized = ansiStripper !== null ? ansiStripper.feed(chunk) : chunk;
|
|
481
|
+
const events = tokenizer.feed(normalized);
|
|
482
|
+
for (const event of events) {
|
|
483
|
+
if (event.type === "line") {
|
|
484
|
+
completed += event.content + "\n";
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
return getState();
|
|
488
|
+
};
|
|
489
|
+
return {
|
|
490
|
+
feed,
|
|
491
|
+
reset,
|
|
492
|
+
getState,
|
|
493
|
+
restoreState
|
|
461
494
|
};
|
|
462
495
|
}
|
|
463
496
|
function terminalDisplayText(state) {
|
|
@@ -479,15 +512,21 @@ function trimCompletedByMaxLines(completed, maxLines) {
|
|
|
479
512
|
if (maxLines <= 0) {
|
|
480
513
|
return completed;
|
|
481
514
|
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
515
|
+
const lineCount = countCompletedLines(completed);
|
|
516
|
+
if (lineCount <= maxLines) {
|
|
517
|
+
return completed;
|
|
518
|
+
}
|
|
519
|
+
const linesToDrop = lineCount - maxLines;
|
|
520
|
+
let dropped = 0;
|
|
521
|
+
for (let i = 0; i < completed.length; i++) {
|
|
522
|
+
if (completed.charAt(i) === "\n") {
|
|
523
|
+
dropped++;
|
|
524
|
+
if (dropped === linesToDrop) {
|
|
525
|
+
return completed.slice(i + 1);
|
|
526
|
+
}
|
|
487
527
|
}
|
|
488
|
-
trimmed = trimmed.slice(firstNewline + 1);
|
|
489
528
|
}
|
|
490
|
-
return
|
|
529
|
+
return completed;
|
|
491
530
|
}
|
|
492
531
|
function trimTerminalState(state, limits) {
|
|
493
532
|
let { completed, currentLine } = state;
|
|
@@ -551,25 +590,28 @@ function resolveTerminalBufferOptions(options) {
|
|
|
551
590
|
stripAnsi: merged.stripAnsi
|
|
552
591
|
};
|
|
553
592
|
}
|
|
554
|
-
var initialTerminalState = {
|
|
555
|
-
completed: "",
|
|
556
|
-
currentLine: ""
|
|
557
|
-
};
|
|
558
593
|
function createTerminalBuffer(receive$, options) {
|
|
559
594
|
const resolved = resolveTerminalBufferOptions(options);
|
|
560
595
|
const limits = {
|
|
561
596
|
maxLines: resolved.maxLines,
|
|
562
597
|
maxChars: resolved.maxChars
|
|
563
598
|
};
|
|
564
|
-
const
|
|
599
|
+
const parser = createTerminalParser({ stripAnsi: resolved.stripAnsi });
|
|
565
600
|
const text$ = receive$.pipe(
|
|
566
|
-
scan((
|
|
567
|
-
|
|
568
|
-
const
|
|
569
|
-
|
|
570
|
-
|
|
601
|
+
scan((_state, chunk) => {
|
|
602
|
+
parser.feed(chunk);
|
|
603
|
+
const trimmed = trimTerminalState(parser.getState(), limits);
|
|
604
|
+
parser.restoreState(trimmed);
|
|
605
|
+
return trimmed;
|
|
606
|
+
}, emptyTerminalState),
|
|
571
607
|
map(terminalDisplayText),
|
|
572
|
-
|
|
608
|
+
finalize(() => {
|
|
609
|
+
parser.reset();
|
|
610
|
+
}),
|
|
611
|
+
share({
|
|
612
|
+
connector: () => new ReplaySubject(1),
|
|
613
|
+
resetOnRefCountZero: true
|
|
614
|
+
})
|
|
573
615
|
);
|
|
574
616
|
return { text$ };
|
|
575
617
|
}
|
|
@@ -579,9 +621,156 @@ function isWebSerialSupported() {
|
|
|
579
621
|
return typeof navigator !== "undefined" && "serial" in navigator && navigator.serial !== void 0 && navigator.serial !== null;
|
|
580
622
|
}
|
|
581
623
|
|
|
624
|
+
// src/session/session-runtime.ts
|
|
625
|
+
import { BehaviorSubject } from "rxjs";
|
|
626
|
+
|
|
627
|
+
// src/session/serial-session-state.ts
|
|
628
|
+
var SerialSessionStatus = {
|
|
629
|
+
Idle: "idle",
|
|
630
|
+
Connecting: "connecting",
|
|
631
|
+
Connected: "connected",
|
|
632
|
+
Disconnecting: "disconnecting",
|
|
633
|
+
Unsupported: "unsupported",
|
|
634
|
+
Error: "error",
|
|
635
|
+
Disposed: "disposed"
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
// src/session/session-runtime.ts
|
|
639
|
+
var S = SerialSessionStatus;
|
|
640
|
+
var ALLOWED_TRANSITIONS = {
|
|
641
|
+
[S.Idle]: [S.Connecting, S.Error, S.Disposed],
|
|
642
|
+
[S.Connecting]: [S.Connected, S.Error, S.Idle, S.Disposed],
|
|
643
|
+
[S.Connected]: [S.Disconnecting, S.Error, S.Disposed],
|
|
644
|
+
[S.Disconnecting]: [S.Idle, S.Error, S.Disposed],
|
|
645
|
+
[S.Error]: [S.Idle, S.Connecting, S.Disposed],
|
|
646
|
+
[S.Unsupported]: [S.Disposed],
|
|
647
|
+
[S.Disposed]: []
|
|
648
|
+
};
|
|
649
|
+
function runtimeToSessionStatus(runtime) {
|
|
650
|
+
return runtime.status;
|
|
651
|
+
}
|
|
652
|
+
function runtimeToPublicState(runtime) {
|
|
653
|
+
switch (runtime.status) {
|
|
654
|
+
case S.Idle:
|
|
655
|
+
return { status: S.Idle };
|
|
656
|
+
case S.Connecting:
|
|
657
|
+
return { status: S.Connecting };
|
|
658
|
+
case S.Connected:
|
|
659
|
+
return { status: S.Connected, portInfo: runtime.port.getInfo() };
|
|
660
|
+
case S.Disconnecting:
|
|
661
|
+
return { status: S.Disconnecting };
|
|
662
|
+
case S.Unsupported:
|
|
663
|
+
return { status: S.Unsupported };
|
|
664
|
+
case S.Error:
|
|
665
|
+
return { status: S.Error, error: runtime.error };
|
|
666
|
+
case S.Disposed:
|
|
667
|
+
return { status: S.Disposed };
|
|
668
|
+
default:
|
|
669
|
+
return assertNever(runtime);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
function isValidTransition(from, to) {
|
|
673
|
+
if (from === to) {
|
|
674
|
+
return false;
|
|
675
|
+
}
|
|
676
|
+
return ALLOWED_TRANSITIONS[from].includes(
|
|
677
|
+
to
|
|
678
|
+
);
|
|
679
|
+
}
|
|
680
|
+
function createIdleRuntime() {
|
|
681
|
+
return { status: S.Idle };
|
|
682
|
+
}
|
|
683
|
+
function createConnectingRuntime(cancel) {
|
|
684
|
+
return { status: S.Connecting, cancel };
|
|
685
|
+
}
|
|
686
|
+
function createConnectedRuntime(port, pump) {
|
|
687
|
+
return { status: S.Connected, port, pump };
|
|
688
|
+
}
|
|
689
|
+
function createDisconnectingRuntime(port) {
|
|
690
|
+
return { status: S.Disconnecting, port };
|
|
691
|
+
}
|
|
692
|
+
function createErrorRuntime(error) {
|
|
693
|
+
return { status: S.Error, error };
|
|
694
|
+
}
|
|
695
|
+
function createUnsupportedRuntime() {
|
|
696
|
+
return { status: S.Unsupported };
|
|
697
|
+
}
|
|
698
|
+
function createDisposedRuntime() {
|
|
699
|
+
return { status: S.Disposed };
|
|
700
|
+
}
|
|
701
|
+
function createInitialRuntime(supported) {
|
|
702
|
+
return supported ? createIdleRuntime() : createUnsupportedRuntime();
|
|
703
|
+
}
|
|
704
|
+
function getRuntimePort(runtime) {
|
|
705
|
+
switch (runtime.status) {
|
|
706
|
+
case S.Connected:
|
|
707
|
+
return runtime.port;
|
|
708
|
+
case S.Disconnecting:
|
|
709
|
+
return runtime.port;
|
|
710
|
+
default:
|
|
711
|
+
return null;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
function getRuntimePump(runtime) {
|
|
715
|
+
if (runtime.status === S.Connected) {
|
|
716
|
+
return runtime.pump;
|
|
717
|
+
}
|
|
718
|
+
return null;
|
|
719
|
+
}
|
|
720
|
+
function createSessionRuntimeController(initial) {
|
|
721
|
+
let runtime = initial;
|
|
722
|
+
const subject = new BehaviorSubject(
|
|
723
|
+
runtimeToPublicState(initial)
|
|
724
|
+
);
|
|
725
|
+
const transition = (next) => {
|
|
726
|
+
const from = runtimeToSessionStatus(runtime);
|
|
727
|
+
const to = runtimeToSessionStatus(next);
|
|
728
|
+
if (from === to) {
|
|
729
|
+
return false;
|
|
730
|
+
}
|
|
731
|
+
if (!isValidTransition(from, to)) {
|
|
732
|
+
if (typeof console !== "undefined" && console.warn) {
|
|
733
|
+
console.warn(
|
|
734
|
+
`[web-serial-rxjs] Ignoring invalid SerialSession transition ${from} -> ${to}`
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
return false;
|
|
738
|
+
}
|
|
739
|
+
const publicState = runtimeToPublicState(next);
|
|
740
|
+
runtime = next;
|
|
741
|
+
subject.next(publicState);
|
|
742
|
+
return true;
|
|
743
|
+
};
|
|
744
|
+
return {
|
|
745
|
+
get runtime() {
|
|
746
|
+
return runtime;
|
|
747
|
+
},
|
|
748
|
+
get status() {
|
|
749
|
+
return runtimeToSessionStatus(runtime);
|
|
750
|
+
},
|
|
751
|
+
get state$() {
|
|
752
|
+
return subject.asObservable();
|
|
753
|
+
},
|
|
754
|
+
transition,
|
|
755
|
+
complete() {
|
|
756
|
+
subject.complete();
|
|
757
|
+
}
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
|
|
582
761
|
// src/session/internal/port-teardown.ts
|
|
762
|
+
function captureResources(runtime) {
|
|
763
|
+
const resources = {
|
|
764
|
+
port: getRuntimePort(runtime),
|
|
765
|
+
pump: getRuntimePump(runtime)
|
|
766
|
+
};
|
|
767
|
+
if (runtime.status === SerialSessionStatus.Connecting) {
|
|
768
|
+
resources.cancelConnect = runtime.cancel;
|
|
769
|
+
}
|
|
770
|
+
return resources;
|
|
771
|
+
}
|
|
583
772
|
function createPortTeardown(deps) {
|
|
584
|
-
const { receivePipeline } = deps;
|
|
773
|
+
const { receivePipeline, sendQueue } = deps;
|
|
585
774
|
const teardownPump = async (pump) => {
|
|
586
775
|
receivePipeline.clearLineBuffer();
|
|
587
776
|
if (pump) {
|
|
@@ -597,7 +786,36 @@ function createPortTeardown(deps) {
|
|
|
597
786
|
} catch {
|
|
598
787
|
}
|
|
599
788
|
};
|
|
600
|
-
|
|
789
|
+
const teardownResources = async (resources, options = {}) => {
|
|
790
|
+
const closeMode = options.closeMode ?? "safe";
|
|
791
|
+
const cancelInFlightConnect = options.cancelInFlightConnect ?? true;
|
|
792
|
+
if (cancelInFlightConnect) {
|
|
793
|
+
resources.cancelConnect?.();
|
|
794
|
+
}
|
|
795
|
+
sendQueue.clear();
|
|
796
|
+
await teardownPump(resources.pump);
|
|
797
|
+
if (!resources.port) {
|
|
798
|
+
return;
|
|
799
|
+
}
|
|
800
|
+
if (closeMode === "safe") {
|
|
801
|
+
await closePortSafely(resources.port);
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
try {
|
|
805
|
+
await resources.port.close();
|
|
806
|
+
} catch (error) {
|
|
807
|
+
if (options.onCloseError) {
|
|
808
|
+
options.onCloseError(error);
|
|
809
|
+
}
|
|
810
|
+
throw error;
|
|
811
|
+
}
|
|
812
|
+
};
|
|
813
|
+
return {
|
|
814
|
+
teardownPump,
|
|
815
|
+
closePortSafely,
|
|
816
|
+
captureResources,
|
|
817
|
+
teardownResources
|
|
818
|
+
};
|
|
601
819
|
}
|
|
602
820
|
|
|
603
821
|
// src/session/internal/receive-pipeline.ts
|
|
@@ -739,155 +957,14 @@ function normalizeSerialError(error, options) {
|
|
|
739
957
|
);
|
|
740
958
|
}
|
|
741
959
|
|
|
742
|
-
// src/session/session-runtime.ts
|
|
743
|
-
import { BehaviorSubject } from "rxjs";
|
|
744
|
-
|
|
745
|
-
// src/session/serial-session-state.ts
|
|
746
|
-
var SerialSessionStatus = {
|
|
747
|
-
Idle: "idle",
|
|
748
|
-
Connecting: "connecting",
|
|
749
|
-
Connected: "connected",
|
|
750
|
-
Disconnecting: "disconnecting",
|
|
751
|
-
Unsupported: "unsupported",
|
|
752
|
-
Error: "error",
|
|
753
|
-
Disposed: "disposed"
|
|
754
|
-
};
|
|
755
|
-
|
|
756
|
-
// src/session/session-runtime.ts
|
|
757
|
-
var S = SerialSessionStatus;
|
|
758
|
-
var ALLOWED_TRANSITIONS = {
|
|
759
|
-
[S.Idle]: [S.Connecting, S.Error, S.Disposed],
|
|
760
|
-
[S.Connecting]: [S.Connected, S.Error, S.Idle, S.Disposed],
|
|
761
|
-
[S.Connected]: [S.Disconnecting, S.Error, S.Disposed],
|
|
762
|
-
[S.Disconnecting]: [S.Idle, S.Error, S.Disposed],
|
|
763
|
-
[S.Error]: [S.Idle, S.Connecting, S.Disposed],
|
|
764
|
-
[S.Unsupported]: [S.Disposed],
|
|
765
|
-
[S.Disposed]: []
|
|
766
|
-
};
|
|
767
|
-
function runtimeToSessionStatus(runtime) {
|
|
768
|
-
return runtime.status;
|
|
769
|
-
}
|
|
770
|
-
function runtimeToPublicState(runtime) {
|
|
771
|
-
switch (runtime.status) {
|
|
772
|
-
case S.Idle:
|
|
773
|
-
return { status: S.Idle };
|
|
774
|
-
case S.Connecting:
|
|
775
|
-
return { status: S.Connecting };
|
|
776
|
-
case S.Connected:
|
|
777
|
-
return { status: S.Connected, portInfo: runtime.port.getInfo() };
|
|
778
|
-
case S.Disconnecting:
|
|
779
|
-
return { status: S.Disconnecting };
|
|
780
|
-
case S.Unsupported:
|
|
781
|
-
return { status: S.Unsupported };
|
|
782
|
-
case S.Error:
|
|
783
|
-
return { status: S.Error, error: runtime.error };
|
|
784
|
-
case S.Disposed:
|
|
785
|
-
return { status: S.Disposed };
|
|
786
|
-
default:
|
|
787
|
-
return assertNeverRuntime(runtime);
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
function isValidTransition(from, to) {
|
|
791
|
-
if (from === to) {
|
|
792
|
-
return false;
|
|
793
|
-
}
|
|
794
|
-
return ALLOWED_TRANSITIONS[from].includes(
|
|
795
|
-
to
|
|
796
|
-
);
|
|
797
|
-
}
|
|
798
|
-
function createIdleRuntime() {
|
|
799
|
-
return { status: S.Idle };
|
|
800
|
-
}
|
|
801
|
-
function createConnectingRuntime(cancel) {
|
|
802
|
-
return { status: S.Connecting, cancel };
|
|
803
|
-
}
|
|
804
|
-
function createConnectedRuntime(port, pump) {
|
|
805
|
-
return { status: S.Connected, port, pump };
|
|
806
|
-
}
|
|
807
|
-
function createDisconnectingRuntime(port) {
|
|
808
|
-
return { status: S.Disconnecting, port };
|
|
809
|
-
}
|
|
810
|
-
function createErrorRuntime(error) {
|
|
811
|
-
return { status: S.Error, error };
|
|
812
|
-
}
|
|
813
|
-
function createUnsupportedRuntime() {
|
|
814
|
-
return { status: S.Unsupported };
|
|
815
|
-
}
|
|
816
|
-
function createDisposedRuntime() {
|
|
817
|
-
return { status: S.Disposed };
|
|
818
|
-
}
|
|
819
|
-
function createInitialRuntime(supported) {
|
|
820
|
-
return supported ? createIdleRuntime() : createUnsupportedRuntime();
|
|
821
|
-
}
|
|
822
|
-
function getRuntimePort(runtime) {
|
|
823
|
-
switch (runtime.status) {
|
|
824
|
-
case S.Connected:
|
|
825
|
-
return runtime.port;
|
|
826
|
-
case S.Disconnecting:
|
|
827
|
-
return runtime.port;
|
|
828
|
-
default:
|
|
829
|
-
return null;
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
function getRuntimePump(runtime) {
|
|
833
|
-
if (runtime.status === S.Connected) {
|
|
834
|
-
return runtime.pump;
|
|
835
|
-
}
|
|
836
|
-
return null;
|
|
837
|
-
}
|
|
838
|
-
function createSessionRuntimeController(initial) {
|
|
839
|
-
let runtime = initial;
|
|
840
|
-
const subject = new BehaviorSubject(
|
|
841
|
-
runtimeToPublicState(initial)
|
|
842
|
-
);
|
|
843
|
-
const transition = (next) => {
|
|
844
|
-
const from = runtimeToSessionStatus(runtime);
|
|
845
|
-
const to = runtimeToSessionStatus(next);
|
|
846
|
-
if (from === to) {
|
|
847
|
-
return false;
|
|
848
|
-
}
|
|
849
|
-
if (!isValidTransition(from, to)) {
|
|
850
|
-
if (typeof console !== "undefined" && console.warn) {
|
|
851
|
-
console.warn(
|
|
852
|
-
`[web-serial-rxjs] Ignoring invalid SerialSession transition ${from} -> ${to}`
|
|
853
|
-
);
|
|
854
|
-
}
|
|
855
|
-
return false;
|
|
856
|
-
}
|
|
857
|
-
const publicState = runtimeToPublicState(next);
|
|
858
|
-
runtime = next;
|
|
859
|
-
subject.next(publicState);
|
|
860
|
-
return true;
|
|
861
|
-
};
|
|
862
|
-
return {
|
|
863
|
-
get runtime() {
|
|
864
|
-
return runtime;
|
|
865
|
-
},
|
|
866
|
-
get status() {
|
|
867
|
-
return runtimeToSessionStatus(runtime);
|
|
868
|
-
},
|
|
869
|
-
get state$() {
|
|
870
|
-
return subject.asObservable();
|
|
871
|
-
},
|
|
872
|
-
transition,
|
|
873
|
-
complete() {
|
|
874
|
-
subject.complete();
|
|
875
|
-
}
|
|
876
|
-
};
|
|
877
|
-
}
|
|
878
|
-
function assertNeverRuntime(value) {
|
|
879
|
-
return assertNever(value);
|
|
880
|
-
}
|
|
881
|
-
|
|
882
960
|
// src/session/internal/session-error-reporter.ts
|
|
883
961
|
function createSessionErrorReporter(deps) {
|
|
884
962
|
const {
|
|
885
963
|
controller,
|
|
886
964
|
errorsSubject,
|
|
887
|
-
sendQueue,
|
|
888
965
|
isDisposed,
|
|
889
|
-
|
|
890
|
-
|
|
966
|
+
captureResources: captureResources2,
|
|
967
|
+
teardownResources
|
|
891
968
|
} = deps;
|
|
892
969
|
const createDisposedError = () => new SerialError(
|
|
893
970
|
SerialErrorCode.SESSION_DISPOSED,
|
|
@@ -900,12 +977,12 @@ function createSessionErrorReporter(deps) {
|
|
|
900
977
|
}
|
|
901
978
|
errorsSubject.next(serialError);
|
|
902
979
|
if (resolveErrorSeverity(serialError.code) === "fatal") {
|
|
903
|
-
const
|
|
904
|
-
const portToClose = getRuntimePort(runtime);
|
|
905
|
-
const pump = getRuntimePump(runtime);
|
|
980
|
+
const resources = captureResources2(controller.runtime);
|
|
906
981
|
controller.transition(createErrorRuntime(serialError));
|
|
907
|
-
|
|
908
|
-
|
|
982
|
+
void teardownResources(resources, {
|
|
983
|
+
closeMode: "safe",
|
|
984
|
+
cancelInFlightConnect: false
|
|
985
|
+
});
|
|
909
986
|
}
|
|
910
987
|
return serialError;
|
|
911
988
|
};
|
|
@@ -1030,22 +1107,11 @@ function createSessionLifecycle(deps) {
|
|
|
1030
1107
|
isDisposed,
|
|
1031
1108
|
teardownPump,
|
|
1032
1109
|
closePortSafely,
|
|
1110
|
+
captureResources: captureResources2,
|
|
1111
|
+
teardownResources,
|
|
1033
1112
|
reportError,
|
|
1034
1113
|
createDisposedError
|
|
1035
1114
|
} = deps;
|
|
1036
|
-
const teardownFromSnapshot = async (snapshot) => {
|
|
1037
|
-
if (snapshot.status === SerialSessionStatus.Connecting) {
|
|
1038
|
-
snapshot.cancel();
|
|
1039
|
-
}
|
|
1040
|
-
sendQueue.clear();
|
|
1041
|
-
if (snapshot.status === SerialSessionStatus.Connected || snapshot.status === SerialSessionStatus.Disconnecting || snapshot.status === SerialSessionStatus.Error) {
|
|
1042
|
-
const portToClose = getRuntimePort(snapshot);
|
|
1043
|
-
const pump = getRuntimePump(snapshot);
|
|
1044
|
-
await teardownPump(pump);
|
|
1045
|
-
await closePortSafely(portToClose);
|
|
1046
|
-
}
|
|
1047
|
-
receivePipeline.clearLineBuffer();
|
|
1048
|
-
};
|
|
1049
1115
|
const completeSubjects = () => {
|
|
1050
1116
|
controller.complete();
|
|
1051
1117
|
errorsSubject.complete();
|
|
@@ -1058,10 +1124,11 @@ function createSessionLifecycle(deps) {
|
|
|
1058
1124
|
return;
|
|
1059
1125
|
}
|
|
1060
1126
|
const snapshot = controller.runtime;
|
|
1127
|
+
const resources = captureResources2(snapshot);
|
|
1061
1128
|
controller.transition(createDisposedRuntime());
|
|
1062
1129
|
const run = async () => {
|
|
1063
1130
|
try {
|
|
1064
|
-
await
|
|
1131
|
+
await teardownResources(resources, { closeMode: "safe" });
|
|
1065
1132
|
completeSubjects();
|
|
1066
1133
|
subscriber.next();
|
|
1067
1134
|
subscriber.complete();
|
|
@@ -1227,31 +1294,29 @@ function createSessionLifecycle(deps) {
|
|
|
1227
1294
|
subscriber.error(error);
|
|
1228
1295
|
return;
|
|
1229
1296
|
}
|
|
1230
|
-
const
|
|
1231
|
-
controller.transition(createDisconnectingRuntime(
|
|
1232
|
-
sendQueue.clear();
|
|
1297
|
+
const resources = captureResources2(runtime);
|
|
1298
|
+
controller.transition(createDisconnectingRuntime(resources.port));
|
|
1233
1299
|
const run = async () => {
|
|
1234
1300
|
try {
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
await portToClose.close();
|
|
1240
|
-
} catch (error) {
|
|
1241
|
-
const serialError = reportError(error, {
|
|
1301
|
+
await teardownResources(resources, {
|
|
1302
|
+
closeMode: "report",
|
|
1303
|
+
onCloseError: (error) => {
|
|
1304
|
+
throw reportError(error, {
|
|
1242
1305
|
fallbackCode: SerialErrorCode.CONNECTION_LOST,
|
|
1243
1306
|
messagePrefix: "Failed to close port"
|
|
1244
1307
|
});
|
|
1245
|
-
subscriber.error(serialError);
|
|
1246
|
-
return;
|
|
1247
1308
|
}
|
|
1248
|
-
}
|
|
1309
|
+
});
|
|
1249
1310
|
if (!isDisposed()) {
|
|
1250
1311
|
controller.transition(createIdleRuntime());
|
|
1251
1312
|
}
|
|
1252
1313
|
subscriber.next();
|
|
1253
1314
|
subscriber.complete();
|
|
1254
1315
|
} catch (error) {
|
|
1316
|
+
if (error instanceof SerialError) {
|
|
1317
|
+
subscriber.error(error);
|
|
1318
|
+
return;
|
|
1319
|
+
}
|
|
1255
1320
|
const serialError = reportError(error, {
|
|
1256
1321
|
fallbackCode: SerialErrorCode.UNKNOWN,
|
|
1257
1322
|
messagePrefix: "Unexpected disconnect failure"
|
|
@@ -1443,16 +1508,21 @@ function createSerialSession(options) {
|
|
|
1443
1508
|
const textEncoder = new TextEncoder();
|
|
1444
1509
|
const isDisposed = () => controller.status === SerialSessionStatus.Disposed;
|
|
1445
1510
|
const receivePipeline = createReceivePipeline({ resolvedOptions });
|
|
1446
|
-
const {
|
|
1447
|
-
|
|
1511
|
+
const {
|
|
1512
|
+
teardownPump,
|
|
1513
|
+
closePortSafely,
|
|
1514
|
+
captureResources: captureResources2,
|
|
1515
|
+
teardownResources
|
|
1516
|
+
} = createPortTeardown({
|
|
1517
|
+
receivePipeline,
|
|
1518
|
+
sendQueue
|
|
1448
1519
|
});
|
|
1449
1520
|
const { reportError, createDisposedError } = createSessionErrorReporter({
|
|
1450
1521
|
controller,
|
|
1451
1522
|
errorsSubject,
|
|
1452
|
-
sendQueue,
|
|
1453
1523
|
isDisposed,
|
|
1454
|
-
|
|
1455
|
-
|
|
1524
|
+
captureResources: captureResources2,
|
|
1525
|
+
teardownResources
|
|
1456
1526
|
});
|
|
1457
1527
|
receivePipeline.bufferErrors$.subscribe(
|
|
1458
1528
|
(error) => reportError(error, { fallbackCode: error.code })
|
|
@@ -1466,6 +1536,8 @@ function createSerialSession(options) {
|
|
|
1466
1536
|
isDisposed,
|
|
1467
1537
|
teardownPump,
|
|
1468
1538
|
closePortSafely,
|
|
1539
|
+
captureResources: captureResources2,
|
|
1540
|
+
teardownResources,
|
|
1469
1541
|
reportError,
|
|
1470
1542
|
createDisposedError
|
|
1471
1543
|
});
|