Update package dependencies and remove unused files from node_modules
This commit is contained in:
427
node_modules/svelte-hmr/runtime/proxy.js
generated
vendored
Normal file
427
node_modules/svelte-hmr/runtime/proxy.js
generated
vendored
Normal file
@@ -0,0 +1,427 @@
|
||||
/* eslint-env browser */
|
||||
/**
|
||||
* The HMR proxy is a component-like object whose task is to sit in the
|
||||
* component tree in place of the proxied component, and rerender each
|
||||
* successive versions of said component.
|
||||
*/
|
||||
|
||||
import { createProxiedComponent } from './svelte-hooks.js'
|
||||
|
||||
const handledMethods = ['constructor', '$destroy']
|
||||
const forwardedMethods = ['$set', '$on']
|
||||
|
||||
const logError = (msg, err) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('[HMR][Svelte]', msg)
|
||||
if (err) {
|
||||
// NOTE avoid too much wrapping around user errors
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err)
|
||||
}
|
||||
}
|
||||
|
||||
const posixify = file => file.replace(/[/\\]/g, '/')
|
||||
|
||||
const getBaseName = id =>
|
||||
id
|
||||
.split('/')
|
||||
.pop()
|
||||
.split('.')
|
||||
.slice(0, -1)
|
||||
.join('.')
|
||||
|
||||
const capitalize = str => str[0].toUpperCase() + str.slice(1)
|
||||
|
||||
const getFriendlyName = id => capitalize(getBaseName(posixify(id)))
|
||||
|
||||
const getDebugName = id => `<${getFriendlyName(id)}>`
|
||||
|
||||
const relayCalls = (getTarget, names, dest = {}) => {
|
||||
for (const key of names) {
|
||||
dest[key] = function(...args) {
|
||||
const target = getTarget()
|
||||
if (!target) {
|
||||
return
|
||||
}
|
||||
return target[key] && target[key].call(this, ...args)
|
||||
}
|
||||
}
|
||||
return dest
|
||||
}
|
||||
|
||||
const isInternal = key => key !== '$$' && key.slice(0, 2) === '$$'
|
||||
|
||||
// This is intented as a somewhat generic / prospective fix to the situation
|
||||
// that arised with the introduction of $$set in Svelte 3.24.1 -- trying to
|
||||
// avoid giving full knowledge (like its name) of this implementation detail
|
||||
// to the proxy. The $$set method can be present or not on the component, and
|
||||
// its presence impacts the behaviour (but with HMR it will be tested if it is
|
||||
// present _on the proxy_). So the idea here is to expose exactly the same $$
|
||||
// props as the current version of the component and, for those that are
|
||||
// functions, proxy the calls to the current component.
|
||||
const relayInternalMethods = (proxy, cmp) => {
|
||||
// delete any previously added $$ prop
|
||||
Object.keys(proxy)
|
||||
.filter(isInternal)
|
||||
.forEach(key => {
|
||||
delete proxy[key]
|
||||
})
|
||||
// guard: no component
|
||||
if (!cmp) return
|
||||
// proxy current $$ props to the actual component
|
||||
Object.keys(cmp)
|
||||
.filter(isInternal)
|
||||
.forEach(key => {
|
||||
Object.defineProperty(proxy, key, {
|
||||
configurable: true,
|
||||
get() {
|
||||
const value = cmp[key]
|
||||
if (typeof value !== 'function') return value
|
||||
return (
|
||||
value &&
|
||||
function(...args) {
|
||||
return value.apply(this, args)
|
||||
}
|
||||
)
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// proxy custom methods
|
||||
const copyComponentProperties = (proxy, cmp, previous) => {
|
||||
if (previous) {
|
||||
previous.forEach(prop => {
|
||||
delete proxy[prop]
|
||||
})
|
||||
}
|
||||
|
||||
const props = Object.getOwnPropertyNames(Object.getPrototypeOf(cmp))
|
||||
const wrappedProps = props.filter(prop => {
|
||||
if (!handledMethods.includes(prop) && !forwardedMethods.includes(prop)) {
|
||||
Object.defineProperty(proxy, prop, {
|
||||
configurable: true,
|
||||
get() {
|
||||
return cmp[prop]
|
||||
},
|
||||
set(value) {
|
||||
// we're changing it on the real component first to see what it
|
||||
// gives... if it throws an error, we want to throw the same error in
|
||||
// order to most closely follow non-hmr behaviour.
|
||||
cmp[prop] = value
|
||||
},
|
||||
})
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
return wrappedProps
|
||||
}
|
||||
|
||||
// everything in the constructor!
|
||||
//
|
||||
// so we don't polute the component class with new members
|
||||
//
|
||||
class ProxyComponent {
|
||||
constructor(
|
||||
{
|
||||
Adapter,
|
||||
id,
|
||||
debugName,
|
||||
current, // { Component, hotOptions: { preserveLocalState, ... } }
|
||||
register,
|
||||
},
|
||||
options // { target, anchor, ... }
|
||||
) {
|
||||
let cmp
|
||||
let disposed = false
|
||||
let lastError = null
|
||||
|
||||
const setComponent = _cmp => {
|
||||
cmp = _cmp
|
||||
relayInternalMethods(this, cmp)
|
||||
}
|
||||
|
||||
const getComponent = () => cmp
|
||||
|
||||
const destroyComponent = () => {
|
||||
// destroyComponent is tolerant (don't crash on no cmp) because it
|
||||
// is possible that reload/rerender is called after a previous
|
||||
// createComponent has failed (hence we have a proxy, but no cmp)
|
||||
if (cmp) {
|
||||
cmp.$destroy()
|
||||
setComponent(null)
|
||||
}
|
||||
}
|
||||
|
||||
const refreshComponent = (target, anchor, conservativeDestroy) => {
|
||||
if (lastError) {
|
||||
lastError = null
|
||||
adapter.rerender()
|
||||
} else {
|
||||
try {
|
||||
const replaceOptions = {
|
||||
target,
|
||||
anchor,
|
||||
preserveLocalState: current.preserveLocalState,
|
||||
}
|
||||
if (conservativeDestroy) {
|
||||
replaceOptions.conservativeDestroy = true
|
||||
}
|
||||
cmp.$replace(current.Component, replaceOptions)
|
||||
} catch (err) {
|
||||
setError(err, target, anchor)
|
||||
if (
|
||||
!current.hotOptions.optimistic ||
|
||||
// non acceptable components (that is components that have to defer
|
||||
// to their parent for rerender -- e.g. accessors, named exports)
|
||||
// are most tricky, and they havent been considered when most of the
|
||||
// code has been written... as a result, they are especially tricky
|
||||
// to deal with, it's better to consider any error with them to be
|
||||
// fatal to avoid odities
|
||||
!current.canAccept ||
|
||||
(err && err.hmrFatal)
|
||||
) {
|
||||
throw err
|
||||
} else {
|
||||
// const errString = String((err && err.stack) || err)
|
||||
logError(`Error during component init: ${debugName}`, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const setError = err => {
|
||||
lastError = err
|
||||
adapter.renderError(err)
|
||||
}
|
||||
|
||||
const instance = {
|
||||
hotOptions: current.hotOptions,
|
||||
proxy: this,
|
||||
id,
|
||||
debugName,
|
||||
refreshComponent,
|
||||
}
|
||||
|
||||
const adapter = new Adapter(instance)
|
||||
|
||||
const { afterMount, rerender } = adapter
|
||||
|
||||
// $destroy is not called when a child component is disposed, so we
|
||||
// need to hook from fragment.
|
||||
const onDestroy = () => {
|
||||
// NOTE do NOT call $destroy on the cmp from here; the cmp is already
|
||||
// dead, this would not work
|
||||
if (!disposed) {
|
||||
disposed = true
|
||||
adapter.dispose()
|
||||
unregister()
|
||||
}
|
||||
}
|
||||
|
||||
// ---- register proxy instance ----
|
||||
|
||||
const unregister = register(rerender)
|
||||
|
||||
// ---- augmented methods ----
|
||||
|
||||
this.$destroy = () => {
|
||||
destroyComponent()
|
||||
onDestroy()
|
||||
}
|
||||
|
||||
// ---- forwarded methods ----
|
||||
|
||||
relayCalls(getComponent, forwardedMethods, this)
|
||||
|
||||
// ---- create & mount target component instance ---
|
||||
|
||||
try {
|
||||
let lastProperties
|
||||
createProxiedComponent(current.Component, options, {
|
||||
allowLiveBinding: current.hotOptions.allowLiveBinding,
|
||||
onDestroy,
|
||||
onMount: afterMount,
|
||||
onInstance: comp => {
|
||||
setComponent(comp)
|
||||
// WARNING the proxy MUST use the same $$ object as its component
|
||||
// instance, because a lot of wiring happens during component
|
||||
// initialisation... lots of references to $$ and $$.fragment have
|
||||
// already been distributed around when the component constructor
|
||||
// returns, before we have a chance to wrap them (and so we can't
|
||||
// wrap them no more, because existing references would become
|
||||
// invalid)
|
||||
this.$$ = comp.$$
|
||||
lastProperties = copyComponentProperties(this, comp, lastProperties)
|
||||
},
|
||||
})
|
||||
} catch (err) {
|
||||
const { target, anchor } = options
|
||||
setError(err, target, anchor)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const syncStatics = (component, proxy, previousKeys) => {
|
||||
// remove previously copied keys
|
||||
if (previousKeys) {
|
||||
for (const key of previousKeys) {
|
||||
delete proxy[key]
|
||||
}
|
||||
}
|
||||
|
||||
// forward static properties and methods
|
||||
const keys = []
|
||||
for (const key in component) {
|
||||
keys.push(key)
|
||||
proxy[key] = component[key]
|
||||
}
|
||||
|
||||
return keys
|
||||
}
|
||||
|
||||
const globalListeners = {}
|
||||
|
||||
const onGlobal = (event, fn) => {
|
||||
event = event.toLowerCase()
|
||||
if (!globalListeners[event]) globalListeners[event] = []
|
||||
globalListeners[event].push(fn)
|
||||
}
|
||||
|
||||
const fireGlobal = (event, ...args) => {
|
||||
const listeners = globalListeners[event]
|
||||
if (!listeners) return
|
||||
for (const fn of listeners) {
|
||||
fn(...args)
|
||||
}
|
||||
}
|
||||
|
||||
const fireBeforeUpdate = () => fireGlobal('beforeupdate')
|
||||
|
||||
const fireAfterUpdate = () => fireGlobal('afterupdate')
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
window.__SVELTE_HMR = {
|
||||
on: onGlobal,
|
||||
}
|
||||
window.dispatchEvent(new CustomEvent('svelte-hmr:ready'))
|
||||
}
|
||||
|
||||
let fatalError = false
|
||||
|
||||
export const hasFatalError = () => fatalError
|
||||
|
||||
/**
|
||||
* Creates a HMR proxy and its associated `reload` function that pushes a new
|
||||
* version to all existing instances of the component.
|
||||
*/
|
||||
export function createProxy({
|
||||
Adapter,
|
||||
id,
|
||||
Component,
|
||||
hotOptions,
|
||||
canAccept,
|
||||
preserveLocalState,
|
||||
}) {
|
||||
const debugName = getDebugName(id)
|
||||
const instances = []
|
||||
|
||||
// current object will be updated, proxy instances will keep a ref
|
||||
const current = {
|
||||
Component,
|
||||
hotOptions,
|
||||
canAccept,
|
||||
preserveLocalState,
|
||||
}
|
||||
|
||||
const name = `Proxy${debugName}`
|
||||
|
||||
// this trick gives the dynamic name Proxy<MyComponent> to the concrete
|
||||
// proxy class... unfortunately, this doesn't shows in dev tools, but
|
||||
// it stills allow to inspect cmp.constructor.name to confirm an instance
|
||||
// is a proxy
|
||||
const proxy = {
|
||||
[name]: class extends ProxyComponent {
|
||||
constructor(options) {
|
||||
try {
|
||||
super(
|
||||
{
|
||||
Adapter,
|
||||
id,
|
||||
debugName,
|
||||
current,
|
||||
register: rerender => {
|
||||
instances.push(rerender)
|
||||
const unregister = () => {
|
||||
const i = instances.indexOf(rerender)
|
||||
instances.splice(i, 1)
|
||||
}
|
||||
return unregister
|
||||
},
|
||||
},
|
||||
options
|
||||
)
|
||||
} catch (err) {
|
||||
// If we fail to create a proxy instance, any instance, that means
|
||||
// that we won't be able to fix this instance when it is updated.
|
||||
// Recovering to normal state will be impossible. HMR's dead.
|
||||
//
|
||||
// Fatal error will trigger a full reload on next update (reloading
|
||||
// right now is kinda pointless since buggy code still exists).
|
||||
//
|
||||
// NOTE Only report first error to avoid too much polution -- following
|
||||
// errors are probably caused by the first one, or they will show up
|
||||
// in turn when the first one is fixed ¯\_(ツ)_/¯
|
||||
//
|
||||
if (!fatalError) {
|
||||
fatalError = true
|
||||
logError(
|
||||
`Unrecoverable HMR error in ${debugName}: ` +
|
||||
`next update will trigger a full reload`
|
||||
)
|
||||
}
|
||||
throw err
|
||||
}
|
||||
}
|
||||
},
|
||||
}[name]
|
||||
|
||||
// initialize static members
|
||||
let previousStatics = syncStatics(current.Component, proxy)
|
||||
|
||||
const update = newState => Object.assign(current, newState)
|
||||
|
||||
// reload all existing instances of this component
|
||||
const reload = () => {
|
||||
fireBeforeUpdate()
|
||||
|
||||
// copy statics before doing anything because a static prop/method
|
||||
// could be used somewhere in the create/render call
|
||||
previousStatics = syncStatics(current.Component, proxy, previousStatics)
|
||||
|
||||
const errors = []
|
||||
|
||||
instances.forEach(rerender => {
|
||||
try {
|
||||
rerender()
|
||||
} catch (err) {
|
||||
logError(`Failed to rerender ${debugName}`, err)
|
||||
errors.push(err)
|
||||
}
|
||||
})
|
||||
|
||||
if (errors.length > 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
fireAfterUpdate()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
const hasFatalError = () => fatalError
|
||||
|
||||
return { id, proxy, update, reload, hasFatalError, current }
|
||||
}
|
Reference in New Issue
Block a user