Skip to content

Commit 5c014a2

Browse files
authored
Merge pull request webpack#7513 from mohsen1/SortableSet-types
Add SortableSet types
2 parents fd1b245 + 7c5cab0 commit 5c014a2

File tree

8 files changed

+99
-64
lines changed

8 files changed

+99
-64
lines changed

lib/Chunk.js

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,34 +19,38 @@ const ERR_CHUNK_INITIAL =
1919
/** @typedef {import("webpack-sources").Source} Source */
2020

2121
/**
22-
* @typedef {Object} Identifiable an object who contains an identifier function property
23-
* @property {() => string} identifier the resource or unique identifier of something
22+
* @typedef {Object} WithId an object who has an id property *
23+
* @property {string | number} id the id of the object
2424
*/
2525

2626
/**
27-
* @typedef {Object} WithId an object who has an id property
28-
* @property {string} id the id of the object
27+
* Compare two Modules based on their ids for sorting
28+
* @param {Module} a module
29+
* @param {Module} b module
30+
* @returns {-1|0|1} sort value
2931
*/
30-
31-
/** @typedef {(a: Module, b: Module) => -1|0|1} ModuleSortPredicate */
32-
/** @typedef {(m: Module) => boolean} ModuleFilterPredicate */
33-
/** @typedef {(c: Chunk) => boolean} ChunkFilterPredicate */
32+
const sortModuleById = (a, b) => {
33+
if (a.id < b.id) return -1;
34+
if (b.id < a.id) return 1;
35+
return 0;
36+
};
3437

