@@ -74,6 +74,25 @@ const DEFAULT_AWARENESS_PALETTE = Object.freeze([
7474 */
7575/** @typedef {import('./types/index.js').NavigableAddress } NavigableAddress */
7676
77+ /**
78+ * Config callbacks are optional on the public typedef because consumers do
79+ * not need to pass them. The fields wrapped by this helper (every callback
80+ * registered in `#initListeners` plus the toolbar `exception` listener)
81+ * default to `() => null` in the class-field initializer, so EventEmitter
82+ * receives a function in normal use. This helper is a runtime identity
83+ * cast: behavior is unchanged if that invariant is ever broken (e.g. a
84+ * consumer explicitly passes `undefined`), and EventEmitter sees the same
85+ * value it would have without the wrapper. Sites with a `null` default
86+ * (`onFontsResolved`, `onTrackedChangeBubbleAccept`, `onTrackedChangeBubbleReject`)
87+ * use a separate `if`-guard pattern instead of this helper.
88+ *
89+ * @param {((...args: any[]) => void) | undefined } listener
90+ * @returns {(...args: any[]) => void }
91+ */
92+ function asEventListener ( listener ) {
93+ return /** @type {(...args: any[]) => void } */ ( listener ) ;
94+ }
95+
7796/**
7897 * SuperDoc class
7998 * Expects a config object
@@ -558,21 +577,21 @@ export class SuperDoc extends EventEmitter {
558577 }
559578
560579 #initListeners( ) {
561- this . on ( 'editorBeforeCreate' , this . config . onEditorBeforeCreate ) ;
562- this . on ( 'editorCreate' , this . config . onEditorCreate ) ;
563- this . on ( 'editorDestroy' , this . config . onEditorDestroy ) ;
564- this . on ( 'ready' , this . config . onReady ) ;
565- this . on ( 'comments-update' , this . config . onCommentsUpdate ) ;
566- this . on ( 'awareness-update' , this . config . onAwarenessUpdate ) ;
567- this . on ( 'locked' , this . config . onLocked ) ;
568- this . on ( 'pdf:document-ready' , this . config . onPdfDocumentReady ) ;
569- this . on ( 'sidebar-toggle' , this . config . onSidebarToggle ) ;
570- this . on ( 'collaboration-ready' , this . config . onCollaborationReady ) ;
571- this . on ( 'editor-update' , this . config . onEditorUpdate ) ;
580+ this . on ( 'editorBeforeCreate' , asEventListener ( this . config . onEditorBeforeCreate ) ) ;
581+ this . on ( 'editorCreate' , asEventListener ( this . config . onEditorCreate ) ) ;
582+ this . on ( 'editorDestroy' , asEventListener ( this . config . onEditorDestroy ) ) ;
583+ this . on ( 'ready' , asEventListener ( this . config . onReady ) ) ;
584+ this . on ( 'comments-update' , asEventListener ( this . config . onCommentsUpdate ) ) ;
585+ this . on ( 'awareness-update' , asEventListener ( this . config . onAwarenessUpdate ) ) ;
586+ this . on ( 'locked' , asEventListener ( this . config . onLocked ) ) ;
587+ this . on ( 'pdf:document-ready' , asEventListener ( this . config . onPdfDocumentReady ) ) ;
588+ this . on ( 'sidebar-toggle' , asEventListener ( this . config . onSidebarToggle ) ) ;
589+ this . on ( 'collaboration-ready' , asEventListener ( this . config . onCollaborationReady ) ) ;
590+ this . on ( 'editor-update' , asEventListener ( this . config . onEditorUpdate ) ) ;
572591 this . on ( 'content-error' , this . onContentError ) ;
573- this . on ( 'exception' , this . config . onException ) ;
574- this . on ( 'list-definitions-change' , this . config . onListDefinitionsChange ) ;
575- this . on ( 'pagination-update' , this . config . onPaginationUpdate ) ;
592+ this . on ( 'exception' , asEventListener ( this . config . onException ) ) ;
593+ this . on ( 'list-definitions-change' , asEventListener ( this . config . onListDefinitionsChange ) ) ;
594+ this . on ( 'pagination-update' , asEventListener ( this . config . onPaginationUpdate ) ) ;
576595
577596 if ( this . config . onFontsResolved ) {
578597 this . on ( 'fonts-resolved' , this . config . onFontsResolved ) ;
@@ -1248,7 +1267,7 @@ export class SuperDoc extends EventEmitter {
12481267
12491268 this . toolbar = new SuperToolbar ( config ) ;
12501269
1251- this . toolbar . on ( 'exception' , this . config . onException ) ;
1270+ this . toolbar . on ( 'exception' , asEventListener ( this . config . onException ) ) ;
12521271 // `this.toolbar` infers as `SuperToolbar | null` from the field's
12531272 // first assignment in `#addToolbar` (the `null` placeholder a few
12541273 // lines up). The closure registers after the SuperToolbar instance
0 commit comments