Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F100991543
comparators.js
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Feb 4, 14:46
Size
11 KB
Mime Type
text/x-c++
Expires
Thu, Feb 6, 14:46 (2 d)
Engine
blob
Format
Raw Data
Handle
24068549
Attached To
rOACCT Open Access Compliance Check Tool (OACCT)
comparators.js
View Options
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict"
;
const
{
compareRuntime
}
=
require
(
"./runtime"
);
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../ChunkGroup")} ChunkGroup */
/** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
/** @template T @typedef {function(T, T): -1|0|1} Comparator */
/** @template TArg @template T @typedef {function(TArg, T, T): -1|0|1} RawParameterizedComparator */
/** @template TArg @template T @typedef {function(TArg): Comparator<T>} ParameterizedComparator */
/**
* @template T
* @param {RawParameterizedComparator<any, T>} fn comparator with argument
* @returns {ParameterizedComparator<any, T>} comparator
*/
const
createCachedParameterizedComparator
=
fn
=>
{
/** @type {WeakMap<object, Comparator<T>>} */
const
map
=
new
WeakMap
();
return
arg
=>
{
const
cachedResult
=
map
.
get
(
arg
);
if
(
cachedResult
!==
undefined
)
return
cachedResult
;
/**
* @param {T} a first item
* @param {T} b second item
* @returns {-1|0|1} compare result
*/
const
result
=
(
a
,
b
)
=>
{
return
fn
(
arg
,
a
,
b
);
};
map
.
set
(
arg
,
result
);
return
result
;
};
};
/**
* @param {Chunk} a chunk
* @param {Chunk} b chunk
* @returns {-1|0|1} compare result
*/
exports
.
compareChunksById
=
(
a
,
b
)
=>
{
return
compareIds
(
a
.
id
,
b
.
id
);
};
/**
* @param {Module} a module
* @param {Module} b module
* @returns {-1|0|1} compare result
*/
exports
.
compareModulesByIdentifier
=
(
a
,
b
)
=>
{
return
compareIds
(
a
.
identifier
(),
b
.
identifier
());
};
/**
* @param {ChunkGraph} chunkGraph the chunk graph
* @param {Module} a module
* @param {Module} b module
* @returns {-1|0|1} compare result
*/
const
compareModulesById
=
(
chunkGraph
,
a
,
b
)
=>
{
return
compareIds
(
chunkGraph
.
getModuleId
(
a
),
chunkGraph
.
getModuleId
(
b
));
};
/** @type {ParameterizedComparator<ChunkGraph, Module>} */
exports
.
compareModulesById
=
createCachedParameterizedComparator
(
compareModulesById
);
/**
* @param {number} a number
* @param {number} b number
* @returns {-1|0|1} compare result
*/
const
compareNumbers
=
(
a
,
b
)
=>
{
if
(
typeof
a
!==
typeof
b
)
{
return
typeof
a
<
typeof
b
?
-
1
:
1
;
}
if
(
a
<
b
)
return
-
1
;
if
(
a
>
b
)
return
1
;
return
0
;
};
exports
.
compareNumbers
=
compareNumbers
;
/**
* @param {string} a string
* @param {string} b string
* @returns {-1|0|1} compare result
*/
const
compareStringsNumeric
=
(
a
,
b
)
=>
{
const
partsA
=
a
.
split
(
/(\d+)/
);
const
partsB
=
b
.
split
(
/(\d+)/
);
const
len
=
Math
.
min
(
partsA
.
length
,
partsB
.
length
);
for
(
let
i
=
0
;
i
<
len
;
i
++
)
{
const
pA
=
partsA
[
i
];
const
pB
=
partsB
[
i
];
if
(
i
%
2
===
0
)
{
if
(
pA
.
length
>
pB
.
length
)
{
if
(
pA
.
slice
(
0
,
pB
.
length
)
>
pB
)
return
1
;
return
-
1
;
}
else
if
(
pB
.
length
>
pA
.
length
)
{
if
(
pB
.
slice
(
0
,
pA
.
length
)
>
pA
)
return
-
1
;
return
1
;
}
else
{
if
(
pA
<
pB
)
return
-
1
;
if
(
pA
>
pB
)
return
1
;
}
}
else
{
const
nA
=
+
pA
;
const
nB
=
+
pB
;
if
(
nA
<
nB
)
return
-
1
;
if
(
nA
>
nB
)
return
1
;
}
}
if
(
partsB
.
length
<
partsA
.
length
)
return
1
;
if
(
partsB
.
length
>
partsA
.
length
)
return
-
1
;
return
0
;
};
exports
.
compareStringsNumeric
=
compareStringsNumeric
;
/**
* @param {ModuleGraph} moduleGraph the module graph
* @param {Module} a module
* @param {Module} b module
* @returns {-1|0|1} compare result
*/
const
compareModulesByPostOrderIndexOrIdentifier
=
(
moduleGraph
,
a
,
b
)
=>
{
const
cmp
=
compareNumbers
(
moduleGraph
.
getPostOrderIndex
(
a
),
moduleGraph
.
getPostOrderIndex
(
b
)
);
if
(
cmp
!==
0
)
return
cmp
;
return
compareIds
(
a
.
identifier
(),
b
.
identifier
());
};
/** @type {ParameterizedComparator<ModuleGraph, Module>} */
exports
.
compareModulesByPostOrderIndexOrIdentifier
=
createCachedParameterizedComparator
(
compareModulesByPostOrderIndexOrIdentifier
);
/**
* @param {ModuleGraph} moduleGraph the module graph
* @param {Module} a module
* @param {Module} b module
* @returns {-1|0|1} compare result
*/
const
compareModulesByPreOrderIndexOrIdentifier
=
(
moduleGraph
,
a
,
b
)
=>
{
const
cmp
=
compareNumbers
(
moduleGraph
.
getPreOrderIndex
(
a
),
moduleGraph
.
getPreOrderIndex
(
b
)
);
if
(
cmp
!==
0
)
return
cmp
;
return
compareIds
(
a
.
identifier
(),
b
.
identifier
());
};
/** @type {ParameterizedComparator<ModuleGraph, Module>} */
exports
.
compareModulesByPreOrderIndexOrIdentifier
=
createCachedParameterizedComparator
(
compareModulesByPreOrderIndexOrIdentifier
);
/**
* @param {ChunkGraph} chunkGraph the chunk graph
* @param {Module} a module
* @param {Module} b module
* @returns {-1|0|1} compare result
*/
const
compareModulesByIdOrIdentifier
=
(
chunkGraph
,
a
,
b
)
=>
{
const
cmp
=
compareIds
(
chunkGraph
.
getModuleId
(
a
),
chunkGraph
.
getModuleId
(
b
));
if
(
cmp
!==
0
)
return
cmp
;
return
compareIds
(
a
.
identifier
(),
b
.
identifier
());
};
/** @type {ParameterizedComparator<ChunkGraph, Module>} */
exports
.
compareModulesByIdOrIdentifier
=
createCachedParameterizedComparator
(
compareModulesByIdOrIdentifier
);
/**
* @param {ChunkGraph} chunkGraph the chunk graph
* @param {Chunk} a chunk
* @param {Chunk} b chunk
* @returns {-1|0|1} compare result
*/
const
compareChunks
=
(
chunkGraph
,
a
,
b
)
=>
{
return
chunkGraph
.
compareChunks
(
a
,
b
);
};
/** @type {ParameterizedComparator<ChunkGraph, Chunk>} */
exports
.
compareChunks
=
createCachedParameterizedComparator
(
compareChunks
);
/**
* @param {string|number} a first id
* @param {string|number} b second id
* @returns {-1|0|1} compare result
*/
const
compareIds
=
(
a
,
b
)
=>
{
if
(
typeof
a
!==
typeof
b
)
{
return
typeof
a
<
typeof
b
?
-
1
:
1
;
}
if
(
a
<
b
)
return
-
1
;
if
(
a
>
b
)
return
1
;
return
0
;
};
exports
.
compareIds
=
compareIds
;
/**
* @param {string} a first string
* @param {string} b second string
* @returns {-1|0|1} compare result
*/
const
compareStrings
=
(
a
,
b
)
=>
{
if
(
a
<
b
)
return
-
1
;
if
(
a
>
b
)
return
1
;
return
0
;
};
exports
.
compareStrings
=
compareStrings
;
/**
* @param {ChunkGroup} a first chunk group
* @param {ChunkGroup} b second chunk group
* @returns {-1|0|1} compare result
*/
const
compareChunkGroupsByIndex
=
(
a
,
b
)
=>
{
return
a
.
index
<
b
.
index
?
-
1
:
1
;
};
exports
.
compareChunkGroupsByIndex
=
compareChunkGroupsByIndex
;
/**
* @template K1 {Object}
* @template K2
* @template T
*/
class
TwoKeyWeakMap
{
constructor
()
{
/** @private @type {WeakMap<any, WeakMap<any, T>>} */
this
.
_map
=
new
WeakMap
();
}
/**
* @param {K1} key1 first key
* @param {K2} key2 second key
* @returns {T | undefined} value
*/
get
(
key1
,
key2
)
{
const
childMap
=
this
.
_map
.
get
(
key1
);
if
(
childMap
===
undefined
)
{
return
undefined
;
}
return
childMap
.
get
(
key2
);
}
/**
* @param {K1} key1 first key
* @param {K2} key2 second key
* @param {T | undefined} value new value
* @returns {void}
*/
set
(
key1
,
key2
,
value
)
{
let
childMap
=
this
.
_map
.
get
(
key1
);
if
(
childMap
===
undefined
)
{
childMap
=
new
WeakMap
();
this
.
_map
.
set
(
key1
,
childMap
);
}
childMap
.
set
(
key2
,
value
);
}
}
/** @type {TwoKeyWeakMap<Comparator<any>, Comparator<any>, Comparator<any>>}} */
const
concatComparatorsCache
=
new
TwoKeyWeakMap
();
/**
* @template T
* @param {Comparator<T>} c1 comparator
* @param {Comparator<T>} c2 comparator
* @param {Comparator<T>[]} cRest comparators
* @returns {Comparator<T>} comparator
*/
const
concatComparators
=
(
c1
,
c2
,
...
cRest
)
=>
{
if
(
cRest
.
length
>
0
)
{
const
[
c3
,
...
cRest2
]
=
cRest
;
return
concatComparators
(
c1
,
concatComparators
(
c2
,
c3
,
...
cRest2
));
}
const
cacheEntry
=
/** @type {Comparator<T>} */
(
concatComparatorsCache
.
get
(
c1
,
c2
));
if
(
cacheEntry
!==
undefined
)
return
cacheEntry
;
/**
* @param {T} a first value
* @param {T} b second value
* @returns {-1|0|1} compare result
*/
const
result
=
(
a
,
b
)
=>
{
const
res
=
c1
(
a
,
b
);
if
(
res
!==
0
)
return
res
;
return
c2
(
a
,
b
);
};
concatComparatorsCache
.
set
(
c1
,
c2
,
result
);
return
result
;
};
exports
.
concatComparators
=
concatComparators
;
/** @template A, B @typedef {(input: A) => B} Selector */
/** @type {TwoKeyWeakMap<Selector<any, any>, Comparator<any>, Comparator<any>>}} */
const
compareSelectCache
=
new
TwoKeyWeakMap
();
/**
* @template T
* @template R
* @param {Selector<T, R>} getter getter for value
* @param {Comparator<R>} comparator comparator
* @returns {Comparator<T>} comparator
*/
const
compareSelect
=
(
getter
,
comparator
)
=>
{
const
cacheEntry
=
compareSelectCache
.
get
(
getter
,
comparator
);
if
(
cacheEntry
!==
undefined
)
return
cacheEntry
;
/**
* @param {T} a first value
* @param {T} b second value
* @returns {-1|0|1} compare result
*/
const
result
=
(
a
,
b
)
=>
{
const
aValue
=
getter
(
a
);
const
bValue
=
getter
(
b
);
if
(
aValue
!==
undefined
&&
aValue
!==
null
)
{
if
(
bValue
!==
undefined
&&
bValue
!==
null
)
{
return
comparator
(
aValue
,
bValue
);
}
return
-
1
;
}
else
{
if
(
bValue
!==
undefined
&&
bValue
!==
null
)
{
return
1
;
}
return
0
;
}
};
compareSelectCache
.
set
(
getter
,
comparator
,
result
);
return
result
;
};
exports
.
compareSelect
=
compareSelect
;
/** @type {WeakMap<Comparator<any>, Comparator<Iterable<any>>>} */
const
compareIteratorsCache
=
new
WeakMap
();
/**
* @template T
* @param {Comparator<T>} elementComparator comparator for elements
* @returns {Comparator<Iterable<T>>} comparator for iterables of elements
*/
const
compareIterables
=
elementComparator
=>
{
const
cacheEntry
=
compareIteratorsCache
.
get
(
elementComparator
);
if
(
cacheEntry
!==
undefined
)
return
cacheEntry
;
/**
* @param {Iterable<T>} a first value
* @param {Iterable<T>} b second value
* @returns {-1|0|1} compare result
*/
const
result
=
(
a
,
b
)
=>
{
const
aI
=
a
[
Symbol
.
iterator
]();
const
bI
=
b
[
Symbol
.
iterator
]();
// eslint-disable-next-line no-constant-condition
while
(
true
)
{
const
aItem
=
aI
.
next
();
const
bItem
=
bI
.
next
();
if
(
aItem
.
done
)
{
return
bItem
.
done
?
0
:
-
1
;
}
else
if
(
bItem
.
done
)
{
return
1
;
}
const
res
=
elementComparator
(
aItem
.
value
,
bItem
.
value
);
if
(
res
!==
0
)
return
res
;
}
};
compareIteratorsCache
.
set
(
elementComparator
,
result
);
return
result
;
};
exports
.
compareIterables
=
compareIterables
;
// TODO this is no longer needed when minimum node.js version is >= 12
// since these versions ship with a stable sort function
/**
* @template T
* @param {Iterable<T>} iterable original ordered list
* @returns {Comparator<T>} comparator
*/
exports
.
keepOriginalOrder
=
iterable
=>
{
/** @type {Map<T, number>} */
const
map
=
new
Map
();
let
i
=
0
;
for
(
const
item
of
iterable
)
{
map
.
set
(
item
,
i
++
);
}
return
(
a
,
b
)
=>
compareNumbers
(
map
.
get
(
a
),
map
.
get
(
b
));
};
/**
* @param {ChunkGraph} chunkGraph the chunk graph
* @returns {Comparator<Chunk>} comparator
*/
exports
.
compareChunksNatural
=
chunkGraph
=>
{
const
cmpFn
=
exports
.
compareModulesById
(
chunkGraph
);
const
cmpIterableFn
=
compareIterables
(
cmpFn
);
return
concatComparators
(
compareSelect
(
chunk
=>
chunk
.
name
,
compareIds
),
compareSelect
(
chunk
=>
chunk
.
runtime
,
compareRuntime
),
compareSelect
(
/**
* @param {Chunk} chunk a chunk
* @returns {Iterable<Module>} modules
*/
chunk
=>
chunkGraph
.
getOrderedChunkModulesIterable
(
chunk
,
cmpFn
),
cmpIterableFn
)
);
};
/**
* Compare two locations
* @param {DependencyLocation} a A location node
* @param {DependencyLocation} b A location node
* @returns {-1|0|1} sorting comparator value
*/
exports
.
compareLocations
=
(
a
,
b
)
=>
{
let
isObjectA
=
typeof
a
===
"object"
&&
a
!==
null
;
let
isObjectB
=
typeof
b
===
"object"
&&
b
!==
null
;
if
(
!
isObjectA
||
!
isObjectB
)
{
if
(
isObjectA
)
return
1
;
if
(
isObjectB
)
return
-
1
;
return
0
;
}
if
(
"start"
in
a
&&
"start"
in
b
)
{
const
ap
=
a
.
start
;
const
bp
=
b
.
start
;
if
(
ap
.
line
<
bp
.
line
)
return
-
1
;
if
(
ap
.
line
>
bp
.
line
)
return
1
;
if
(
ap
.
column
<
bp
.
column
)
return
-
1
;
if
(
ap
.
column
>
bp
.
column
)
return
1
;
}
if
(
"name"
in
a
&&
"name"
in
b
)
{
if
(
a
.
name
<
b
.
name
)
return
-
1
;
if
(
a
.
name
>
b
.
name
)
return
1
;
}
if
(
"index"
in
a
&&
"index"
in
b
)
{
if
(
a
.
index
<
b
.
index
)
return
-
1
;
if
(
a
.
index
>
b
.
index
)
return
1
;
}
return
0
;
};
Event Timeline
Log In to Comment