Add destroy method

Which revokes all blob URLs and removes the element from document.
This commit is contained in:
John Factotum
2023-05-09 14:02:07 +08:00
parent a817932b08
commit 5da3be5200
7 changed files with 45 additions and 5 deletions
+4
View File
@@ -36,5 +36,9 @@ export const makeComicBook = ({ entries, loadBlob, getSize }, file) => {
book.resolveHref = href => ({ index: book.sections.findIndex(s => s.id === href) })
book.splitTOCHref = href => [href, null]
book.getTOCFragment = doc => doc.documentElement
book.destroy = () => {
for (const arr of urls.values())
for (const url of arr) URL.revokeObjectURL(url)
}
return book
}
+10 -3
View File
@@ -611,6 +611,9 @@ class Loader {
unloadItem(item) {
this.unref(item?.href)
}
destroy() {
for (const url of this.#cache.values()) URL.revokeObjectURL(url)
}
}
const getHTMLFragment = (doc, id) => doc.getElementById(id)
@@ -628,6 +631,7 @@ const getPageSpread = properties => {
export class EPUB {
parser = new DOMParser()
#loader
#encryption
constructor({ loadText, loadBlob, getSize, sha1 }) {
this.loadText = loadText
@@ -662,7 +666,7 @@ export class EPUB {
opf,
resolveHref: url => resolveURL(url, opfPath),
})
const loader = new Loader({
this.#loader = new Loader({
loadText: this.loadText,
loadBlob: uri => Promise.resolve(this.loadBlob(uri))
.then(this.#encryption.getDecoder(uri)),
@@ -677,8 +681,8 @@ export class EPUB {
}
return {
id: this.resources.getItemByID(idref)?.href,
load: () => loader.loadItem(item),
unload: () => loader.unloadItem(item),
load: () => this.#loader.loadItem(item),
unload: () => this.#loader.unloadItem(item),
createDocument: () => this.loadDocument(item),
size: this.getSize(item.href),
cfi: this.resources.cfis[index],
@@ -805,4 +809,7 @@ export class EPUB {
return JSON.parse(json)
}
}
destroy() {
this.#loader?.destroy()
}
}
+5
View File
@@ -272,6 +272,7 @@ export const makeFB2 = async blob => {
}), converted]
})
const urls = []
const sectionData = bodyData[0][0]
// make a separate section for each section in the first body
.map(({ el, ids }) => {
@@ -294,6 +295,7 @@ export const makeFB2 = async blob => {
const str = template(el.outerHTML)
const blob = new Blob([str], { type: MIME.XHTML })
const url = URL.createObjectURL(blob)
urls.push(url)
const title = normalizeWhitespace(
el.querySelector('.title, .subtitle, p')?.textContent
?? (el.classList.contains('title') ? el.textContent : ''))
@@ -338,5 +340,8 @@ export const makeFB2 = async blob => {
book.splitTOCHref = href => href?.split('#')?.map(x => Number(x)) ?? []
book.getTOCFragment = (doc, id) => doc.querySelector(`[${dataID}="${id}"]`)
book.destroy = () => {
for (const url of urls) URL.revokeObjectURL(url)
}
return book
}
+9 -1
View File
@@ -30,6 +30,7 @@ const getViewport = (doc, viewport) => {
}
class Container {
#observer = new ResizeObserver(() => this.render())
#element = document.createElement('div')
defaultViewport
spread
@@ -46,7 +47,7 @@ class Container {
justifyContent: 'center',
alignItems: 'center',
})
new ResizeObserver(() => this.render()).observe(this.#element)
this.#observer.observe(this.#element)
}
get element() {
return this.#element
@@ -170,6 +171,10 @@ class Container {
return true
}
}
destroy() {
this.#observer.unobserve(this.#element)
this.#element.remove()
}
}
export class FixedLayout {
@@ -289,4 +294,7 @@ export class FixedLayout {
for (const frame of this.#container.element.querySelectorAll('iframe'))
frame.contentWindow.getSelection().removeAllRanges()
}
destroy() {
this.#container.destroy()
}
}
+7
View File
@@ -842,6 +842,10 @@ class MOBI6 {
isExternal(uri) {
return /^(?!blob|filepos)\w+:/i.test(uri)
}
destroy() {
for (const url of this.#resourceCache.values()) URL.revokeObjectURL(url)
for (const url of this.#cache.values()) URL.revokeObjectURL(url)
}
}
// handlers for `kindle:` uris
@@ -1154,4 +1158,7 @@ class KF8 {
isExternal(uri) {
return /^(?!blob|kindle)\w+:/i.test(uri)
}
destroy() {
for (const url of this.#cache.values()) URL.revokeObjectURL(url)
}
}
+6 -1
View File
@@ -329,6 +329,7 @@ class View {
export class Paginator {
#gap = 0
#shouldUpdateGap = true
#observer = new ResizeObserver(() => this.render())
#element = document.createElement('div')
#background = document.createElement('div')
#maxSizeContainer = document.createElement('div')
@@ -394,7 +395,7 @@ export class Paginator {
this.#maxSizeContainer.append(this.#header)
this.#maxSizeContainer.append(this.#footer)
new ResizeObserver(() => this.render()).observe(this.#element)
this.#observer.observe(this.#element)
this.#container.addEventListener('scroll', debounce(() => {
if (this.scrolled) this.#afterScroll('scroll')
}, 250))
@@ -774,4 +775,8 @@ export class Paginator {
this.#anchor = anchor
await this.#scrollToAnchor(select)
}
destroy() {
this.#observer.unobserve(this.#element)
this.#element.remove()
}
}
+4
View File
@@ -270,4 +270,8 @@ export class View {
subitems: result.subitems,
} : result
}
destroy() {
this.book.destroy?.()
this.renderer?.destroy?.()
}
}