1 | /*
|
---|
2 | MIT License http://www.opensource.org/licenses/mit-license.php
|
---|
3 | Author Tobias Koppers @sokra
|
---|
4 | */
|
---|
5 |
|
---|
6 | "use strict";
|
---|
7 |
|
---|
8 | const { AsyncParallelHook, AsyncSeriesBailHook, SyncHook } = require("tapable");
|
---|
9 | const {
|
---|
10 | makeWebpackError,
|
---|
11 | makeWebpackErrorCallback
|
---|
12 | } = require("./HookWebpackError");
|
---|
13 |
|
---|
14 | /** @typedef {import("./WebpackError")} WebpackError */
|
---|
15 |
|
---|
16 | /**
|
---|
17 | * @typedef {Object} Etag
|
---|
18 | * @property {function(): string} toString
|
---|
19 | */
|
---|
20 |
|
---|
21 | /**
|
---|
22 | * @template T
|
---|
23 | * @callback CallbackCache
|
---|
24 | * @param {WebpackError=} err
|
---|
25 | * @param {T=} result
|
---|
26 | * @returns {void}
|
---|
27 | */
|
---|
28 |
|
---|
29 | /**
|
---|
30 | * @callback GotHandler
|
---|
31 | * @param {any} result
|
---|
32 | * @param {function(Error=): void} callback
|
---|
33 | * @returns {void}
|
---|
34 | */
|
---|
35 |
|
---|
36 | const needCalls = (times, callback) => {
|
---|
37 | return err => {
|
---|
38 | if (--times === 0) {
|
---|
39 | return callback(err);
|
---|
40 | }
|
---|
41 | if (err && times > 0) {
|
---|
42 | times = 0;
|
---|
43 | return callback(err);
|
---|
44 | }
|
---|
45 | };
|
---|
46 | };
|
---|
47 |
|
---|
48 | class Cache {
|
---|
49 | constructor() {
|
---|
50 | this.hooks = {
|
---|
51 | /** @type {AsyncSeriesBailHook<[string, Etag | null, GotHandler[]], any>} */
|
---|
52 | get: new AsyncSeriesBailHook(["identifier", "etag", "gotHandlers"]),
|
---|
53 | /** @type {AsyncParallelHook<[string, Etag | null, any]>} */
|
---|
54 | store: new AsyncParallelHook(["identifier", "etag", "data"]),
|
---|
55 | /** @type {AsyncParallelHook<[Iterable<string>]>} */
|
---|
56 | storeBuildDependencies: new AsyncParallelHook(["dependencies"]),
|
---|
57 | /** @type {SyncHook<[]>} */
|
---|
58 | beginIdle: new SyncHook([]),
|
---|
59 | /** @type {AsyncParallelHook<[]>} */
|
---|
60 | endIdle: new AsyncParallelHook([]),
|
---|
61 | /** @type {AsyncParallelHook<[]>} */
|
---|
62 | shutdown: new AsyncParallelHook([])
|
---|
63 | };
|
---|
64 | }
|
---|
65 |
|
---|
66 | /**
|
---|
67 | * @template T
|
---|
68 | * @param {string} identifier the cache identifier
|
---|
69 | * @param {Etag | null} etag the etag
|
---|
70 | * @param {CallbackCache<T>} callback signals when the value is retrieved
|
---|
71 | * @returns {void}
|
---|
72 | */
|
---|
73 | get(identifier, etag, callback) {
|
---|
74 | const gotHandlers = [];
|
---|
75 | this.hooks.get.callAsync(identifier, etag, gotHandlers, (err, result) => {
|
---|
76 | if (err) {
|
---|
77 | callback(makeWebpackError(err, "Cache.hooks.get"));
|
---|
78 | return;
|
---|
79 | }
|
---|
80 | if (result === null) {
|
---|
81 | result = undefined;
|
---|
82 | }
|
---|
83 | if (gotHandlers.length > 1) {
|
---|
84 | const innerCallback = needCalls(gotHandlers.length, () =>
|
---|
85 | callback(null, result)
|
---|
86 | );
|
---|
87 | for (const gotHandler of gotHandlers) {
|
---|
88 | gotHandler(result, innerCallback);
|
---|
89 | }
|
---|
90 | } else if (gotHandlers.length === 1) {
|
---|
91 | gotHandlers[0](result, () => callback(null, result));
|
---|
92 | } else {
|
---|
93 | callback(null, result);
|
---|
94 | }
|
---|
95 | });
|
---|
96 | }
|
---|
97 |
|
---|
98 | /**
|
---|
99 | * @template T
|
---|
100 | * @param {string} identifier the cache identifier
|
---|
101 | * @param {Etag | null} etag the etag
|
---|
102 | * @param {T} data the value to store
|
---|
103 | * @param {CallbackCache<void>} callback signals when the value is stored
|
---|
104 | * @returns {void}
|
---|
105 | */
|
---|
106 | store(identifier, etag, data, callback) {
|
---|
107 | this.hooks.store.callAsync(
|
---|
108 | identifier,
|
---|
109 | etag,
|
---|
110 | data,
|
---|
111 | makeWebpackErrorCallback(callback, "Cache.hooks.store")
|
---|
112 | );
|
---|
113 | }
|
---|
114 |
|
---|
115 | /**
|
---|
116 | * After this method has succeeded the cache can only be restored when build dependencies are
|
---|
117 | * @param {Iterable<string>} dependencies list of all build dependencies
|
---|
118 | * @param {CallbackCache<void>} callback signals when the dependencies are stored
|
---|
119 | * @returns {void}
|
---|
120 | */
|
---|
121 | storeBuildDependencies(dependencies, callback) {
|
---|
122 | this.hooks.storeBuildDependencies.callAsync(
|
---|
123 | dependencies,
|
---|
124 | makeWebpackErrorCallback(callback, "Cache.hooks.storeBuildDependencies")
|
---|
125 | );
|
---|
126 | }
|
---|
127 |
|
---|
128 | /**
|
---|
129 | * @returns {void}
|
---|
130 | */
|
---|
131 | beginIdle() {
|
---|
132 | this.hooks.beginIdle.call();
|
---|
133 | }
|
---|
134 |
|
---|
135 | /**
|
---|
136 | * @param {CallbackCache<void>} callback signals when the call finishes
|
---|
137 | * @returns {void}
|
---|
138 | */
|
---|
139 | endIdle(callback) {
|
---|
140 | this.hooks.endIdle.callAsync(
|
---|
141 | makeWebpackErrorCallback(callback, "Cache.hooks.endIdle")
|
---|
142 | );
|
---|
143 | }
|
---|
144 |
|
---|
145 | /**
|
---|
146 | * @param {CallbackCache<void>} callback signals when the call finishes
|
---|
147 | * @returns {void}
|
---|
148 | */
|
---|
149 | shutdown(callback) {
|
---|
150 | this.hooks.shutdown.callAsync(
|
---|
151 | makeWebpackErrorCallback(callback, "Cache.hooks.shutdown")
|
---|
152 | );
|
---|
153 | }
|
---|
154 | }
|
---|
155 |
|
---|
156 | Cache.STAGE_MEMORY = -10;
|
---|
157 | Cache.STAGE_DEFAULT = 0;
|
---|
158 | Cache.STAGE_DISK = 10;
|
---|
159 | Cache.STAGE_NETWORK = 20;
|
---|
160 |
|
---|
161 | module.exports = Cache;
|
---|