1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-10-22 07:50:04 +02:00

fixing duplicate input when encryptor changes

This commit is contained in:
✨ Audrey ✨ 2024-10-16 17:50:02 -04:00
parent 919984c9c5
commit 98386c3032
No known key found for this signature in database
GPG Key ID: 0CF8B4C0D9088B97
3 changed files with 11 additions and 9 deletions

View File

@ -117,7 +117,7 @@ export function withLatestReady<Source, Watch>(
// is an external subscriber.
const source = new ReplaySubject<Source>(1);
source$.subscribe(source);
const watch = new ReplaySubject<Watch>(null);
const watch = new ReplaySubject<Watch>(1);
watch$.subscribe(watch);
// `concat` is subscribed immediately after it's returned, at which point

View File

@ -352,12 +352,16 @@ describe("UserStateSubject", () => {
const singleUserId$ = new BehaviorSubject(SomeUser);
const constraints$ = new Subject<StateConstraints<TestType>>();
const subject = new UserStateSubject(SomeKey, () => state, { singleUserId$, constraints$ });
const tracker = new ObservableTracker(subject);
const results: any[] = [];
subject.subscribe((r) => {
results.push(r);
});
subject.next({ foo: "next" });
constraints$.next(fooMaxLength(3));
await awaitAsync();
// `init` is also waiting and is processed before `next`
const [, nextResult] = await tracker.pauseUntilReceived(2);
const [, nextResult] = results;
expect(nextResult).toEqual({ foo: "nex" });
});

View File

@ -5,7 +5,6 @@ import {
ReplaySubject,
filter,
map,
Subject,
takeUntil,
pairwise,
distinctUntilChanged,
@ -137,8 +136,6 @@ export class UserStateSubject<
// the update stream simulates the stateProvider's "shouldUpdate"
// functionality & applies policy
const updates$ = concat(
// normalize input in case this `UserStateSubject` is not the only
// observer of the backing store
this.input.pipe(
this.when(when$),
this.adjust(withLatestReady(constraints$)),
@ -326,7 +323,8 @@ export class UserStateSubject<
}
private classify(encryptor$: Observable<UserEncryptor>): OperatorFunction<State, unknown> {
// short-circuit if they key lacks encryption support
// short-circuit if they key lacks encryption support; `encryptor` is
// readied to preserve `dependencies.singleUserId$` emission contract
if (!this.objectKey || this.objectKey.format === "plain") {
return pipe(
ready(encryptor$),
@ -337,7 +335,7 @@ export class UserStateSubject<
// if the key supports encryption, enable encryptor support
if (this.objectKey && this.objectKey.format === "classified") {
return pipe(
combineLatestWith(encryptor$),
withLatestReady(encryptor$),
concatMap(async ([input, encryptor]) => {
// fail fast if there's no value
if (input === null || input === undefined) {
@ -400,7 +398,7 @@ export class UserStateSubject<
// using subjects to ensure the right semantics are followed;
// if greater efficiency becomes desirable, consider implementing
// `SubjectLike` directly
private input = new Subject<State>();
private input = new ReplaySubject<State>(1);
private state: SingleUserState<unknown>;
private readonly output = new ReplaySubject<WithConstraints<State>>(1);