-
Notifications
You must be signed in to change notification settings - Fork 464
Open
Description
Description
BookReader can crash during initialization because plugin lifecycle work (plugin construction and/or plugin setup()) runs before br.book is created.
Currently, if a plugin (including downstream integrations’ custom plugins) touches br.book during its constructor(br) or setup() lifecycle, it may dereference undefined and throw. When this happens, BookReader fails to initialize and the UI never renders.
This is particularly noticeable in apps where book metadata or data may load asynchronously — the crash may appear timing-dependent, even if the plugin isn’t doing anything inherently wrong.
Symptoms
- BookReader initialization aborts with an exception; the reader UI never appears.
- The error originates in plugin code but is caused by setup ordering (plugins run before
br.bookexists), making it hard for downstream apps to diagnose.
How to Reproduce
- Register/enable a plugin that references
br.bookduring construction or setup. Minimal example:
class TestPlugin extends BookReaderPlugin {
constructor(br) {
super(br);
br.book.pages; // Accessing book too early
}
}
BookReader.registerPlugin('test_plugin', TestPlugin);- Create a BookReader instance (with or without
dataloaded yet). - Observe the runtime error during initialization.
Evidence / Screenshot
Console error example:
Uncaught TypeError: Cannot read properties of undefined (reading 'pages')
Location:
src/BookReader.js—BookReader.prototype.setup()initialization order (plugins are initialized beforethis.bookis created).
Expected Behavior
br.bookshould exist before plugin construction and before pluginsetup()runs.- Plugins can safely reference
br.book, even if the underlying bookdatahasn’t loaded yet.
Context
- OS: Windows 10 (win32 10.0.26100)
- Browser: (e.g., Chrome 131, Firefox 133)
- BookReader version / commit: (fill in)
Proposal & Constraints
Proposed fix:
- Adjust initialization order in
BookReader.prototype.setup()sothis.bookis created before constructing or setting up plugins.
Implementation notes:
- Assign
this.reduceSet,this.pageProgression,this.protected, andthis.dataearly (soBookModelhas sane defaults). - Create
this.book = new BookModel(this)before plugin construction/setup. - Keep existing plugin setup logic unchanged, but execute it after
this.bookexists.
Constraints / Non-goals:
- Book data does not need to be loaded; this ensures
br.bookexists during early plugin lifecycle. - Does not attempt to make
br.book.pagesmeaningful before data loads — it only prevents crashes.
Verification:
- Add a regression test that registers a plugin accessing
br.book.pagesduring construction, then assertnew BookReader()does not throw.
Metadata
Metadata
Assignees
Labels
No labels