Skip to content

Commit

Permalink
Prevent race conditions
Browse files Browse the repository at this point in the history
  • Loading branch information
Mati365 committed Jun 7, 2024
1 parent f2118e1 commit 8d1cdcb
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/ckeditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import type {
import type { EditorSemaphoreMountResult } from './lifecycle/LifeCycleEditorSemaphore';

import { uid } from './utils/uid';
import { ContextWatchdogContext, isContextWatchdogValueWithStatus } from './ckeditorcontext';
import { ContextWatchdogContext, isContextWatchdogValueWithStatus, isContextWatchdogReadyToUse } from './ckeditorcontext';
import { LifeCycleElementSemaphore } from './lifecycle/LifeCycleElementSemaphore';

const REACT_INTEGRATION_READ_ONLY_LOCK_ID = 'Lock from React integration (@ckeditor/ckeditor5-react)';
Expand Down Expand Up @@ -225,7 +225,7 @@ export default class CKEditor<TEditor extends Editor> extends React.Component<Pr
const watchdog = ( () => {
// There is small delay where React did not update the context yet but watchdog is already destroyed.
// However editor should be created again in such case, after receiving new context.
if ( isContextWatchdogValueWithStatus( 'initialized', this.context ) && this.context.watchdog.state !== 'destroyed' ) {
if ( isContextWatchdogReadyToUse( this.context ) ) {
return new EditorWatchdogAdapter( this.context.watchdog );
}

Expand Down
10 changes: 10 additions & 0 deletions src/ckeditorcontext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,16 @@ export const isContextWatchdogValueWithStatus = <S extends ContextWatchdogValueS
obj is ExtractContextWatchdogValueByStatus<S> =>
isContextWatchdogValue( obj ) && obj.status === status;

/**
* Checks if the provided object is a fully initialized context watchdog value. It prevents race conditions between
* watchdog state that is not fully synchronized with the context state. For example, the watchdog state can be 'destroyed'
* while the context is still being initialized because context setState is pending.
*/
export const isContextWatchdogReadyToUse = ( obj: any ): obj is ExtractContextWatchdogValueByStatus<'initialized'> => (
isContextWatchdogValueWithStatus( 'initialized', obj ) &&
obj.watchdog.state === 'ready'
);

/**
* Represents the value of the ContextWatchdog in the CKEditor context.
*/
Expand Down

0 comments on commit 8d1cdcb

Please sign in to comment.