You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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