106 lines
3.2 KiB
JavaScript
106 lines
3.2 KiB
JavaScript
/* global window, document */
|
|
import * as svelteInternal from 'svelte/internal'
|
|
// NOTE from 3.38.3 (or so), insert was carrying the hydration logic, that must
|
|
// be used because DOM elements are reused more (and so insertion points are not
|
|
// necessarily added in order); then in 3.40 the logic was moved to
|
|
// insert_hydration, which is the one we must use for HMR
|
|
const svelteInsert = svelteInternal.insert_hydration || svelteInternal.insert
|
|
if (!svelteInsert) {
|
|
throw new Error(
|
|
'failed to find insert_hydration and insert in svelte/internal'
|
|
)
|
|
}
|
|
|
|
import ErrorOverlay from './overlay.js'
|
|
|
|
const removeElement = el => el && el.parentNode && el.parentNode.removeChild(el)
|
|
|
|
export const adapter = class ProxyAdapterDom {
|
|
constructor(instance) {
|
|
this.instance = instance
|
|
this.insertionPoint = null
|
|
|
|
this.afterMount = this.afterMount.bind(this)
|
|
this.rerender = this.rerender.bind(this)
|
|
|
|
this._noOverlay = !!instance.hotOptions.noOverlay
|
|
}
|
|
|
|
// NOTE overlay is only created before being actually shown to help test
|
|
// runner (it won't have to account for error overlay when running assertions
|
|
// about the contents of the rendered page)
|
|
static getErrorOverlay(noCreate = false) {
|
|
if (!noCreate && !this.errorOverlay) {
|
|
this.errorOverlay = ErrorOverlay()
|
|
}
|
|
return this.errorOverlay
|
|
}
|
|
|
|
// TODO this is probably unused now: remove in next breaking release
|
|
static renderCompileError(message) {
|
|
const noCreate = !message
|
|
const overlay = this.getErrorOverlay(noCreate)
|
|
if (!overlay) return
|
|
overlay.setCompileError(message)
|
|
}
|
|
|
|
dispose() {
|
|
// Component is being destroyed, detaching is not optional in Svelte3's
|
|
// component API, so we can dispose of the insertion point in every case.
|
|
if (this.insertionPoint) {
|
|
removeElement(this.insertionPoint)
|
|
this.insertionPoint = null
|
|
}
|
|
this.clearError()
|
|
}
|
|
|
|
// NOTE afterMount CAN be called multiple times (e.g. keyed list)
|
|
afterMount(target, anchor) {
|
|
const {
|
|
instance: { debugName },
|
|
} = this
|
|
if (!this.insertionPoint) {
|
|
this.insertionPoint = document.createComment(debugName)
|
|
}
|
|
svelteInsert(target, this.insertionPoint, anchor)
|
|
}
|
|
|
|
rerender() {
|
|
this.clearError()
|
|
const {
|
|
instance: { refreshComponent },
|
|
insertionPoint,
|
|
} = this
|
|
if (!insertionPoint) {
|
|
throw new Error('Cannot rerender: missing insertion point')
|
|
}
|
|
refreshComponent(insertionPoint.parentNode, insertionPoint)
|
|
}
|
|
|
|
renderError(err) {
|
|
if (this._noOverlay) return
|
|
const {
|
|
instance: { debugName },
|
|
} = this
|
|
const title = debugName || err.moduleName || 'Error'
|
|
this.constructor.getErrorOverlay().addError(err, title)
|
|
}
|
|
|
|
clearError() {
|
|
if (this._noOverlay) return
|
|
const overlay = this.constructor.getErrorOverlay(true)
|
|
if (!overlay) return
|
|
overlay.clearErrors()
|
|
}
|
|
}
|
|
|
|
// TODO this is probably unused now: remove in next breaking release
|
|
if (typeof window !== 'undefined') {
|
|
window.__SVELTE_HMR_ADAPTER = adapter
|
|
}
|
|
|
|
// mitigate situation with Snowpack remote source pulling latest of runtime,
|
|
// but using previous version of the Node code transform in the plugin
|
|
// see: https://github.com/rixo/svelte-hmr/issues/27
|
|
export default adapter
|