5
5
* @typedef {Pick<CompileOptions, 'SourceMapGenerator'> } Defaults
6
6
* @typedef {Omit<CompileOptions, 'SourceMapGenerator'> } Options
7
7
* @typedef {import('webpack').LoaderContext<unknown> } LoaderContext
8
+ * @typedef {import('webpack').Compiler } WebpackCompiler
8
9
* @typedef {(vfileCompatible: VFileCompatible) => Promise<VFile> } Process
9
10
*/
10
11
12
+ import { createHash } from 'node:crypto'
11
13
import { SourceMapGenerator } from 'source-map'
12
14
import { createFormatAwareProcessors } from '@mdx-js/mdx/lib/util/create-format-aware-processors.js'
13
15
14
- /** @type {WeakMap<CompileOptions, Process> } */
16
+ const own = { } . hasOwnProperty
17
+
18
+ // Note: the cache is heavily inspired by:
19
+ // <https://github.com/TypeStrong/ts-loader/blob/5c030bf/src/instance-cache.ts>
20
+ const marker = /** @type {WebpackCompiler } */ ( { } )
21
+ /** @type {WeakMap<WebpackCompiler, Map<string, Process>> } */
15
22
const cache = new WeakMap ( )
16
23
17
24
/**
@@ -28,6 +35,10 @@ export function loader(value, callback) {
28
35
const defaults = this . sourceMap ? { SourceMapGenerator} : { }
29
36
const options = /** @type {CompileOptions } */ ( this . getOptions ( ) )
30
37
const config = { ...defaults , ...options }
38
+ const hash = getOptionsHash ( options )
39
+ // Some loaders set `undefined` (see `TypeStrong/ts-loader`).
40
+ /* c8 ignore next */
41
+ const compiler = this . _compiler || marker
31
42
32
43
/* Removed option. */
33
44
/* c8 ignore next 5 */
@@ -37,15 +48,44 @@ export function loader(value, callback) {
37
48
)
38
49
}
39
50
40
- let process = cache . get ( config )
51
+ let map = cache . get ( compiler )
52
+
53
+ if ( ! map ) {
54
+ map = new Map ( )
55
+ cache . set ( compiler , map )
56
+ }
57
+
58
+ let process = map . get ( hash )
41
59
42
60
if ( ! process ) {
43
61
process = createFormatAwareProcessors ( config ) . process
44
- cache . set ( config , process )
62
+ map . set ( hash , process )
45
63
}
46
64
47
65
process ( { value, path : this . resourcePath } ) . then ( ( file ) => {
48
66
callback ( null , file . value , file . map )
49
67
return file
50
68
} , callback )
51
69
}
70
+
71
+ /**
72
+ * @param {Options } options
73
+ */
74
+ function getOptionsHash ( options ) {
75
+ const hash = createHash ( 'sha256' )
76
+ /** @type {keyof Options } */
77
+ let key
78
+
79
+ for ( key in options ) {
80
+ if ( own . call ( options , key ) ) {
81
+ const value = options [ key ]
82
+
83
+ if ( value !== undefined ) {
84
+ const valueString = JSON . stringify ( value )
85
+ hash . update ( key + valueString )
86
+ }
87
+ }
88
+ }
89
+
90
+ return hash . digest ( 'hex' ) . slice ( 0 , 16 )
91
+ }
1 commit comments
vercel[bot] commentedon Jan 26, 2022
Successfully deployed to the following URLs: