forked from codesandbox/codesandbox-client
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrefresh-transpiler.ts
More file actions
129 lines (109 loc) · 3.73 KB
/
refresh-transpiler.ts
File metadata and controls
129 lines (109 loc) · 3.73 KB
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
import { LoaderContext } from 'sandbox/eval/transpiled-module';
import Transpiler from '..';
const HELPER_PATH = '/node_modules/csbbust/refresh-helper.js';
const HELPER_CODE = `
const Refresh = require('react-refresh/runtime');
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
const enqueueUpdate = () => {
try {
Refresh.performReactRefresh()
} catch (e) {
module.hot.decline();
throw e;
}
}
function isReactRefreshBoundary(moduleExports) {
if (Object.keys(Refresh).length === 0) {
return false;
}
if (Refresh.isLikelyComponentType(moduleExports)) {
return true;
}
if (moduleExports == null || typeof moduleExports !== 'object') {
// Exit if we can't iterate over exports.
return false;
}
let hasExports = false;
let areAllExportsComponents = true;
for (const key in moduleExports) {
hasExports = true;
if (key === '__esModule') {
continue;
}
const desc = Object.getOwnPropertyDescriptor(moduleExports, key);
if (desc && desc.get) {
// Don't invoke getters as they may have side effects.
return false;
}
const exportValue = moduleExports[key];
if (!Refresh.isLikelyComponentType(exportValue)) {
areAllExportsComponents = false;
}
}
return hasExports && areAllExportsComponents;
};
module.exports = {
enqueueUpdate: debounce(enqueueUpdate, 30),
isReactRefreshBoundary
};
`.trim();
/**
* `var prevRefreshReg = window.$RefreshReg$;
var prevRefreshSig = window.$RefreshSig$;
var RefreshRuntime = require('react-refresh/runtime');
window.$RefreshReg$ = (type, id) => {
// Note module.id is webpack-specific, this may vary in other bundlers
const fullId = module.id + ' ' + id;
RefreshRuntime.register(type, fullId);
}
window.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;
try {
${sourceCode}
} finally {
window.$RefreshReg$ = prevRefreshReg;
window.$RefreshSig$ = prevRefreshSig;
}
const _csbRefreshUtils = require('${HELPER_PATH}');
if (_csbRefreshUtils.isReactRefreshBoundary && _csbRefreshUtils.isReactRefreshBoundary(module.exports)) {
module.hot.accept();
_csbRefreshUtils.enqueueUpdate();
}
`
*/
/**
* This is the compressed version of the code in the comment above. We compress the code
* to a single line so we don't mess with the source mapping when showing errors.
*/
const getWrapperCode = (sourceCode: string) =>
`var prevRefreshReg=window.$RefreshReg$,prevRefreshSig=window.$RefreshSig$,RefreshRuntime=require("react-refresh/runtime");window.$RefreshReg$=(a,b)=>{const c=module.id+" "+b;RefreshRuntime.register(a,c)},window.$RefreshSig$=RefreshRuntime.createSignatureFunctionForTransform;try{${sourceCode}
}finally{window.$RefreshReg$=prevRefreshReg,window.$RefreshSig$=prevRefreshSig}const _csbRefreshUtils=require("${HELPER_PATH}");_csbRefreshUtils.isReactRefreshBoundary&&_csbRefreshUtils.isReactRefreshBoundary(module.exports)&&(module.hot.accept(),_csbRefreshUtils.enqueueUpdate());
`.trim();
class RefreshTranspiler extends Transpiler {
constructor() {
super('refresh-loader');
}
doTranspilation(code: string, loaderContext: LoaderContext) {
loaderContext.addDependency('react-refresh/runtime');
loaderContext.emitModule(HELPER_PATH, HELPER_CODE, '/', false, false);
const newCode = getWrapperCode(code);
return Promise.resolve({
transpiledCode: newCode || '',
});
}
}
const transpiler = new RefreshTranspiler();
export { RefreshTranspiler };
export default transpiler;