Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F99948761
ProgressPlugin.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
Mon, Jan 27, 10:21
Size
16 KB
Mime Type
text/x-c++
Expires
Wed, Jan 29, 10:21 (1 d, 5 h)
Engine
blob
Format
Raw Data
Handle
23855535
Attached To
rOACCT Open Access Compliance Check Tool (OACCT)
ProgressPlugin.js
View Options
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict"
;
const
{
validate
}
=
require
(
"schema-utils"
);
const
schema
=
require
(
"../schemas/plugins/ProgressPlugin.json"
);
const
Compiler
=
require
(
"./Compiler"
);
const
MultiCompiler
=
require
(
"./MultiCompiler"
);
const
NormalModule
=
require
(
"./NormalModule"
);
const
{
contextify
}
=
require
(
"./util/identifier"
);
/** @typedef {import("../declarations/plugins/ProgressPlugin").HandlerFunction} HandlerFunction */
/** @typedef {import("../declarations/plugins/ProgressPlugin").ProgressPluginArgument} ProgressPluginArgument */
/** @typedef {import("../declarations/plugins/ProgressPlugin").ProgressPluginOptions} ProgressPluginOptions */
const
median3
=
(
a
,
b
,
c
)
=>
{
return
a
+
b
+
c
-
Math
.
max
(
a
,
b
,
c
)
-
Math
.
min
(
a
,
b
,
c
);
};
const
createDefaultHandler
=
(
profile
,
logger
)
=>
{
/** @type {{ value: string, time: number }[]} */
const
lastStateInfo
=
[];
const
defaultHandler
=
(
percentage
,
msg
,
...
args
)
=>
{
if
(
profile
)
{
if
(
percentage
===
0
)
{
lastStateInfo
.
length
=
0
;
}
const
fullState
=
[
msg
,
...
args
];
const
state
=
fullState
.
map
(
s
=>
s
.
replace
(
/\d+\/\d+ /g
,
""
));
const
now
=
Date
.
now
();
const
len
=
Math
.
max
(
state
.
length
,
lastStateInfo
.
length
);
for
(
let
i
=
len
;
i
>=
0
;
i
--
)
{
const
stateItem
=
i
<
state
.
length
?
state
[
i
]
:
undefined
;
const
lastStateItem
=
i
<
lastStateInfo
.
length
?
lastStateInfo
[
i
]
:
undefined
;
if
(
lastStateItem
)
{
if
(
stateItem
!==
lastStateItem
.
value
)
{
const
diff
=
now
-
lastStateItem
.
time
;
if
(
lastStateItem
.
value
)
{
let
reportState
=
lastStateItem
.
value
;
if
(
i
>
0
)
{
reportState
=
lastStateInfo
[
i
-
1
].
value
+
" > "
+
reportState
;
}
const
stateMsg
=
`
$
{
" | "
.
repeat
(
i
)}
$
{
diff
}
ms
$
{
reportState
}
`
;
const
d
=
diff
;
// This depends on timing so we ignore it for coverage
/* istanbul ignore next */
{
if
(
d
>
10000
)
{
logger
.
error
(
stateMsg
);
}
else
if
(
d
>
1000
)
{
logger
.
warn
(
stateMsg
);
}
else
if
(
d
>
10
)
{
logger
.
info
(
stateMsg
);
}
else
if
(
d
>
5
)
{
logger
.
log
(
stateMsg
);
}
else
{
logger
.
debug
(
stateMsg
);
}
}
}
if
(
stateItem
===
undefined
)
{
lastStateInfo
.
length
=
i
;
}
else
{
lastStateItem
.
value
=
stateItem
;
lastStateItem
.
time
=
now
;
lastStateInfo
.
length
=
i
+
1
;
}
}
}
else
{
lastStateInfo
[
i
]
=
{
value
:
stateItem
,
time
:
now
};
}
}
}
logger
.
status
(
`
$
{
Math
.
floor
(
percentage
*
100
)}
%
`
,
msg
,
...
args
);
if
(
percentage
===
1
||
(
!
msg
&&
args
.
length
===
0
))
logger
.
status
();
};
return
defaultHandler
;
};
/**
* @callback ReportProgress
* @param {number} p
* @param {...string[]} [args]
* @returns {void}
*/
/** @type {WeakMap<Compiler,ReportProgress>} */
const
progressReporters
=
new
WeakMap
();
class
ProgressPlugin
{
/**
* @param {Compiler} compiler the current compiler
* @returns {ReportProgress} a progress reporter, if any
*/
static
getReporter
(
compiler
)
{
return
progressReporters
.
get
(
compiler
);
}
/**
* @param {ProgressPluginArgument} options options
*/
constructor
(
options
)
{
if
(
typeof
options
===
"function"
)
{
options
=
{
handler
:
options
};
}
options
=
options
||
{};
validate
(
schema
,
options
,
{
name
:
"Progress Plugin"
,
baseDataPath
:
"options"
});
options
=
{
...
ProgressPlugin
.
defaultOptions
,
...
options
};
this
.
profile
=
options
.
profile
;
this
.
handler
=
options
.
handler
;
this
.
modulesCount
=
options
.
modulesCount
;
this
.
dependenciesCount
=
options
.
dependenciesCount
;
this
.
showEntries
=
options
.
entries
;
this
.
showModules
=
options
.
modules
;
this
.
showDependencies
=
options
.
dependencies
;
this
.
showActiveModules
=
options
.
activeModules
;
this
.
percentBy
=
options
.
percentBy
;
}
/**
* @param {Compiler | MultiCompiler} compiler webpack compiler
* @returns {void}
*/
apply
(
compiler
)
{
const
handler
=
this
.
handler
||
createDefaultHandler
(
this
.
profile
,
compiler
.
getInfrastructureLogger
(
"webpack.Progress"
)
);
if
(
compiler
instanceof
MultiCompiler
)
{
this
.
_applyOnMultiCompiler
(
compiler
,
handler
);
}
else
if
(
compiler
instanceof
Compiler
)
{
this
.
_applyOnCompiler
(
compiler
,
handler
);
}
}
/**
* @param {MultiCompiler} compiler webpack multi-compiler
* @param {HandlerFunction} handler function that executes for every progress step
* @returns {void}
*/
_applyOnMultiCompiler
(
compiler
,
handler
)
{
const
states
=
compiler
.
compilers
.
map
(
()
=>
/** @type {[number, ...string[]]} */
([
0
])
);
compiler
.
compilers
.
forEach
((
compiler
,
idx
)
=>
{
new
ProgressPlugin
((
p
,
msg
,
...
args
)
=>
{
states
[
idx
]
=
[
p
,
msg
,
...
args
];
let
sum
=
0
;
for
(
const
[
p
]
of
states
)
sum
+=
p
;
handler
(
sum
/
states
.
length
,
`
[
$
{
idx
}]
$
{
msg
}
`
,
...
args
);
}).
apply
(
compiler
);
});
}
/**
* @param {Compiler} compiler webpack compiler
* @param {HandlerFunction} handler function that executes for every progress step
* @returns {void}
*/
_applyOnCompiler
(
compiler
,
handler
)
{
const
showEntries
=
this
.
showEntries
;
const
showModules
=
this
.
showModules
;
const
showDependencies
=
this
.
showDependencies
;
const
showActiveModules
=
this
.
showActiveModules
;
let
lastActiveModule
=
""
;
let
currentLoader
=
""
;
let
lastModulesCount
=
0
;
let
lastDependenciesCount
=
0
;
let
lastEntriesCount
=
0
;
let
modulesCount
=
0
;
let
dependenciesCount
=
0
;
let
entriesCount
=
1
;
let
doneModules
=
0
;
let
doneDependencies
=
0
;
let
doneEntries
=
0
;
const
activeModules
=
new
Set
();
let
lastUpdate
=
0
;
const
updateThrottled
=
()
=>
{
if
(
lastUpdate
+
500
<
Date
.
now
())
update
();
};
const
update
=
()
=>
{
/** @type {string[]} */
const
items
=
[];
const
percentByModules
=
doneModules
/
Math
.
max
(
lastModulesCount
||
this
.
modulesCount
,
modulesCount
);
const
percentByEntries
=
doneEntries
/
Math
.
max
(
lastEntriesCount
||
this
.
dependenciesCount
,
entriesCount
);
const
percentByDependencies
=
doneDependencies
/
Math
.
max
(
lastDependenciesCount
,
dependenciesCount
);
let
percentageFactor
;
switch
(
this
.
percentBy
)
{
case
"entries"
:
percentageFactor
=
percentByEntries
;
break
;
case
"dependencies"
:
percentageFactor
=
percentByDependencies
;
break
;
case
"modules"
:
percentageFactor
=
percentByModules
;
break
;
default
:
percentageFactor
=
median3
(
percentByModules
,
percentByEntries
,
percentByDependencies
);
}
const
percentage
=
0.1
+
percentageFactor
*
0.55
;
if
(
currentLoader
)
{
items
.
push
(
`
import
loader
$
{
contextify
(
compiler
.
context
,
currentLoader
,
compiler
.
root
)}
`
);
}
else
{
const
statItems
=
[];
if
(
showEntries
)
{
statItems
.
push
(
`
$
{
doneEntries
}
/
$
{
entriesCount
}
entries
`
);
}
if
(
showDependencies
)
{
statItems
.
push
(
`
$
{
doneDependencies
}
/
$
{
dependenciesCount
}
dependencies
`
);
}
if
(
showModules
)
{
statItems
.
push
(
`
$
{
doneModules
}
/
$
{
modulesCount
}
modules
`
);
}
if
(
showActiveModules
)
{
statItems
.
push
(
`
$
{
activeModules
.
size
}
active
`
);
}
if
(
statItems
.
length
>
0
)
{
items
.
push
(
statItems
.
join
(
" "
));
}
if
(
showActiveModules
)
{
items
.
push
(
lastActiveModule
);
}
}
handler
(
percentage
,
"building"
,
...
items
);
lastUpdate
=
Date
.
now
();
};
const
factorizeAdd
=
()
=>
{
dependenciesCount
++
;
if
(
dependenciesCount
%
100
===
0
)
updateThrottled
();
};
const
factorizeDone
=
()
=>
{
doneDependencies
++
;
if
(
doneDependencies
%
100
===
0
)
updateThrottled
();
};
const
moduleAdd
=
()
=>
{
modulesCount
++
;
if
(
modulesCount
%
100
===
0
)
updateThrottled
();
};
// only used when showActiveModules is set
const
moduleBuild
=
module
=>
{
const
ident
=
module
.
identifier
();
if
(
ident
)
{
activeModules
.
add
(
ident
);
lastActiveModule
=
ident
;
update
();
}
};
const
entryAdd
=
(
entry
,
options
)
=>
{
entriesCount
++
;
if
(
entriesCount
%
10
===
0
)
updateThrottled
();
};
const
moduleDone
=
module
=>
{
doneModules
++
;
if
(
showActiveModules
)
{
const
ident
=
module
.
identifier
();
if
(
ident
)
{
activeModules
.
delete
(
ident
);
if
(
lastActiveModule
===
ident
)
{
lastActiveModule
=
""
;
for
(
const
m
of
activeModules
)
{
lastActiveModule
=
m
;
}
update
();
return
;
}
}
}
if
(
doneModules
%
100
===
0
)
updateThrottled
();
};
const
entryDone
=
(
entry
,
options
)
=>
{
doneEntries
++
;
update
();
};
const
cache
=
compiler
.
getCache
(
"ProgressPlugin"
)
.
getItemCache
(
"counts"
,
null
);
let
cacheGetPromise
;
compiler
.
hooks
.
beforeCompile
.
tap
(
"ProgressPlugin"
,
()
=>
{
if
(
!
cacheGetPromise
)
{
cacheGetPromise
=
cache
.
getPromise
().
then
(
data
=>
{
if
(
data
)
{
lastModulesCount
=
lastModulesCount
||
data
.
modulesCount
;
lastDependenciesCount
=
lastDependenciesCount
||
data
.
dependenciesCount
;
}
return
data
;
},
err
=>
{
// Ignore error
}
);
}
});
compiler
.
hooks
.
afterCompile
.
tapPromise
(
"ProgressPlugin"
,
compilation
=>
{
if
(
compilation
.
compiler
.
isChild
())
return
Promise
.
resolve
();
return
cacheGetPromise
.
then
(
async
oldData
=>
{
if
(
!
oldData
||
oldData
.
modulesCount
!==
modulesCount
||
oldData
.
dependenciesCount
!==
dependenciesCount
)
{
await
cache
.
storePromise
({
modulesCount
,
dependenciesCount
});
}
});
});
compiler
.
hooks
.
compilation
.
tap
(
"ProgressPlugin"
,
compilation
=>
{
if
(
compilation
.
compiler
.
isChild
())
return
;
lastModulesCount
=
modulesCount
;
lastEntriesCount
=
entriesCount
;
lastDependenciesCount
=
dependenciesCount
;
modulesCount
=
dependenciesCount
=
entriesCount
=
0
;
doneModules
=
doneDependencies
=
doneEntries
=
0
;
compilation
.
factorizeQueue
.
hooks
.
added
.
tap
(
"ProgressPlugin"
,
factorizeAdd
);
compilation
.
factorizeQueue
.
hooks
.
result
.
tap
(
"ProgressPlugin"
,
factorizeDone
);
compilation
.
addModuleQueue
.
hooks
.
added
.
tap
(
"ProgressPlugin"
,
moduleAdd
);
compilation
.
processDependenciesQueue
.
hooks
.
result
.
tap
(
"ProgressPlugin"
,
moduleDone
);
if
(
showActiveModules
)
{
compilation
.
hooks
.
buildModule
.
tap
(
"ProgressPlugin"
,
moduleBuild
);
}
compilation
.
hooks
.
addEntry
.
tap
(
"ProgressPlugin"
,
entryAdd
);
compilation
.
hooks
.
failedEntry
.
tap
(
"ProgressPlugin"
,
entryDone
);
compilation
.
hooks
.
succeedEntry
.
tap
(
"ProgressPlugin"
,
entryDone
);
// avoid dynamic require if bundled with webpack
// @ts-expect-error
if
(
typeof
__webpack_require__
!==
"function"
)
{
const
requiredLoaders
=
new
Set
();
NormalModule
.
getCompilationHooks
(
compilation
).
beforeLoaders
.
tap
(
"ProgressPlugin"
,
loaders
=>
{
for
(
const
loader
of
loaders
)
{
if
(
loader
.
type
!==
"module"
&&
!
requiredLoaders
.
has
(
loader
.
loader
)
)
{
requiredLoaders
.
add
(
loader
.
loader
);
currentLoader
=
loader
.
loader
;
update
();
require
(
loader
.
loader
);
}
}
if
(
currentLoader
)
{
currentLoader
=
""
;
update
();
}
}
);
}
const
hooks
=
{
finishModules
:
"finish module graph"
,
seal
:
"plugins"
,
optimizeDependencies
:
"dependencies optimization"
,
afterOptimizeDependencies
:
"after dependencies optimization"
,
beforeChunks
:
"chunk graph"
,
afterChunks
:
"after chunk graph"
,
optimize
:
"optimizing"
,
optimizeModules
:
"module optimization"
,
afterOptimizeModules
:
"after module optimization"
,
optimizeChunks
:
"chunk optimization"
,
afterOptimizeChunks
:
"after chunk optimization"
,
optimizeTree
:
"module and chunk tree optimization"
,
afterOptimizeTree
:
"after module and chunk tree optimization"
,
optimizeChunkModules
:
"chunk modules optimization"
,
afterOptimizeChunkModules
:
"after chunk modules optimization"
,
reviveModules
:
"module reviving"
,
beforeModuleIds
:
"before module ids"
,
moduleIds
:
"module ids"
,
optimizeModuleIds
:
"module id optimization"
,
afterOptimizeModuleIds
:
"module id optimization"
,
reviveChunks
:
"chunk reviving"
,
beforeChunkIds
:
"before chunk ids"
,
chunkIds
:
"chunk ids"
,
optimizeChunkIds
:
"chunk id optimization"
,
afterOptimizeChunkIds
:
"after chunk id optimization"
,
recordModules
:
"record modules"
,
recordChunks
:
"record chunks"
,
beforeModuleHash
:
"module hashing"
,
beforeCodeGeneration
:
"code generation"
,
beforeRuntimeRequirements
:
"runtime requirements"
,
beforeHash
:
"hashing"
,
afterHash
:
"after hashing"
,
recordHash
:
"record hash"
,
beforeModuleAssets
:
"module assets processing"
,
beforeChunkAssets
:
"chunk assets processing"
,
processAssets
:
"asset processing"
,
afterProcessAssets
:
"after asset optimization"
,
record
:
"recording"
,
afterSeal
:
"after seal"
};
const
numberOfHooks
=
Object
.
keys
(
hooks
).
length
;
Object
.
keys
(
hooks
).
forEach
((
name
,
idx
)
=>
{
const
title
=
hooks
[
name
];
const
percentage
=
(
idx
/
numberOfHooks
)
*
0.25
+
0.7
;
compilation
.
hooks
[
name
].
intercept
({
name
:
"ProgressPlugin"
,
call
()
{
handler
(
percentage
,
"sealing"
,
title
);
},
done
()
{
progressReporters
.
set
(
compiler
,
undefined
);
handler
(
percentage
,
"sealing"
,
title
);
},
result
()
{
handler
(
percentage
,
"sealing"
,
title
);
},
error
()
{
handler
(
percentage
,
"sealing"
,
title
);
},
tap
(
tap
)
{
// p is percentage from 0 to 1
// args is any number of messages in a hierarchical matter
progressReporters
.
set
(
compilation
.
compiler
,
(
p
,
...
args
)
=>
{
handler
(
percentage
,
"sealing"
,
title
,
tap
.
name
,
...
args
);
});
handler
(
percentage
,
"sealing"
,
title
,
tap
.
name
);
}
});
});
});
compiler
.
hooks
.
make
.
intercept
({
name
:
"ProgressPlugin"
,
call
()
{
handler
(
0.1
,
"building"
);
},
done
()
{
handler
(
0.65
,
"building"
);
}
});
const
interceptHook
=
(
hook
,
progress
,
category
,
name
)
=>
{
hook
.
intercept
({
name
:
"ProgressPlugin"
,
call
()
{
handler
(
progress
,
category
,
name
);
},
done
()
{
progressReporters
.
set
(
compiler
,
undefined
);
handler
(
progress
,
category
,
name
);
},
result
()
{
handler
(
progress
,
category
,
name
);
},
error
()
{
handler
(
progress
,
category
,
name
);
},
tap
(
tap
)
{
progressReporters
.
set
(
compiler
,
(
p
,
...
args
)
=>
{
handler
(
progress
,
category
,
name
,
tap
.
name
,
...
args
);
});
handler
(
progress
,
category
,
name
,
tap
.
name
);
}
});
};
compiler
.
cache
.
hooks
.
endIdle
.
intercept
({
name
:
"ProgressPlugin"
,
call
()
{
handler
(
0
,
""
);
}
});
interceptHook
(
compiler
.
cache
.
hooks
.
endIdle
,
0.01
,
"cache"
,
"end idle"
);
compiler
.
hooks
.
initialize
.
intercept
({
name
:
"ProgressPlugin"
,
call
()
{
handler
(
0
,
""
);
}
});
interceptHook
(
compiler
.
hooks
.
initialize
,
0.01
,
"setup"
,
"initialize"
);
interceptHook
(
compiler
.
hooks
.
beforeRun
,
0.02
,
"setup"
,
"before run"
);
interceptHook
(
compiler
.
hooks
.
run
,
0.03
,
"setup"
,
"run"
);
interceptHook
(
compiler
.
hooks
.
watchRun
,
0.03
,
"setup"
,
"watch run"
);
interceptHook
(
compiler
.
hooks
.
normalModuleFactory
,
0.04
,
"setup"
,
"normal module factory"
);
interceptHook
(
compiler
.
hooks
.
contextModuleFactory
,
0.05
,
"setup"
,
"context module factory"
);
interceptHook
(
compiler
.
hooks
.
beforeCompile
,
0.06
,
"setup"
,
"before compile"
);
interceptHook
(
compiler
.
hooks
.
compile
,
0.07
,
"setup"
,
"compile"
);
interceptHook
(
compiler
.
hooks
.
thisCompilation
,
0.08
,
"setup"
,
"compilation"
);
interceptHook
(
compiler
.
hooks
.
compilation
,
0.09
,
"setup"
,
"compilation"
);
interceptHook
(
compiler
.
hooks
.
finishMake
,
0.69
,
"building"
,
"finish"
);
interceptHook
(
compiler
.
hooks
.
emit
,
0.95
,
"emitting"
,
"emit"
);
interceptHook
(
compiler
.
hooks
.
afterEmit
,
0.98
,
"emitting"
,
"after emit"
);
interceptHook
(
compiler
.
hooks
.
done
,
0.99
,
"done"
,
"plugins"
);
compiler
.
hooks
.
done
.
intercept
({
name
:
"ProgressPlugin"
,
done
()
{
handler
(
0.99
,
""
);
}
});
interceptHook
(
compiler
.
cache
.
hooks
.
storeBuildDependencies
,
0.99
,
"cache"
,
"store build dependencies"
);
interceptHook
(
compiler
.
cache
.
hooks
.
shutdown
,
0.99
,
"cache"
,
"shutdown"
);
interceptHook
(
compiler
.
cache
.
hooks
.
beginIdle
,
0.99
,
"cache"
,
"begin idle"
);
interceptHook
(
compiler
.
hooks
.
watchClose
,
0.99
,
"end"
,
"closing watch compilation"
);
compiler
.
cache
.
hooks
.
beginIdle
.
intercept
({
name
:
"ProgressPlugin"
,
done
()
{
handler
(
1
,
""
);
}
});
compiler
.
cache
.
hooks
.
shutdown
.
intercept
({
name
:
"ProgressPlugin"
,
done
()
{
handler
(
1
,
""
);
}
});
}
}
ProgressPlugin
.
defaultOptions
=
{
profile
:
false
,
modulesCount
:
5000
,
dependenciesCount
:
10000
,
modules
:
true
,
dependencies
:
true
,
activeModules
:
false
,
entries
:
true
};
module
.
exports
=
ProgressPlugin
;
Event Timeline
Log In to Comment