UNPKG

3.97 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const { AsyncParallelHook, AsyncSeriesBailHook, SyncHook } = require("tapable");
9const {
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
36const 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
48class 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
156Cache.STAGE_MEMORY = -10;
157Cache.STAGE_DEFAULT = 0;
158Cache.STAGE_DISK = 10;
159Cache.STAGE_NETWORK = 20;
160
161module.exports = Cache;