Skip to content

Commit b9bb193

Browse files
authored
fix: backport #921 to 0.5.x (#922)
fix: backport #921 to 0.5.x
1 parent a106ec7 commit b9bb193

File tree

2 files changed

+112
-108
lines changed

2 files changed

+112
-108
lines changed

lib/utils/makeRefreshRuntimeModule.js

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
/**
22
* Makes a runtime module to intercept module execution for React Refresh.
3-
* This module creates an isolated __webpak_require__ function for each module
4-
* and injects a $Refresh$ object into it for use by react-refresh.
3+
* This module creates an isolated `__webpack_require__` function for each module,
4+
* and injects a `$Refresh$` object into it for use by React Refresh.
55
* @param {import('webpack')} webpack The Webpack exports.
6-
* @returns {ReactRefreshRuntimeModule} The runtime module class.
6+
* @returns {new () => import('webpack').RuntimeModule} The runtime module class.
77
*/
88
function makeRefreshRuntimeModule(webpack) {
99
return class ReactRefreshRuntimeModule extends webpack.RuntimeModule {
@@ -17,6 +17,8 @@ function makeRefreshRuntimeModule(webpack) {
1717
* @returns {string} runtime code
1818
*/
1919
generate() {
20+
if (!this.compilation) throw new Error('Webpack compilation missing!');
21+
2022
const { runtimeTemplate } = this.compilation;
2123
const declareVar = runtimeTemplate.supportsConst() ? 'const' : 'var';
2224
return webpack.Template.asString([
@@ -48,40 +50,42 @@ function makeRefreshRuntimeModule(webpack) {
4850
'options',
4951
[
5052
`${declareVar} originalFactory = options.factory;`,
51-
`options.factory = ${runtimeTemplate.basicFunction(
52-
['moduleObject', 'moduleExports', 'webpackRequire'],
53-
[
54-
// Our require function delegates to the original require function
55-
`${declareVar} hotRequire = ${runtimeTemplate.returningFunction(
56-
'webpackRequire(request)',
57-
'request'
58-
)};`,
59-
// The propery descriptor factory below ensures that all properties but $Refresh$ are proxied through to the original require function
60-
`${declareVar} createPropertyDescriptor = ${runtimeTemplate.basicFunction('name', [
61-
`return {`,
62-
webpack.Template.indent([
63-
`configurable: true,`,
64-
`enumerable: true,`,
65-
`get: ${runtimeTemplate.returningFunction('webpackRequire[name]')},`,
66-
`set: ${runtimeTemplate.basicFunction('value', [
67-
'webpackRequire[name] = value;',
68-
])},`,
69-
]),
70-
`};`,
71-
])};`,
72-
`for (${declareVar} name in webpackRequire) {`,
53+
// Using a function declaration -
54+
// ensures `this` would propagate for modules relying on it
55+
`options.factory = function(moduleObject, moduleExports, webpackRequire) {`,
56+
webpack.Template.indent([
57+
// Our require function delegates to the original require function
58+
`${declareVar} hotRequire = ${runtimeTemplate.returningFunction(
59+
'webpackRequire(request)',
60+
'request'
61+
)};`,
62+
// The propery descriptor factory below ensures all properties but `$Refresh$`
63+
// are proxied through to the original require function
64+
`${declareVar} createPropertyDescriptor = ${runtimeTemplate.basicFunction('name', [
65+
`return {`,
7366
webpack.Template.indent([
74-
`if (Object.prototype.hasOwnProperty.call(webpackRequire, name) && name !== "$Refresh$") {`,
75-
webpack.Template.indent([
76-
`Object.defineProperty(hotRequire, name, createPropertyDescriptor(name));`,
77-
]),
78-
`}`,
67+
`configurable: true,`,
68+
`enumerable: true,`,
69+
`get: ${runtimeTemplate.returningFunction('webpackRequire[name]')},`,
70+
`set: ${runtimeTemplate.basicFunction('value', [
71+
'webpackRequire[name] = value;',
72+
])},`,
73+
]),
74+
`};`,
75+
])};`,
76+
`for (${declareVar} name in webpackRequire) {`,
77+
webpack.Template.indent([
78+
`if (Object.prototype.hasOwnProperty.call(webpackRequire, name) && name !== "$Refresh$") {`,
79+
webpack.Template.indent([
80+
`Object.defineProperty(hotRequire, name, createPropertyDescriptor(name));`,
7981
]),
8082
`}`,
81-
`hotRequire.$Refresh$ = setup(options.id);`,
82-
`originalFactory.call(this, moduleObject, moduleExports, hotRequire);`,
83-
]
84-
)};`,
83+
]),
84+
`}`,
85+
`hotRequire.$Refresh$ = setup(options.id);`,
86+
`originalFactory.call(this, moduleObject, moduleExports, hotRequire);`,
87+
]),
88+
'};',
8589
]
8690
)});`,
8791
]);

test/unit/makeRefreshRuntimeModule.test.js

Lines changed: 74 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -38,46 +38,46 @@ describe.skipIf(WEBPACK_VERSION !== 5, 'makeRefreshRuntimeModule', () => {
3838

3939
const runtime = instance.generate();
4040
expect(runtime).toMatchInlineSnapshot(`
41-
"var setup = function(moduleId) {
42-
var refresh = {
43-
moduleId: moduleId,
44-
register: function(type, id) {
45-
var typeId = moduleId + " " + id;
46-
refresh.runtime.register(type, typeId);
47-
},
48-
signature: function() { return refresh.runtime.createSignatureFunctionForTransform(); },
49-
runtime: {
50-
createSignatureFunctionForTransform: function() { return function(type) { return type; }; },
51-
register: function() {}
41+
"var setup = function(moduleId) {
42+
var refresh = {
43+
moduleId: moduleId,
44+
register: function(type, id) {
45+
var typeId = moduleId + " " + id;
46+
refresh.runtime.register(type, typeId);
47+
},
48+
signature: function() { return refresh.runtime.createSignatureFunctionForTransform(); },
49+
runtime: {
50+
createSignatureFunctionForTransform: function() { return function(type) { return type; }; },
51+
register: function() {}
52+
},
53+
};
54+
return refresh;
55+
}
56+
57+
__webpack_require__.i.push(function(options) {
58+
var originalFactory = options.factory;
59+
options.factory = function(moduleObject, moduleExports, webpackRequire) {
60+
var hotRequire = function(request) { return webpackRequire(request); };
61+
var createPropertyDescriptor = function(name) {
62+
return {
63+
configurable: true,
64+
enumerable: true,
65+
get: function() { return webpackRequire[name]; },
66+
set: function(value) {
67+
webpackRequire[name] = value;
5268
},
5369
};
54-
return refresh;
70+
};
71+
for (var name in webpackRequire) {
72+
if (Object.prototype.hasOwnProperty.call(webpackRequire, name) && name !== "$Refresh$") {
73+
Object.defineProperty(hotRequire, name, createPropertyDescriptor(name));
74+
}
5575
}
56-
57-
__webpack_require__.i.push(function(options) {
58-
var originalFactory = options.factory;
59-
options.factory = function(moduleObject,moduleExports,webpackRequire) {
60-
var hotRequire = function(request) { return webpackRequire(request); };
61-
var createPropertyDescriptor = function(name) {
62-
return {
63-
configurable: true,
64-
enumerable: true,
65-
get: function() { return webpackRequire[name]; },
66-
set: function(value) {
67-
webpackRequire[name] = value;
68-
},
69-
};
70-
};
71-
for (var name in webpackRequire) {
72-
if (Object.prototype.hasOwnProperty.call(webpackRequire, name) && name !== "$Refresh$") {
73-
Object.defineProperty(hotRequire, name, createPropertyDescriptor(name));
74-
}
75-
}
76-
hotRequire.$Refresh$ = setup(options.id);
77-
originalFactory.call(this, moduleObject, moduleExports, hotRequire);
78-
};
79-
});"
80-
`);
76+
hotRequire.$Refresh$ = setup(options.id);
77+
originalFactory.call(this, moduleObject, moduleExports, hotRequire);
78+
};
79+
});"
80+
`);
8181
expect(() => {
8282
eval(runtime);
8383
}).not.toThrow();
@@ -99,46 +99,46 @@ describe.skipIf(WEBPACK_VERSION !== 5, 'makeRefreshRuntimeModule', () => {
9999

100100
const runtime = instance.generate();
101101
expect(runtime).toMatchInlineSnapshot(`
102-
"const setup = (moduleId) => {
103-
const refresh = {
104-
moduleId: moduleId,
105-
register: (type, id) => {
106-
const typeId = moduleId + " " + id;
107-
refresh.runtime.register(type, typeId);
108-
},
109-
signature: () => (refresh.runtime.createSignatureFunctionForTransform()),
110-
runtime: {
111-
createSignatureFunctionForTransform: () => ((type) => (type)),
112-
register: x => {}
102+
"const setup = (moduleId) => {
103+
const refresh = {
104+
moduleId: moduleId,
105+
register: (type, id) => {
106+
const typeId = moduleId + " " + id;
107+
refresh.runtime.register(type, typeId);
108+
},
109+
signature: () => (refresh.runtime.createSignatureFunctionForTransform()),
110+
runtime: {
111+
createSignatureFunctionForTransform: () => ((type) => (type)),
112+
register: x => {}
113+
},
114+
};
115+
return refresh;
116+
}
117+
118+
__webpack_require__.i.push((options) => {
119+
const originalFactory = options.factory;
120+
options.factory = function(moduleObject, moduleExports, webpackRequire) {
121+
const hotRequire = (request) => (webpackRequire(request));
122+
const createPropertyDescriptor = (name) => {
123+
return {
124+
configurable: true,
125+
enumerable: true,
126+
get: () => (webpackRequire[name]),
127+
set: (value) => {
128+
webpackRequire[name] = value;
113129
},
114130
};
115-
return refresh;
131+
};
132+
for (const name in webpackRequire) {
133+
if (Object.prototype.hasOwnProperty.call(webpackRequire, name) && name !== "$Refresh$") {
134+
Object.defineProperty(hotRequire, name, createPropertyDescriptor(name));
135+
}
116136
}
117-
118-
__webpack_require__.i.push((options) => {
119-
const originalFactory = options.factory;
120-
options.factory = (moduleObject,moduleExports,webpackRequire) => {
121-
const hotRequire = (request) => (webpackRequire(request));
122-
const createPropertyDescriptor = (name) => {
123-
return {
124-
configurable: true,
125-
enumerable: true,
126-
get: () => (webpackRequire[name]),
127-
set: (value) => {
128-
webpackRequire[name] = value;
129-
},
130-
};
131-
};
132-
for (const name in webpackRequire) {
133-
if (Object.prototype.hasOwnProperty.call(webpackRequire, name) && name !== "$Refresh$") {
134-
Object.defineProperty(hotRequire, name, createPropertyDescriptor(name));
135-
}
136-
}
137-
hotRequire.$Refresh$ = setup(options.id);
138-
originalFactory.call(this, moduleObject, moduleExports, hotRequire);
139-
};
140-
});"
141-
`);
137+
hotRequire.$Refresh$ = setup(options.id);
138+
originalFactory.call(this, moduleObject, moduleExports, hotRequire);
139+
};
140+
});"
141+
`);
142142
expect(() => {
143143
eval(runtime);
144144
}).not.toThrow();

0 commit comments

Comments
 (0)