UNPKG

2.15 kBJavaScriptView Raw
1import { makeApplyHmr } from 'svelte-hmr/runtime';
2
3// eslint-disable-next-line no-undef
4const g = typeof window !== 'undefined' ? window : global;
5
6const globalKey =
7 typeof Symbol !== 'undefined'
8 ? Symbol('SVELTE_LOADER_HOT')
9 : '__SVELTE_LOADER_HOT';
10
11if (!g[globalKey]) {
12 // do updating refs counting to know when a full update has been applied
13 let updatingCount = 0;
14
15 const notifyStart = () => {
16 updatingCount++;
17 };
18
19 const notifyError = reload => err => {
20 const errString = (err && err.stack) || err;
21 // eslint-disable-next-line no-console
22 console.error(
23 '[HMR] Failed to accept update (nollup compat mode)',
24 errString
25 );
26 reload();
27 notifyEnd();
28 };
29
30 const notifyEnd = () => {
31 updatingCount--;
32 if (updatingCount === 0) {
33 // NOTE this message is important for timing in tests
34 // eslint-disable-next-line no-console
35 console.log('[HMR:Svelte] Up to date');
36 }
37 };
38
39 g[globalKey] = {
40 hotStates: {},
41 notifyStart,
42 notifyError,
43 notifyEnd,
44 };
45}
46
47const runAcceptHandlers = acceptHandlers => {
48 const queue = [...acceptHandlers];
49 const next = () => {
50 const cur = queue.shift();
51 if (cur) {
52 return cur(null).then(next);
53 } else {
54 return Promise.resolve(null);
55 }
56 };
57 return next();
58};
59
60export const applyHmr = makeApplyHmr(args => {
61 const { notifyStart, notifyError, notifyEnd } = g[globalKey];
62 const { m, reload } = args;
63
64 let acceptHandlers = (m.hot.data && m.hot.data.acceptHandlers) || [];
65 let nextAcceptHandlers = [];
66
67 m.hot.dispose(data => {
68 data.acceptHandlers = nextAcceptHandlers;
69 });
70
71 const dispose = (...args) => m.hot.dispose(...args);
72
73 const accept = handler => {
74 if (nextAcceptHandlers.length === 0) {
75 m.hot.accept();
76 }
77 nextAcceptHandlers.push(handler);
78 };
79
80 const check = status => {
81 if (status === 'ready') {
82 notifyStart();
83 } else if (status === 'idle') {
84 runAcceptHandlers(acceptHandlers)
85 .then(notifyEnd)
86 .catch(notifyError(reload));
87 }
88 };
89
90 m.hot.addStatusHandler(check);
91
92 m.hot.dispose(() => {
93 m.hot.removeStatusHandler(check);
94 });
95
96 const hot = {
97 data: m.hot.data,
98 dispose,
99 accept,
100 };
101
102 return { ...args, hot };
103});