3538
/**
36-
* @param {WithId} a object that contains an ID property
37-
* @param {WithId} b object that contains an ID property
39+
* Compare two ChunkGroups based on their ids for sorting
40+
* @param {ChunkGroup} a chunk group
41+
* @param {ChunkGroup} b chunk group
3842
* @returns {-1|0|1} sort value
3943
*/
40-
const sortById = (a, b) => {
44+
const sortChunkGroupById = (a, b) => {
4145
if (a.id < b.id) return -1;
4246
if (b.id < a.id) return 1;
4347
return 0;
4448
};
4549

4650
/**
47-
*
48-
* @param {Identifiable} a first object with ident fn
49-
* @param {Identifiable} b second object with ident fn
51+
* Compare two Identifiables , based on their ids for sorting
52+
* @param {Module} a first object with ident fn
53+
* @param {Module} b second object with ident fn
5054
* @returns {-1|0|1} The order number of the sort
5155
*/
5256
const sortByIdentifier = (a, b) => {
@@ -70,13 +74,13 @@ const getModulesIdent = set => {
7074

7175
/**
7276
* @template T
73-
* @param {Set<T>} set the set to convert to array
77+
* @param {SortableSet<T>} set the sortable set to convert to array
7478
* @returns {Array<T>} the array returned from Array.from(set)
7579
*/
7680
const getArray = set => Array.from(set);
7781

7882
/**
79-
* @param {Set<Module>} set the Set to get the count/size of
83+
* @param {SortableSet<Module>} set the sortable Set to get the count/size of
8084
* @returns {number} the size of the modules
8185
*/
8286
const getModulesSize = set => {
@@ -108,12 +112,10 @@ class Chunk {
108112
this.preventIntegration = false;
109113
/** @type {Module=} */
110114
this.entryModule = undefined;
111-
//TODO make these typed generics for Module[] and ChunkGroup[] and their sort being (T, T): => 1,-1,0
112-
//See https://github.com/webpack/webpack/pull/7046
113-
/** @private */
115+
/** @private @type {SortableSet<Module>} */
114116
this._modules = new SortableSet(undefined, sortByIdentifier);
115-
/** @private */
116-
this._groups = new SortableSet(undefined, sortById);
117+
/** @private @type {SortableSet<ChunkGroup>} */
118+
this._groups = new SortableSet(undefined, sortChunkGroupById);
117119
/** @type {Source[]} */
118120
this.files = [];
119121
/** @type {boolean} */
@@ -498,14 +500,14 @@ class Chunk {
498500
}
499501

500502
/**
501-
* @param {ModuleSortPredicate=} sortByFn a predicate function used to sort modules
503+
* @param {function(Module, Module): -1|0|1=} sortByFn a predicate function used to sort modules
502504
* @returns {void}
503505
*/
504506
sortModules(sortByFn) {
505-
this._modules.sortWith(sortByFn || sortById);
507+
this._modules.sortWith(sortByFn || sortModuleById);
506508
}
507509

508-
sortItems(sortChunks) {
510+
sortItems() {
509511
this.sortModules();
510512
}
511513

@@ -661,8 +663,8 @@ class Chunk {
661663

662664
/**
663665
*
664-
* @param {ModuleFilterPredicate} filterFn predicate function used to filter modules
665-
* @param {ChunkFilterPredicate} filterChunkFn predicate function used to filter chunks
666+
* @param {function(Module): boolean} filterFn predicate function used to filter modules
667+
* @param {function(Chunk): boolean} filterChunkFn predicate function used to filter chunks
666668
* @returns {boolean} return true if module exists in graph
667669
*/
668670
hasModuleInGraph(filterFn, filterChunkFn) {

lib/ChunkGroup.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ let debugId = 5000;
1919

2020
/**
2121
* @template T
22-
* @param {Set<T>} set set to convert to array.
22+
* @param {SortableSet<T>} set set to convert to array.
2323
* @returns {T[]} the array format of existing set
2424
*/
2525
const getArray = set => Array.from(set);
2626

2727
/**
2828
* A convenience method used to sort chunks based on their id's
29-
* @param {HasId} a first sorting comparitor
30-
* @param {HasId} b second sorting comparitor
29+
* @param {HasId} a first sorting comparator
30+
* @param {HasId} b second sorting comparator
3131
* @returns {1|0|-1} a sorting index to determine order
3232
*/
3333
const sortById = (a, b) => {
@@ -37,8 +37,8 @@ const sortById = (a, b) => {
3737
};
3838

3939
/**
40-
* @param {OriginRecord} a the first comparitor in sort
41-
* @param {OriginRecord} b the second comparitor in sort
40+
* @param {OriginRecord} a the first comparator in sort
41+
* @param {OriginRecord} b the second comparator in sort
4242
* @returns {1|-1|0} returns sorting order as index
4343
*/
4444
const sortOrigin = (a, b) => {

lib/Module.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class Module extends DependenciesBlock {
6565
// Graph (per Compilation)
6666
/** @type {ModuleReason[]} */
6767
this.reasons = [];
68-
/** @type {SortableSet} */
68+
/** @type {SortableSet<Chunk>} */
6969
this._chunks = new SortableSet(undefined, sortById);
7070

7171
// Info from Compilation (per Compilation)

lib/ModuleTemplate.js

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

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

9+
/** @typedef {import("webpack-sources").Source} Source */
10+
/** @typedef {import("./Module")} Module */
11+
912
module.exports = class ModuleTemplate extends Tapable {
1013
constructor(runtimeTemplate, type) {
1114
super();
@@ -40,6 +43,12 @@ module.exports = class ModuleTemplate extends Tapable {
4043
};
4144
}
4245

46+
/**
47+
* @param {Module} module the module
48+
* @param {TODO} dependencyTemplates templates for dependencies
49+
* @param {TODO} options render options
50+
* @returns {Source} the source
51+
*/
4352
render(module, dependencyTemplates, options) {
4453
try {
4554
const moduleSource = module.source(

lib/Template.js

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ const MATCH_PADDED_HYPHENS_REPLACE_REGEX = /^-|-$/g;
2424

2525
/**
2626
* @typedef {Object} HasId
27-
* @property {number} id
27+
* @property {number | string} id
2828
* */
2929

3030
/**
31-
* @typedef {(m: Module, idx: number) => boolean} ModuleFilterPredicate
31+
* @typedef {function(Module, number): boolean} ModuleFilterPredicate
3232
*/
3333

3434
/**
@@ -44,14 +44,6 @@ const stringifyIdSortPredicate = (a, b) => {
4444
return 0;
4545
};
4646

47-
/**
48-
* @param {Module} module the module to compare against
49-
* @returns {boolean} return true if module.id is equal to type "number"
50-
*/
51-
const moduleIdIsNumber = module => {
52-
return typeof module.id === "number";
53-
};
54-
5547
class Template {
5648
/**
5749
*
@@ -177,18 +169,20 @@ class Template {
177169
}
178170

179171
/**
180-
*
181-
* @param {Module[]} modules a collection of modules to get array bounds for
172+
* @typedef {Object} WithId
173+
* @property {string|number} id
174+
*/
175+
176+
/**
177+
* @param {WithId[]} modules a collection of modules to get array bounds for
182178
* @returns {[number, number] | false} returns the upper and lower array bounds
183179
* or false if not every module has a number based id
184180
*/
185181
static getModulesArrayBounds(modules) {
186-
// Typeguards don't work for .every() with predicate functions
187-
// https://github.com/Microsoft/TypeScript/issues/23799
188-
if (!modules.every(moduleIdIsNumber)) return false;
189182
var maxId = -Infinity;
190183
var minId = Infinity;
191184
for (const module of modules) {
185+
if (typeof module.id !== "number") return false;
192186
if (maxId < module.id) maxId = /** @type {number} */ (module.id);
193187
if (minId > module.id) minId = /** @type {number} */ (module.id);
194188
}

lib/util/SortableSet.js

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,31 @@
11
"use strict";
2-
//TODO: Make this a generic type
3-
//https://github.com/Microsoft/TypeScript/issues/23385
4-
//https://github.com/Microsoft/TypeScript/issues/23384
2+
3+
/**
4+
* A subset of Set that offers sorting functionality
5+
* @template T item type in set
6+
*/
57
class SortableSet extends Set {
8+
/**
9+
* Create a new sortable set
10+
* @param {Array<T>=} initialIterable The initial iterable value
11+
* @typedef {function(T, T): number} SortFunction
12+
* @param {SortFunction=} defaultSort Default sorting function
13+
*/
614
constructor(initialIterable, defaultSort) {
715
super(initialIterable);
16+
/** @private @type {function(T, T): number}} */
817
this._sortFn = defaultSort;
18+
/** @private @type {function(T, T): number} | null} */
919
this._lastActiveSortFn = null;
20+
/** @private @type {Map<Function, T[]> | undefined} */
1021
this._cache = undefined;
22+
/** @private @type {Map<Function, T[]|string|number> | undefined} */
1123
this._cacheOrderIndependent = undefined;
1224
}
1325

1426
/**
15-
* @param {TODO} value - value to add to set
16-
* @returns {this} - returns itself
27+
* @param {T} value value to add to set
28+
* @returns {this} returns itself
1729
*/
1830
add(value) {
1931
this._lastActiveSortFn = null;
@@ -23,19 +35,31 @@ class SortableSet extends Set {
2335
return this;
2436
}
2537

38+
/**
39+
* @param {T} value value to delete
40+
* @returns {boolean} true if value existed in set, false otherwise
41+
*/
2642
delete(value) {
2743
this._invalidateCache();
2844
this._invalidateOrderedCache();
2945
return super.delete(value);
3046
}
3147

48+
/**
49+
* @returns {void}
50+
*/
3251
clear() {
3352
this._invalidateCache();
3453
this._invalidateOrderedCache();
3554
return super.clear();
3655
}
3756

38-
sortWith(/** @type {(a: TODO, b: TODO) => number} */ sortFn) {
57+
/**
58+
* Sort with a comparer function
59+
* @param {SortFunction} sortFn Sorting comparer function
60+
* @returns {void}
61+
*/
62+
sortWith(sortFn) {
3963
if (this.size <= 1 || sortFn === this._lastActiveSortFn) {
4064
// already sorted - nothing to do
4165
return;
@@ -50,16 +74,14 @@ class SortableSet extends Set {
5074
this._invalidateCache();
5175
}
5276

53-
/**
54-
* @returns {void}
55-
*/
5677
sort() {
5778
this.sortWith(this._sortFn);
5879
}
5980

6081
/**
61-
* @param {Function} fn - function to calculate value
62-
* @returns {TODO} - returns result of fn(this), cached until set changes
82+
* Get data from cache
83+
* @param {function(SortableSet<T>): T[]} fn function to calculate value
84+
* @returns {T[]} returns result of fn(this), cached until set changes
6385
*/
6486
getFromCache(fn) {
6587
if (this._cache === undefined) {
@@ -76,8 +98,8 @@ class SortableSet extends Set {
7698
}
7799

78100
/**
79-
* @param {Function} fn - function to calculate value
80-
* @returns {TODO} - returns result of fn(this), cached until set changes
101+
* @param {function(SortableSet<T>): string|number|T[]} fn function to calculate value
102+
* @returns {any} returns result of fn(this), cached until set changes
81103
*/
82104
getFromUnorderedCache(fn) {
83105
if (this._cacheOrderIndependent === undefined) {
@@ -93,12 +115,20 @@ class SortableSet extends Set {
93115
return newData;
94116
}
95117

118+
/**
119+
* @private
120+
* @returns {void}
121+
*/
96122
_invalidateCache() {
97123
if (this._cache !== undefined) {
98124
this._cache.clear();
99125
}
100126
}
101127

128+
/**
129+
* @private
130+
* @returns {void}
131+
*/
102132
_invalidateOrderedCache() {
103133
if (this._cacheOrderIndependent !== undefined) {
104134
this._cacheOrderIndependent.clear();

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
"script-loader": "~0.7.0",
7373
"simple-git": "^1.65.0",
7474
"style-loader": "^0.19.1",
75-
"typescript": "^2.9.0-dev.20180518",
75+
"typescript": "^2.9.1",
7676
"url-loader": "^0.6.2",
7777
"val-loader": "^1.0.2",
7878
"vm-browserify": "~0.0.0",

yarn.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6489,9 +6489,9 @@ typedarray@^0.0.6:
64896489
version "0.0.6"
64906490
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
64916491

6492-
typescript@^2.9.0-dev.20180518:
6493-
version "2.9.0-dev.20180518"
6494-
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.0-dev.20180518.tgz#7c709cb5d59e60a5e346cc5856277fd7b8ced68c"
6492+
typescript@^2.9.1:
6493+
version "2.9.1"
6494+
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.1.tgz#fdb19d2c67a15d11995fd15640e373e09ab09961"
64956495

64966496
ua-parser-js@^0.7.9:
64976497
version "0.7.17"

0 commit comments

Comments
 (0)