Skip to content

Commit fc3774a

Browse files
authored
Merge pull request webpack#7116 from webpack/feature/main-template-type-support
Types: Main Template is now Typed with JSDoc Annotations
2 parents 7829a0b + fdcafe6 commit fc3774a

File tree

4 files changed

+176
-7
lines changed

4 files changed

+176
-7
lines changed

lib/ChunkTemplate.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,21 @@
66

77
const { Tapable, SyncWaterfallHook, SyncHook } = require("tapable");
88

9+
/** @typedef {import("./ModuleTemplate")} ModuleTemplate */
10+
/** @typedef {import("./Chunk")} Chunk */
11+
/** @typedef {import("./Module")} Module} */
12+
/** @typedef {import("crypto").Hash} Hash */
13+
14+
/**
15+
* @typedef {Object} RenderManifestOptions
16+
* @property {Chunk} chunk the chunk used to render
17+
* @property {Hash} hash
18+
* @property {string} fullHash
19+
* @property {any} outputOptions
20+
* @property {{javascript: ModuleTemplate, webassembly: ModuleTemplate}} moduleTemplates
21+
* @property {Map} dependencyTemplates
22+
*/
23+
924
module.exports = class ChunkTemplate extends Tapable {
1025
constructor(outputOptions) {
1126
super();
@@ -30,6 +45,11 @@ module.exports = class ChunkTemplate extends Tapable {
3045
};
3146
}
3247

48+
/**
49+
*
50+
* @param {RenderManifestOptions} options render manifest options
51+
* @returns {any[]} returns render manifest
52+
*/
3353
getRenderManifest(options) {
3454
const result = [];
3555

lib/MainTemplate.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,22 @@ const {
1818
} = require("tapable");
1919
const Template = require("./Template");
2020

21+
/** @typedef {import("webpack-sources").ConcatSource} ConcatSource */
22+
/** @typedef {import("./ModuleTemplate")} ModuleTemplate */
23+
/** @typedef {import("./Chunk")} Chunk */
24+
/** @typedef {import("./Module")} Module} */
25+
/** @typedef {import("crypto").Hash} Hash} */
26+
27+
/**
28+
* @typedef {Object} RenderManifestOptions
29+
* @property {Chunk} chunk the chunk used to render
30+
* @property {Hash} hash
31+
* @property {string} fullHash
32+
* @property {any} outputOptions
33+
* @property {{javascript: ModuleTemplate, webassembly: ModuleTemplate}} moduleTemplates
34+
* @property {Map} dependencyTemplates
35+
*/
36+
2137
// require function shortcuts:
2238
// __webpack_require__.s = the module id of the entry point
2339
// __webpack_require__.c = the module cache
@@ -35,10 +51,16 @@ const Template = require("./Template");
3551
// __webpack_require__.nc = the script nonce
3652

3753
module.exports = class MainTemplate extends Tapable {
54+
/**
55+
*
56+
* @param {any=} outputOptions output options for the MainTemplate
57+
*/
3858
constructor(outputOptions) {
3959
super();
60+
/** @type {any?} */
4061
this.outputOptions = outputOptions || {};
4162
this.hooks = {
63+
/** @type {SyncWaterfallHook<any[], RenderManifestOptions>} */
4264
renderManifest: new SyncWaterfallHook(["result", "options"]),
4365
modules: new SyncWaterfallHook([
4466
"modules",
@@ -104,6 +126,7 @@ module.exports = class MainTemplate extends Tapable {
104126
hotBootstrap: new SyncWaterfallHook(["source", "chunk", "hash"])
105127
};
106128
this.hooks.startup.tap("MainTemplate", (source, chunk, hash) => {
129+
/** @type {string[]} */
107130
const buf = [];
108131
if (chunk.entryModule) {
109132
buf.push("// Load entry module and return exports");
@@ -296,6 +319,11 @@ module.exports = class MainTemplate extends Tapable {
296319
this.requireFn = "__webpack_require__";
297320
}
298321

322+
/**
323+
*
324+
* @param {RenderManifestOptions} options render manifest options
325+
* @returns {any[]} returns render manifest
326+
*/
299327
getRenderManifest(options) {
300328
const result = [];
301329

@@ -304,6 +332,14 @@ module.exports = class MainTemplate extends Tapable {
304332
return result;
305333
}
306334

335+
/**
336+
*
337+
* @param {string} hash hash to be used for render call
338+
* @param {Chunk} chunk Chunk instance
339+
* @param {ModuleTemplate} moduleTemplate ModuleTemplate instance for render
340+
* @param {any} dependencyTemplates DependencyTemplate[]s
341+
* @return {ConcatSource} the newly generated source from rendering
342+
*/
307343
render(hash, chunk, moduleTemplate, dependencyTemplates) {
308344
const buf = [];
309345
buf.push(
@@ -349,6 +385,13 @@ module.exports = class MainTemplate extends Tapable {
349385
return new ConcatSource(source, ";");
350386
}
351387

388+
/**
389+
*
390+
* @param {string} hash hash for render fn
391+
* @param {Chunk} chunk Chunk instance for require
392+
* @param {(number|string)=} varModuleId module id
393+
* @return {any} the moduleRequire hook call return signature
394+
*/
352395
renderRequireFunctionForModule(hash, chunk, varModuleId) {
353396
return this.hooks.moduleRequire.call(
354397
this.requireFn,
@@ -358,6 +401,14 @@ module.exports = class MainTemplate extends Tapable {
358401
);
359402
}
360403

404+
/**
405+
*
406+
* @param {string} hash hash for render add fn
407+
* @param {Chunk} chunk Chunk instance for require add fn
408+
* @param {(string|number)=} varModuleId module id
409+
* @param {Module} varModule Module instance
410+
* @return {any} renderAddModule call
411+
*/
361412
renderAddModule(hash, chunk, varModuleId, varModule) {
362413
return this.hooks.addModule.call(
363414
`modules[${varModuleId}] = ${varModule};`,
@@ -368,6 +419,12 @@ module.exports = class MainTemplate extends Tapable {
368419
);
369420
}
370421

422+
/**
423+
*
424+
* @param {string} hash string hash
425+
* @param {number} length length
426+
* @return {any} call hook return
427+
*/
371428
renderCurrentHashCode(hash, length) {
372429
length = length || Infinity;
373430
return this.hooks.currentHash.call(
@@ -376,6 +433,11 @@ module.exports = class MainTemplate extends Tapable {
376433
);
377434
}
378435

436+
/**
437+
*
438+
* @param {object} options get public path options
439+
* @return {any} hook call
440+
*/
379441
getPublicPath(options) {
380442
return this.hooks.assetPath.call(
381443
this.outputOptions.publicPath || "",

lib/Module.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ const SortableSet = require("./util/SortableSet");
1212
const Template = require("./Template");
1313

1414
/** @typedef {typeof import("./Chunk")} Chunk */
15-
1615
/** @typedef {typeof import("./RequestShortener")} RequestShortener */
1716

1817
const EMPTY_RESOLVE_OPTIONS = {};
@@ -101,6 +100,9 @@ class Module extends DependenciesBlock {
101100

102101
/** @type {boolean} */
103102
this.useSourceMap = false;
103+
104+
// info from build
105+
this._source = null;
104106
}
105107

106108
get exportsArgument() {

lib/Template.js

Lines changed: 91 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22
MIT License http://www.opensource.org/licenses/mit-license.php
33
Author Tobias Koppers @sokra
44
*/
5-
"use strict";
5+
/** @typedef {import("./Module")} Module */
6+
/** @typedef {import("./Chunk")} Chunk */
7+
/** @typedef {import("./ModuleTemplate")} ModuleTemplate */
8+
/** @typedef {import("webpack-sources").ConcatSource} ConcatSource */
69

710
const { ConcatSource } = require("webpack-sources");
11+
const HotUpdateChunk = require("./HotUpdateChunk");
812

913
const START_LOWERCASE_ALPHABET_CODE = "a".charCodeAt(0);
1014
const START_UPPERCASE_ALPHABET_CODE = "A".charCodeAt(0);
@@ -18,6 +22,20 @@ const COMMENT_END_REGEX = /\*\//g;
1822
const PATH_NAME_NORMALIZE_REPLACE_REGEX = /[^a-zA-Z0-9_!§$()=\-^°]+/g;
1923
const MATCH_PADDED_HYPHENS_REPLACE_REGEX = /^-|-$/g;
2024

25+
/**
26+
* @typedef {Object} HasId
27+
* @property {number} id
28+
* */
29+
30+
/**
31+
* @typedef {(m: Module, idx: number) => boolean} ModuleFilterPredicate
32+
*/
33+
34+
/**
35+
* @param {HasId} a first id object to be sorted
36+
* @param {HasId} b second id object to be sorted against
37+
* @return {-1|0|1} the sort value
38+
*/
2139
const stringifyIdSortPredicate = (a, b) => {
2240
var aId = a.id + "";
2341
var bId = b.id + "";
@@ -26,36 +44,63 @@ const stringifyIdSortPredicate = (a, b) => {
2644
return 0;
2745
};
2846

47+
//TODO: Change type to Module when import works
48+
//https://github.com/Microsoft/TypeScript/issues/23375
49+
/**
50+
* @param {HasId} module the module to compare against
51+
* @return {boolean} return true if module.id is equal to type "number"
52+
*/
2953
const moduleIdIsNumber = module => {
3054
return typeof module.id === "number";
3155
};
3256

33-
module.exports = class Template {
57+
class Template {
58+
/**
59+
*
60+
* @param {Function} fn - a runtime function (.runtime.js) "template"
61+
* @return {string} the updated and normalized function string
62+
*/
3463
static getFunctionContent(fn) {
3564
return fn
3665
.toString()
3766
.replace(FUNCTION_CONTENT_REGEX, "")
3867
.replace(INDENT_MULTILINE_REGEX, "")
3968
.replace(LINE_SEPARATOR_REGEX, "\n");
4069
}
41-
70+
/**
71+
* @param {string} str the string converted to identifier
72+
* @return {string} created identifier
73+
*/
4274
static toIdentifier(str) {
4375
if (typeof str !== "string") return "";
4476
return str
4577
.replace(IDENTIFIER_NAME_REPLACE_REGEX, "_$1")
4678
.replace(IDENTIFIER_ALPHA_NUMERIC_NAME_REPLACE_REGEX, "_");
4779
}
48-
80+
/**
81+
*
82+
* @param {string} str string to be converted to commented in bundle code
83+
* @return {string} returns a commented version of string
84+
*/
4985
static toComment(str) {
5086
if (!str) return "";
5187
return `/*! ${str.replace(COMMENT_END_REGEX, "* /")} */`;
5288
}
5389

90+
/**
91+
*
92+
* @param {string} str string to be converted to "normal comment"
93+
* @return {string} returns a commented version of string
94+
*/
5495
static toNormalComment(str) {
5596
if (!str) return "";
5697
return `/* ${str.replace(COMMENT_END_REGEX, "* /")} */`;
5798
}
5899

100+
/**
101+
* @param {string} str string path to be normalized
102+
* @return {string} normalized bundle-safe path
103+
*/
59104
static toPath(str) {
60105
if (typeof str !== "string") return "";
61106
return str
@@ -64,6 +109,11 @@ module.exports = class Template {
64109
}
65110

66111
// map number to a single character a-z, A-Z or <_ + number> if number is too big
112+
/**
113+
*
114+
* @param {number} n number to convert to ident
115+
* @return {string} returns single character ident
116+
*/
67117
static numberToIdentifer(n) {
68118
// lower case
69119
if (n < DELTA_A_TO_Z)
@@ -81,6 +131,11 @@ module.exports = class Template {
81131
);
82132
}
83133

134+
/**
135+
*
136+
* @param {string | string[]} str string to convert to identity
137+
* @return {string} converted identity
138+
*/
84139
static indent(str) {
85140
if (Array.isArray(str)) {
86141
return str.map(Template.indent).join("\n");
@@ -92,6 +147,12 @@ module.exports = class Template {
92147
}
93148
}
94149

150+
/**
151+
*
152+
* @param {string|string[]} str string to create prefix for
153+
* @param {string} prefix prefix to compose
154+
* @return {string} returns new prefix string
155+
*/
95156
static prefix(str, prefix) {
96157
if (Array.isArray(str)) {
97158
str = str.join("\n");
@@ -102,13 +163,24 @@ module.exports = class Template {
102163
return ind + str.replace(/\n([^\n])/g, "\n" + prefix + "$1");
103164
}
104165

166+
/**
167+
*
168+
* @param {string|string[]} str string or string collection
169+
* @return {string} returns a single string from array
170+
*/
105171
static asString(str) {
106172
if (Array.isArray(str)) {
107173
return str.join("\n");
108174
}
109175
return str;
110176
}
111177

178+
/**
179+
*
180+
* @param {HasId[]} modules - a collection of modules to get array bounds for
181+
* @return {[number, number] | false} returns the upper and lower array bounds
182+
* or false if not every module has a number based id
183+
*/
112184
static getModulesArrayBounds(modules) {
113185
if (!modules.every(moduleIdIsNumber)) return false;
114186
var maxId = -Infinity;
@@ -133,6 +205,15 @@ module.exports = class Template {
133205
return arrayOverhead < objectOverhead ? [minId, maxId] : false;
134206
}
135207

208+
/**
209+
*
210+
* @param {Chunk} chunk chunk whose modules will be rendered
211+
* @param {ModuleFilterPredicate} filterFn function used to filter modules from chunk to render
212+
* @param {ModuleTemplate} moduleTemplate ModuleTemplate instance used to render modules
213+
* @param {any | any[]} dependencyTemplates templates needed for each module to render dependencies
214+
* @param {string=} prefix applying prefix strings
215+
* @return {ConcatSource} rendered chunk modules in a Source object
216+
*/
136217
static renderChunkModules(
137218
chunk,
138219
filterFn,
@@ -143,7 +224,9 @@ module.exports = class Template {
143224
if (!prefix) prefix = "";
144225
var source = new ConcatSource();
145226
const modules = chunk.getModules().filter(filterFn);
146-
var removedModules = chunk.removedModules;
227+
if (chunk instanceof HotUpdateChunk) {
228+
var removedModules = chunk.removedModules;
229+
}
147230
if (
148231
modules.length === 0 &&
149232
(!removedModules || removedModules.length === 0)
@@ -202,4 +285,6 @@ module.exports = class Template {
202285
}
203286
return source;
204287
}
205-
};
288+
}
289+
290+
module.exports = Template;

0 commit comments

Comments
 (0)