Skip to content

Commit 967adbd

Browse files
Merge branch 'master' into rm-3rd-party-tests
2 parents 5f607fe + 0dd1ee6 commit 967adbd

21 files changed

+450
-204
lines changed

.eslintrc.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,21 @@ module.exports = {
2121
"prefer-rest-params": "off",
2222
strict: ["error", "safe"],
2323
"global-require": "off",
24+
"spaced-comment": [
25+
"error",
26+
"always",
27+
{
28+
line: {
29+
exceptions: ["-", "+"],
30+
markers: ["=", "!", "/"],
31+
},
32+
block: {
33+
exceptions: ["-", "+"],
34+
markers: ["=", "!"],
35+
balanced: false,
36+
},
37+
},
38+
],
2439
},
2540
overrides: [
2641
{

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
44

5+
### [4.7.1](https://github.com/webpack/webpack-dev-server/compare/v4.7.0...v4.7.1) (2021-12-22)
6+
7+
8+
### Bug Fixes
9+
10+
* removed `url` package, fixed compatibility with future webpack defaults ([#4132](https://github.com/webpack/webpack-dev-server/issues/4132)) ([4e5d8ea](https://github.com/webpack/webpack-dev-server/commit/4e5d8eae654ef382697722c6406dbc96207594aa))
11+
512
## [4.7.0](https://github.com/webpack/webpack-dev-server/compare/v4.6.0...v4.7.0) (2021-12-21)
613

714

client-src/clients/SockJSClient.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,12 @@ export default class SockJSClient {
3838
* @param {(...args: any[]) => void} f
3939
*/
4040
onMessage(f) {
41-
this.sock.onmessage = (e) => {
42-
f(e.data);
43-
};
41+
this.sock.onmessage =
42+
/**
43+
* @param {Error & { data: string }} e
44+
*/
45+
(e) => {
46+
f(e.data);
47+
};
4448
}
4549
}

client-src/index.js

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* global __resourceQuery, __webpack_hash__ */
2-
2+
/// <reference types="webpack/module" />
33
import webpackHotLog from "webpack/hot/log.js";
44
import stripAnsi from "./modules/strip-ansi/index.js";
55
import parseURL from "./utils/parseURL.js";
@@ -10,13 +10,34 @@ import sendMessage from "./utils/sendMessage.js";
1010
import reloadApp from "./utils/reloadApp.js";
1111
import createSocketURL from "./utils/createSocketURL.js";
1212

13+
/**
14+
* @typedef {Object} Options
15+
* @property {boolean} hot
16+
* @property {boolean} liveReload
17+
* @property {boolean} progress
18+
* @property {boolean | { warnings?: boolean, errors?: boolean }} overlay
19+
* @property {string} [logging]
20+
* @property {number} [reconnect]
21+
*/
22+
23+
/**
24+
* @typedef {Object} Status
25+
* @property {boolean} isUnloading
26+
* @property {string} currentHash
27+
* @property {string} [previousHash]
28+
*/
29+
30+
/**
31+
* @type {Status}
32+
*/
1333
const status = {
1434
isUnloading: false,
1535
// TODO Workaround for webpack v4, `__webpack_hash__` is not replaced without HotModuleReplacement
1636
// eslint-disable-next-line camelcase
1737
currentHash: typeof __webpack_hash__ !== "undefined" ? __webpack_hash__ : "",
1838
};
1939

40+
/** @type {Options} */
2041
const options = {
2142
hot: false,
2243
liveReload: false,
@@ -101,23 +122,35 @@ const onSocketMessage = {
101122
status.currentHash = hash;
102123
},
103124
logging: setAllLogLevel,
125+
/**
126+
* @param {boolean} value
127+
*/
104128
overlay(value) {
105129
if (typeof document === "undefined") {
106130
return;
107131
}
108132

109133
options.overlay = value;
110134
},
135+
/**
136+
* @param {number} value
137+
*/
111138
reconnect(value) {
112139
if (parsedResourceQuery.reconnect === "false") {
113140
return;
114141
}
115142

116143
options.reconnect = value;
117144
},
118-
progress(progress) {
119-
options.progress = progress;
145+
/**
146+
* @param {boolean} value
147+
*/
148+
progress(value) {
149+
options.progress = value;
120150
},
151+
/**
152+
* @param {{ pluginName?: string, percent: number, msg: string }} data
153+
*/
121154
"progress-update": function progressUpdate(data) {
122155
if (options.progress) {
123156
log.info(
@@ -148,6 +181,9 @@ const onSocketMessage = {
148181
reloadApp(options, status);
149182
},
150183
// TODO: remove in v5 in favor of 'static-changed'
184+
/**
185+
* @param {string} file
186+
*/
151187
"content-changed": function contentChanged(file) {
152188
log.info(
153189
`${
@@ -157,6 +193,9 @@ const onSocketMessage = {
157193

158194
self.location.reload();
159195
},
196+
/**
197+
* @param {string} file
198+
*/
160199
"static-changed": function staticChanged(file) {
161200
log.info(
162201
`${

client-src/overlay.js

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@ const colors = {
1717
darkgrey: "6D7891",
1818
};
1919

20+
/** @type {HTMLIFrameElement | null | undefined} */
2021
let iframeContainerElement;
22+
/** @type {HTMLDivElement | null | undefined} */
2123
let containerElement;
24+
/** @type {Array<(element: HTMLDivElement) => void>} */
2225
let onLoadQueue = [];
2326

2427
ansiHTML.setColors(colors);
@@ -38,7 +41,11 @@ function createContainer() {
3841
iframeContainerElement.style.zIndex = 9999999999;
3942
iframeContainerElement.onload = () => {
4043
containerElement =
41-
iframeContainerElement.contentDocument.createElement("div");
44+
/** @type {Document} */
45+
(
46+
/** @type {HTMLIFrameElement} */
47+
(iframeContainerElement).contentDocument
48+
).createElement("div");
4249
containerElement.id = "webpack-dev-server-client-overlay-div";
4350
containerElement.style.position = "fixed";
4451
containerElement.style.boxSizing = "border-box";
@@ -71,6 +78,7 @@ function createContainer() {
7178
closeButtonElement.style.color = "white";
7279
closeButtonElement.style.cursor = "pointer";
7380
closeButtonElement.style.cssFloat = "right";
81+
// @ts-ignore
7482
closeButtonElement.style.styleFloat = "right";
7583
closeButtonElement.addEventListener("click", () => {
7684
hide();
@@ -81,19 +89,27 @@ function createContainer() {
8189
containerElement.appendChild(document.createElement("br"));
8290
containerElement.appendChild(document.createElement("br"));
8391

84-
iframeContainerElement.contentDocument.body.appendChild(containerElement);
92+
/** @type {Document} */
93+
(
94+
/** @type {HTMLIFrameElement} */
95+
(iframeContainerElement).contentDocument
96+
).body.appendChild(containerElement);
8597

8698
onLoadQueue.forEach((onLoad) => {
87-
onLoad(containerElement);
99+
onLoad(/** @type {HTMLDivElement} */ (containerElement));
88100
});
89101
onLoadQueue = [];
90102

91-
iframeContainerElement.onload = null;
103+
/** @type {HTMLIFrameElement} */
104+
(iframeContainerElement).onload = null;
92105
};
93106

94107
document.body.appendChild(iframeContainerElement);
95108
}
96109

110+
/**
111+
* @param {(element: HTMLDivElement) => void} callback
112+
*/
97113
function ensureOverlayExists(callback) {
98114
if (containerElement) {
99115
// Everything is ready, call the callback right away.
@@ -124,6 +140,11 @@ function hide() {
124140
containerElement = null;
125141
}
126142

143+
/**
144+
* @param {string} type
145+
* @param {string | { file?: string, moduleName?: string, loc?: string, message?: string }} item
146+
* @returns {{ header: string, body: string }}
147+
*/
127148
function formatProblem(type, item) {
128149
let header = type === "warning" ? "WARNING" : "ERROR";
129150
let body = "";
@@ -154,6 +175,10 @@ function formatProblem(type, item) {
154175
}
155176

156177
// Compilation with errors (e.g. syntax error or missing modules).
178+
/**
179+
* @param {string} type
180+
* @param {Array<string | { file?: string, moduleName?: string, loc?: string, message?: string }>} messages
181+
*/
157182
function show(type, messages) {
158183
ensureOverlayExists(() => {
159184
messages.forEach((message) => {
@@ -177,7 +202,8 @@ function show(type, messages) {
177202
entryElement.appendChild(document.createElement("br"));
178203
entryElement.appendChild(document.createElement("br"));
179204

180-
containerElement.appendChild(entryElement);
205+
/** @type {HTMLDivElement} */
206+
(containerElement).appendChild(entryElement);
181207
});
182208
});
183209
}

client-src/socket.js

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,20 @@ let retries = 0;
1818
let maxRetries = 10;
1919
let client = null;
2020

21+
/**
22+
* @param {string} url
23+
* @param {{ [handler: string]: (data?: any, params?: any) => any }} handlers
24+
* @param {number} [reconnect]
25+
*/
2126
const socket = function initSocket(url, handlers, reconnect) {
2227
client = new Client(url);
2328

2429
client.onOpen(() => {
2530
retries = 0;
26-
maxRetries = reconnect;
31+
32+
if (typeof reconnect !== "undefined") {
33+
maxRetries = reconnect;
34+
}
2735
});
2836

2937
client.onClose(() => {
@@ -51,13 +59,18 @@ const socket = function initSocket(url, handlers, reconnect) {
5159
}
5260
});
5361

54-
client.onMessage((data) => {
55-
const message = JSON.parse(data);
62+
client.onMessage(
63+
/**
64+
* @param {any} data
65+
*/
66+
(data) => {
67+
const message = JSON.parse(data);
5668

57-
if (handlers[message.type]) {
58-
handlers[message.type](message.data, message.params);
69+
if (handlers[message.type]) {
70+
handlers[message.type](message.data, message.params);
71+
}
5972
}
60-
});
73+
);
6174
};
6275

6376
export default socket;

client-src/utils/createSocketURL.js

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,82 @@
1-
import url from "url";
1+
/**
2+
* @param {{ protocol?: string, auth?: string, hostname?: string, port?: string, pathname?: string, search?: string, hash?: string, slashes?: boolean }} objURL
3+
* @returns {string}
4+
*/
5+
function format(objURL) {
6+
let protocol = objURL.protocol || "";
7+
8+
if (protocol && protocol.substr(-1) !== ":") {
9+
protocol += ":";
10+
}
11+
12+
let auth = objURL.auth || "";
13+
14+
if (auth) {
15+
auth = encodeURIComponent(auth);
16+
auth = auth.replace(/%3A/i, ":");
17+
auth += "@";
18+
}
19+
20+
let host = "";
21+
22+
if (objURL.hostname) {
23+
host =
24+
auth +
25+
(objURL.hostname.indexOf(":") === -1
26+
? objURL.hostname
27+
: `[${objURL.hostname}]`);
28+
29+
if (objURL.port) {
30+
host += `:${objURL.port}`;
31+
}
32+
}
33+
34+
let pathname = objURL.pathname || "";
35+
36+
if (objURL.slashes) {
37+
host = `//${host || ""}`;
38+
39+
if (pathname && pathname.charAt(0) !== "/") {
40+
pathname = `/${pathname}`;
41+
}
42+
} else if (!host) {
43+
host = "";
44+
}
45+
46+
let search = objURL.search || "";
47+
48+
if (search && search.charAt(0) !== "?") {
49+
search = `?${search}`;
50+
}
51+
52+
let hash = objURL.hash || "";
53+
54+
if (hash && hash.charAt(0) !== "#") {
55+
hash = `#${hash}`;
56+
}
57+
58+
pathname = pathname.replace(
59+
/[?#]/g,
60+
/**
61+
* @param {string} match
62+
* @returns {string}
63+
*/
64+
(match) => encodeURIComponent(match)
65+
);
66+
search = search.replace("#", "%23");
67+
68+
return `${protocol}${host}${pathname}${search}${hash}`;
69+
}
270

3-
// We handle legacy API that is Node.js specific, and a newer API that implements the same WHATWG URL Standard used by web browsers
4-
// Please look at https://nodejs.org/api/url.html#url_url_strings_and_url_objects
71+
/**
72+
* @param {URL & { fromCurrentScript?: boolean }} parsedURL
73+
* @returns {string}
74+
*/
575
function createSocketURL(parsedURL) {
676
let { hostname } = parsedURL;
777

878
// Node.js module parses it as `::`
9-
// `new URL(urlString, [baseURLstring])` parses it as '[::]'
79+
// `new URL(urlString, [baseURLString])` parses it as '[::]'
1080
const isInAddrAny =
1181
hostname === "0.0.0.0" || hostname === "::" || hostname === "[::]";
1282

@@ -80,7 +150,7 @@ function createSocketURL(parsedURL) {
80150
socketURLPathname = parsedURL.pathname;
81151
}
82152

83-
return url.format({
153+
return format({
84154
protocol: socketURLProtocol,
85155
auth: socketURLAuth,
86156
hostname: socketURLHostname,

client-src/utils/getCurrentScriptSource.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
/**
2+
* @returns {string}
3+
*/
14
function getCurrentScriptSource() {
25
// `document.currentScript` is the most accurate way to find the current script,
36
// but is not supported in all browsers.

0 commit comments

Comments
 (0)