forked from sveltejs/svelte-hmr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
proxy-adapter-dom.js
105 lines (91 loc) · 3.2 KB
/
proxy-adapter-dom.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/* 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