Spaces:
Runtime error
Runtime error
File size: 4,472 Bytes
5f5d58c |
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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
/* eslint-env browser */
import { createProxy, hasFatalError } from './proxy.js'
const logPrefix = '[HMR:Svelte]'
// eslint-disable-next-line no-console
const log = (...args) => console.log(logPrefix, ...args)
const domReload = () => {
// eslint-disable-next-line no-undef
const win = typeof window !== 'undefined' && window
if (win && win.location && win.location.reload) {
log('Reload')
win.location.reload()
} else {
log('Full reload required')
}
}
const replaceCss = (previousId, newId) => {
if (typeof document === 'undefined') return false
if (!previousId) return false
if (!newId) return false
// svelte-xxx-style => svelte-xxx
const previousClass = previousId.slice(0, -6)
const newClass = newId.slice(0, -6)
// eslint-disable-next-line no-undef
document.querySelectorAll('.' + previousClass).forEach(el => {
el.classList.remove(previousClass)
el.classList.add(newClass)
})
return true
}
const removeStylesheet = cssId => {
if (cssId == null) return
if (typeof document === 'undefined') return
// eslint-disable-next-line no-undef
const el = document.getElementById(cssId)
if (el) el.remove()
return
}
const defaultArgs = {
reload: domReload,
}
export const makeApplyHmr = transformArgs => args => {
const allArgs = transformArgs({ ...defaultArgs, ...args })
return applyHmr(allArgs)
}
let needsReload = false
function applyHmr(args) {
const {
id,
cssId,
nonCssHash,
reload = domReload,
// normalized hot API (must conform to rollup-plugin-hot)
hot,
hotOptions,
Component,
acceptable, // some types of components are impossible to HMR correctly
preserveLocalState,
ProxyAdapter,
emitCss,
} = args
const existing = hot.data && hot.data.record
const canAccept = acceptable && (!existing || existing.current.canAccept)
const r =
existing ||
createProxy({
Adapter: ProxyAdapter,
id,
Component,
hotOptions,
canAccept,
preserveLocalState,
})
const cssOnly =
hotOptions.injectCss &&
existing &&
nonCssHash &&
existing.current.nonCssHash === nonCssHash
r.update({
Component,
hotOptions,
canAccept,
nonCssHash,
cssId,
previousCssId: r.current.cssId,
cssOnly,
preserveLocalState,
})
hot.dispose(data => {
// handle previous fatal errors
if (needsReload || hasFatalError()) {
if (hotOptions && hotOptions.noReload) {
log('Full reload required')
} else {
reload()
}
}
// 2020-09-21 Snowpack master doesn't pass data as arg to dispose handler
data = data || hot.data
data.record = r
if (!emitCss && cssId && r.current.cssId !== cssId) {
if (hotOptions.cssEjectDelay) {
setTimeout(() => removeStylesheet(cssId), hotOptions.cssEjectDelay)
} else {
removeStylesheet(cssId)
}
}
})
if (canAccept) {
hot.accept(async arg => {
const { bubbled } = arg || {}
// NOTE Snowpack registers accept handlers only once, so we can NOT rely
// on the surrounding scope variables -- they're not the last version!
const { cssId: newCssId, previousCssId } = r.current
const cssChanged = newCssId !== previousCssId
// ensure old style sheet has been removed by now
if (!emitCss && cssChanged) removeStylesheet(previousCssId)
// guard: css only change
if (
// NOTE bubbled is provided only by rollup-plugin-hot, and we
// can't safely assume a CSS only change without it... this means we
// can't support CSS only injection with Nollup or Webpack currently
bubbled === false && // WARNING check false, not falsy!
r.current.cssOnly &&
(!cssChanged || replaceCss(previousCssId, newCssId))
) {
return
}
const success = await r.reload()
if (hasFatalError() || (!success && !hotOptions.optimistic)) {
needsReload = true
}
})
}
// well, endgame... we won't be able to render next updates, even successful,
// if we don't have proxies in svelte's tree
//
// since we won't return the proxy and the app will expect a svelte component,
// it's gonna crash... so it's best to report the real cause
//
// full reload required
//
const proxyOk = r && r.proxy
if (!proxyOk) {
throw new Error(`Failed to create HMR proxy for Svelte component ${id}`)
}
return r.proxy
}
|