| [9af201e] | 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 Source = require("./Source");
|
|---|
| 9 | const streamAndGetSourceAndMap = require("./helpers/streamAndGetSourceAndMap");
|
|---|
| 10 | const streamChunksOfRawSource = require("./helpers/streamChunksOfRawSource");
|
|---|
| 11 | const streamChunksOfSourceMap = require("./helpers/streamChunksOfSourceMap");
|
|---|
| 12 | const {
|
|---|
| 13 | isDualStringBufferCachingEnabled,
|
|---|
| 14 | } = require("./helpers/stringBufferUtils");
|
|---|
| 15 |
|
|---|
| 16 | /** @typedef {import("./Source").HashLike} HashLike */
|
|---|
| 17 | /** @typedef {import("./Source").MapOptions} MapOptions */
|
|---|
| 18 | /** @typedef {import("./Source").RawSourceMap} RawSourceMap */
|
|---|
| 19 | /** @typedef {import("./Source").SourceAndMap} SourceAndMap */
|
|---|
| 20 | /** @typedef {import("./Source").SourceValue} SourceValue */
|
|---|
| 21 | /** @typedef {import("./helpers/getGeneratedSourceInfo").GeneratedSourceInfo} GeneratedSourceInfo */
|
|---|
| 22 | /** @typedef {import("./helpers/streamChunks").OnChunk} OnChunk */
|
|---|
| 23 | /** @typedef {import("./helpers/streamChunks").OnName} OnName */
|
|---|
| 24 | /** @typedef {import("./helpers/streamChunks").OnSource} OnSource */
|
|---|
| 25 | /** @typedef {import("./helpers/streamChunks").Options} Options */
|
|---|
| 26 |
|
|---|
| 27 | /**
|
|---|
| 28 | * @typedef {object} BufferedMap
|
|---|
| 29 | * @property {number} version version
|
|---|
| 30 | * @property {string[]} sources sources
|
|---|
| 31 | * @property {string[]} names name
|
|---|
| 32 | * @property {string=} sourceRoot source root
|
|---|
| 33 | * @property {(Buffer | "")[]=} sourcesContent sources content
|
|---|
| 34 | * @property {Buffer=} mappings mappings
|
|---|
| 35 | * @property {string} file file
|
|---|
| 36 | */
|
|---|
| 37 |
|
|---|
| 38 | /**
|
|---|
| 39 | * @param {null | RawSourceMap} map map
|
|---|
| 40 | * @returns {null | BufferedMap} buffered map
|
|---|
| 41 | */
|
|---|
| 42 | const mapToBufferedMap = (map) => {
|
|---|
| 43 | if (typeof map !== "object" || !map) return map;
|
|---|
| 44 | const bufferedMap =
|
|---|
| 45 | /** @type {BufferedMap} */
|
|---|
| 46 | (/** @type {unknown} */ ({ ...map }));
|
|---|
| 47 | if (map.mappings) {
|
|---|
| 48 | bufferedMap.mappings = Buffer.from(map.mappings, "utf8");
|
|---|
| 49 | }
|
|---|
| 50 | if (map.sourcesContent) {
|
|---|
| 51 | bufferedMap.sourcesContent = map.sourcesContent.map(
|
|---|
| 52 | (str) => str && Buffer.from(str, "utf8"),
|
|---|
| 53 | );
|
|---|
| 54 | }
|
|---|
| 55 | return bufferedMap;
|
|---|
| 56 | };
|
|---|
| 57 |
|
|---|
| 58 | /**
|
|---|
| 59 | * @param {null | BufferedMap} bufferedMap buffered map
|
|---|
| 60 | * @returns {null | RawSourceMap} map
|
|---|
| 61 | */
|
|---|
| 62 | const bufferedMapToMap = (bufferedMap) => {
|
|---|
| 63 | if (typeof bufferedMap !== "object" || !bufferedMap) return bufferedMap;
|
|---|
| 64 | const map =
|
|---|
| 65 | /** @type {RawSourceMap} */
|
|---|
| 66 | (/** @type {unknown} */ ({ ...bufferedMap }));
|
|---|
| 67 | if (bufferedMap.mappings) {
|
|---|
| 68 | map.mappings = bufferedMap.mappings.toString("utf8");
|
|---|
| 69 | }
|
|---|
| 70 | if (bufferedMap.sourcesContent) {
|
|---|
| 71 | map.sourcesContent = bufferedMap.sourcesContent.map(
|
|---|
| 72 | (buffer) => buffer && buffer.toString("utf8"),
|
|---|
| 73 | );
|
|---|
| 74 | }
|
|---|
| 75 | return map;
|
|---|
| 76 | };
|
|---|
| 77 |
|
|---|
| 78 | /** @typedef {{ map?: null | RawSourceMap, bufferedMap?: null | BufferedMap }} BufferEntry */
|
|---|
| 79 | /** @typedef {Map<string, BufferEntry>} BufferedMaps */
|
|---|
| 80 |
|
|---|
| 81 | const CACHE_KEY_EMPTY = "{}";
|
|---|
| 82 | const CACHE_KEY_COLUMNS_FALSE = '{"columns":false}';
|
|---|
| 83 | const CACHE_KEY_COLUMNS_TRUE = '{"columns":true}';
|
|---|
| 84 |
|
|---|
| 85 | /**
|
|---|
| 86 | * Fast-path replacement for `JSON.stringify(options)` when used as a cache
|
|---|
| 87 | * key. MapOptions / streamChunks Options are both small boolean-only shapes
|
|---|
| 88 | * and the overwhelmingly common shapes (`undefined`, `{}`, `{columns}`) can
|
|---|
| 89 | * be keyed without calling `JSON.stringify`, which dominates short-circuit
|
|---|
| 90 | * cache lookups. Falls back to `JSON.stringify` for any other shape so keys
|
|---|
| 91 | * remain compatible with previously cached `BufferedMaps` entries.
|
|---|
| 92 | * @param {undefined | MapOptions | Options} options options
|
|---|
| 93 | * @returns {string} cache key
|
|---|
| 94 | */
|
|---|
| 95 | const getCacheKey = (options) => {
|
|---|
| 96 | if (!options) return CACHE_KEY_EMPTY;
|
|---|
| 97 | const { columns } = options;
|
|---|
| 98 | if (
|
|---|
| 99 | /** @type {Options} */ (options).source === undefined &&
|
|---|
| 100 | /** @type {Options} */ (options).finalSource === undefined &&
|
|---|
| 101 | /** @type {MapOptions} */ (options).module === undefined
|
|---|
| 102 | ) {
|
|---|
| 103 | if (columns === undefined) return CACHE_KEY_EMPTY;
|
|---|
| 104 | return columns ? CACHE_KEY_COLUMNS_TRUE : CACHE_KEY_COLUMNS_FALSE;
|
|---|
| 105 | }
|
|---|
| 106 | return JSON.stringify(options);
|
|---|
| 107 | };
|
|---|
| 108 |
|
|---|
| 109 | /**
|
|---|
| 110 | * @typedef {object} CachedData
|
|---|
| 111 | * @property {boolean=} source source
|
|---|
| 112 | * @property {Buffer} buffer buffer
|
|---|
| 113 | * @property {number=} size size
|
|---|
| 114 | * @property {BufferedMaps} maps maps
|
|---|
| 115 | * @property {(string | Buffer)[]=} hash hash
|
|---|
| 116 | */
|
|---|
| 117 |
|
|---|
| 118 | class CachedSource extends Source {
|
|---|
| 119 | /**
|
|---|
| 120 | * @param {Source | (() => Source)} source source
|
|---|
| 121 | * @param {CachedData=} cachedData cached data
|
|---|
| 122 | */
|
|---|
| 123 | constructor(source, cachedData) {
|
|---|
| 124 | super();
|
|---|
| 125 | /**
|
|---|
| 126 | * @private
|
|---|
| 127 | * @type {Source | (() => Source)}
|
|---|
| 128 | */
|
|---|
| 129 | this._source = source;
|
|---|
| 130 | /**
|
|---|
| 131 | * @private
|
|---|
| 132 | * @type {undefined | string}
|
|---|
| 133 | */
|
|---|
| 134 | this._cachedSource = undefined;
|
|---|
| 135 | // Split on `cachedData` once instead of re-evaluating the ternary for
|
|---|
| 136 | // every field. Under the interpreter (and CodSpeed's simulation) each
|
|---|
| 137 | // ternary is a separate branch; consolidating cuts the per-instance
|
|---|
| 138 | // branch count roughly in half.
|
|---|
| 139 | if (cachedData) {
|
|---|
| 140 | /**
|
|---|
| 141 | * @private
|
|---|
| 142 | * @type {boolean | undefined}
|
|---|
| 143 | */
|
|---|
| 144 | this._cachedSourceType = cachedData.source;
|
|---|
| 145 | /**
|
|---|
| 146 | * @private
|
|---|
| 147 | * @type {Buffer | undefined}
|
|---|
| 148 | */
|
|---|
| 149 | this._cachedBuffer = cachedData.buffer;
|
|---|
| 150 | /**
|
|---|
| 151 | * @private
|
|---|
| 152 | * @type {number | undefined}
|
|---|
| 153 | */
|
|---|
| 154 | this._cachedSize = cachedData.size;
|
|---|
| 155 | /**
|
|---|
| 156 | * @private
|
|---|
| 157 | * @type {BufferedMaps}
|
|---|
| 158 | */
|
|---|
| 159 | this._cachedMaps = cachedData.maps;
|
|---|
| 160 | /**
|
|---|
| 161 | * @private
|
|---|
| 162 | * @type {(string | Buffer)[] | undefined}
|
|---|
| 163 | */
|
|---|
| 164 | this._cachedHashUpdate = cachedData.hash;
|
|---|
| 165 | } else {
|
|---|
| 166 | this._cachedSourceType = undefined;
|
|---|
| 167 | this._cachedBuffer = undefined;
|
|---|
| 168 | this._cachedSize = undefined;
|
|---|
| 169 | this._cachedMaps = new Map();
|
|---|
| 170 | this._cachedHashUpdate = undefined;
|
|---|
| 171 | }
|
|---|
| 172 | }
|
|---|
| 173 |
|
|---|
| 174 | /**
|
|---|
| 175 | * @returns {CachedData} cached data
|
|---|
| 176 | */
|
|---|
| 177 | getCachedData() {
|
|---|
| 178 | /** @type {BufferedMaps} */
|
|---|
| 179 | const bufferedMaps = new Map();
|
|---|
| 180 | for (const pair of this._cachedMaps) {
|
|---|
| 181 | const [, cacheEntry] = pair;
|
|---|
| 182 | if (cacheEntry.bufferedMap === undefined) {
|
|---|
| 183 | cacheEntry.bufferedMap = mapToBufferedMap(
|
|---|
| 184 | this._getMapFromCacheEntry(cacheEntry),
|
|---|
| 185 | );
|
|---|
| 186 | }
|
|---|
| 187 | bufferedMaps.set(pair[0], {
|
|---|
| 188 | map: undefined,
|
|---|
| 189 | bufferedMap: cacheEntry.bufferedMap,
|
|---|
| 190 | });
|
|---|
| 191 | }
|
|---|
| 192 | return {
|
|---|
| 193 | // We don't want to cache strings
|
|---|
| 194 | // So if we have a caches sources
|
|---|
| 195 | // create a buffer from it and only store
|
|---|
| 196 | // if it was a Buffer or string
|
|---|
| 197 | buffer: this._cachedSource
|
|---|
| 198 | ? this.buffer()
|
|---|
| 199 | : /** @type {Buffer} */ (this._cachedBuffer),
|
|---|
| 200 | source:
|
|---|
| 201 | this._cachedSourceType !== undefined
|
|---|
| 202 | ? this._cachedSourceType
|
|---|
| 203 | : typeof this._cachedSource === "string"
|
|---|
| 204 | ? true
|
|---|
| 205 | : Buffer.isBuffer(this._cachedSource)
|
|---|
| 206 | ? false
|
|---|
| 207 | : undefined,
|
|---|
| 208 | size: this._cachedSize,
|
|---|
| 209 | maps: bufferedMaps,
|
|---|
| 210 | hash: this._cachedHashUpdate,
|
|---|
| 211 | };
|
|---|
| 212 | }
|
|---|
| 213 |
|
|---|
| 214 | originalLazy() {
|
|---|
| 215 | return this._source;
|
|---|
| 216 | }
|
|---|
| 217 |
|
|---|
| 218 | original() {
|
|---|
| 219 | if (typeof this._source === "function") this._source = this._source();
|
|---|
| 220 | return this._source;
|
|---|
| 221 | }
|
|---|
| 222 |
|
|---|
| 223 | /**
|
|---|
| 224 | * @returns {SourceValue} source
|
|---|
| 225 | */
|
|---|
| 226 | source() {
|
|---|
| 227 | // Fully inlined _getCachedSource: both warm- and cold-cache paths skip
|
|---|
| 228 | // the prototype method lookup / stack frame the interpreter would
|
|---|
| 229 | // otherwise pay on every call.
|
|---|
| 230 | if (this._cachedSource !== undefined) return this._cachedSource;
|
|---|
| 231 | const cachedBuffer = this._cachedBuffer;
|
|---|
| 232 | const cachedSourceType = this._cachedSourceType;
|
|---|
| 233 | if (cachedBuffer !== undefined && cachedSourceType !== undefined) {
|
|---|
| 234 | const value = cachedSourceType
|
|---|
| 235 | ? cachedBuffer.toString("utf8")
|
|---|
| 236 | : cachedBuffer;
|
|---|
| 237 | if (isDualStringBufferCachingEnabled()) {
|
|---|
| 238 | this._cachedSource = /** @type {string} */ (value);
|
|---|
| 239 | }
|
|---|
| 240 | return /** @type {string} */ (value);
|
|---|
| 241 | }
|
|---|
| 242 | return (this._cachedSource =
|
|---|
| 243 | /** @type {string} */
|
|---|
| 244 | (this.original().source()));
|
|---|
| 245 | }
|
|---|
| 246 |
|
|---|
| 247 | /**
|
|---|
| 248 | * @private
|
|---|
| 249 | * @param {BufferEntry} cacheEntry cache entry
|
|---|
| 250 | * @returns {null | RawSourceMap} raw source map
|
|---|
| 251 | */
|
|---|
| 252 | _getMapFromCacheEntry(cacheEntry) {
|
|---|
| 253 | if (cacheEntry.map !== undefined) {
|
|---|
| 254 | return cacheEntry.map;
|
|---|
| 255 | } else if (cacheEntry.bufferedMap !== undefined) {
|
|---|
| 256 | return (cacheEntry.map = bufferedMapToMap(cacheEntry.bufferedMap));
|
|---|
| 257 | }
|
|---|
| 258 |
|
|---|
| 259 | return null;
|
|---|
| 260 | }
|
|---|
| 261 |
|
|---|
| 262 | /**
|
|---|
| 263 | * @private
|
|---|
| 264 | * @returns {undefined | string} cached source
|
|---|
| 265 | */
|
|---|
| 266 | _getCachedSource() {
|
|---|
| 267 | if (this._cachedSource !== undefined) return this._cachedSource;
|
|---|
| 268 | if (this._cachedBuffer && this._cachedSourceType !== undefined) {
|
|---|
| 269 | const value = this._cachedSourceType
|
|---|
| 270 | ? this._cachedBuffer.toString("utf8")
|
|---|
| 271 | : this._cachedBuffer;
|
|---|
| 272 | if (isDualStringBufferCachingEnabled()) {
|
|---|
| 273 | this._cachedSource = /** @type {string} */ (value);
|
|---|
| 274 | }
|
|---|
| 275 | return /** @type {string} */ (value);
|
|---|
| 276 | }
|
|---|
| 277 | }
|
|---|
| 278 |
|
|---|
| 279 | /**
|
|---|
| 280 | * @returns {Buffer} buffer
|
|---|
| 281 | */
|
|---|
| 282 | buffer() {
|
|---|
| 283 | if (this._cachedBuffer !== undefined) return this._cachedBuffer;
|
|---|
| 284 | if (this._cachedBuffers !== undefined) {
|
|---|
| 285 | return (this._cachedBuffer = Buffer.concat(this._cachedBuffers));
|
|---|
| 286 | }
|
|---|
| 287 | if (this._cachedSource !== undefined) {
|
|---|
| 288 | const value = Buffer.isBuffer(this._cachedSource)
|
|---|
| 289 | ? this._cachedSource
|
|---|
| 290 | : Buffer.from(this._cachedSource, "utf8");
|
|---|
| 291 | if (isDualStringBufferCachingEnabled()) {
|
|---|
| 292 | this._cachedBuffer = value;
|
|---|
| 293 | }
|
|---|
| 294 | return value;
|
|---|
| 295 | }
|
|---|
| 296 | if (typeof this.original().buffer === "function") {
|
|---|
| 297 | return (this._cachedBuffer = this.original().buffer());
|
|---|
| 298 | }
|
|---|
| 299 | const bufferOrString = this.source();
|
|---|
| 300 | if (Buffer.isBuffer(bufferOrString)) {
|
|---|
| 301 | return (this._cachedBuffer = bufferOrString);
|
|---|
| 302 | }
|
|---|
| 303 | const value = Buffer.from(bufferOrString, "utf8");
|
|---|
| 304 | if (isDualStringBufferCachingEnabled()) {
|
|---|
| 305 | this._cachedBuffer = value;
|
|---|
| 306 | }
|
|---|
| 307 | return value;
|
|---|
| 308 | }
|
|---|
| 309 |
|
|---|
| 310 | /**
|
|---|
| 311 | * @returns {Buffer[]} buffers
|
|---|
| 312 | */
|
|---|
| 313 | buffers() {
|
|---|
| 314 | if (this._cachedBuffers !== undefined) return this._cachedBuffers;
|
|---|
| 315 | if (this._cachedBuffer !== undefined) {
|
|---|
| 316 | return (this._cachedBuffers = [this._cachedBuffer]);
|
|---|
| 317 | }
|
|---|
| 318 | const original = this.original();
|
|---|
| 319 | if (typeof original.buffers === "function") {
|
|---|
| 320 | return (this._cachedBuffers = original.buffers());
|
|---|
| 321 | }
|
|---|
| 322 | return (this._cachedBuffers = [this.buffer()]);
|
|---|
| 323 | }
|
|---|
| 324 |
|
|---|
| 325 | /**
|
|---|
| 326 | * @returns {number} size
|
|---|
| 327 | */
|
|---|
| 328 | size() {
|
|---|
| 329 | if (this._cachedSize !== undefined) return this._cachedSize;
|
|---|
| 330 | if (this._cachedBuffer !== undefined) {
|
|---|
| 331 | return (this._cachedSize = this._cachedBuffer.length);
|
|---|
| 332 | }
|
|---|
| 333 | const source = this._getCachedSource();
|
|---|
| 334 | if (source !== undefined) {
|
|---|
| 335 | return (this._cachedSize = Buffer.byteLength(source));
|
|---|
| 336 | }
|
|---|
| 337 | return (this._cachedSize = this.original().size());
|
|---|
| 338 | }
|
|---|
| 339 |
|
|---|
| 340 | /**
|
|---|
| 341 | * @param {MapOptions=} options map options
|
|---|
| 342 | * @returns {SourceAndMap} source and map
|
|---|
| 343 | */
|
|---|
| 344 | sourceAndMap(options) {
|
|---|
| 345 | const key = getCacheKey(options);
|
|---|
| 346 | const cacheEntry = this._cachedMaps.get(key);
|
|---|
| 347 | // Look for a cached map
|
|---|
| 348 | if (cacheEntry !== undefined) {
|
|---|
| 349 | // We have a cached map in some representation
|
|---|
| 350 | const map = this._getMapFromCacheEntry(cacheEntry);
|
|---|
| 351 |
|
|---|
| 352 | // Either get the cached source or compute it
|
|---|
| 353 | return { source: this.source(), map };
|
|---|
| 354 | }
|
|---|
| 355 | // Look for a cached source
|
|---|
| 356 | let source = this._getCachedSource();
|
|---|
| 357 | // Compute the map
|
|---|
| 358 | let map;
|
|---|
| 359 | if (source !== undefined) {
|
|---|
| 360 | map = this.original().map(options);
|
|---|
| 361 | } else {
|
|---|
| 362 | // Compute the source and map together.
|
|---|
| 363 | const sourceAndMap = this.original().sourceAndMap(options);
|
|---|
| 364 | source = /** @type {string} */ (sourceAndMap.source);
|
|---|
| 365 | map = sourceAndMap.map;
|
|---|
| 366 | this._cachedSource = source;
|
|---|
| 367 | }
|
|---|
| 368 | this._cachedMaps.set(key, {
|
|---|
| 369 | map,
|
|---|
| 370 | bufferedMap: undefined,
|
|---|
| 371 | });
|
|---|
| 372 | return { source, map };
|
|---|
| 373 | }
|
|---|
| 374 |
|
|---|
| 375 | /**
|
|---|
| 376 | * @param {Options} options options
|
|---|
| 377 | * @param {OnChunk} onChunk called for each chunk of code
|
|---|
| 378 | * @param {OnSource} onSource called for each source
|
|---|
| 379 | * @param {OnName} onName called for each name
|
|---|
| 380 | * @returns {GeneratedSourceInfo} generated source info
|
|---|
| 381 | */
|
|---|
| 382 | streamChunks(options, onChunk, onSource, onName) {
|
|---|
| 383 | const key = getCacheKey(options);
|
|---|
| 384 | if (
|
|---|
| 385 | this._cachedMaps.has(key) &&
|
|---|
| 386 | (this._cachedBuffer !== undefined || this._cachedSource !== undefined)
|
|---|
| 387 | ) {
|
|---|
| 388 | const { source, map } = this.sourceAndMap(options);
|
|---|
| 389 | if (map) {
|
|---|
| 390 | return streamChunksOfSourceMap(
|
|---|
| 391 | /** @type {string} */
|
|---|
| 392 | (source),
|
|---|
| 393 | map,
|
|---|
| 394 | onChunk,
|
|---|
| 395 | onSource,
|
|---|
| 396 | onName,
|
|---|
| 397 | Boolean(options && options.finalSource),
|
|---|
| 398 | true,
|
|---|
| 399 | );
|
|---|
| 400 | }
|
|---|
| 401 | return streamChunksOfRawSource(
|
|---|
| 402 | /** @type {string} */
|
|---|
| 403 | (source),
|
|---|
| 404 | onChunk,
|
|---|
| 405 | onSource,
|
|---|
| 406 | onName,
|
|---|
| 407 | Boolean(options && options.finalSource),
|
|---|
| 408 | );
|
|---|
| 409 | }
|
|---|
| 410 | const sourceAndMap = streamAndGetSourceAndMap(
|
|---|
| 411 | this.original(),
|
|---|
| 412 | options,
|
|---|
| 413 | onChunk,
|
|---|
| 414 | onSource,
|
|---|
| 415 | onName,
|
|---|
| 416 | );
|
|---|
| 417 | this._cachedSource = sourceAndMap.source;
|
|---|
| 418 | this._cachedMaps.set(key, {
|
|---|
| 419 | map: /** @type {RawSourceMap} */ (sourceAndMap.map),
|
|---|
| 420 | bufferedMap: undefined,
|
|---|
| 421 | });
|
|---|
| 422 | return sourceAndMap.result;
|
|---|
| 423 | }
|
|---|
| 424 |
|
|---|
| 425 | /**
|
|---|
| 426 | * @param {MapOptions=} options map options
|
|---|
| 427 | * @returns {RawSourceMap | null} map
|
|---|
| 428 | */
|
|---|
| 429 | map(options) {
|
|---|
| 430 | const key = getCacheKey(options);
|
|---|
| 431 | const cacheEntry = this._cachedMaps.get(key);
|
|---|
| 432 | if (cacheEntry !== undefined) {
|
|---|
| 433 | return this._getMapFromCacheEntry(cacheEntry);
|
|---|
| 434 | }
|
|---|
| 435 | const map = this.original().map(options);
|
|---|
| 436 | this._cachedMaps.set(key, {
|
|---|
| 437 | map,
|
|---|
| 438 | bufferedMap: undefined,
|
|---|
| 439 | });
|
|---|
| 440 | return map;
|
|---|
| 441 | }
|
|---|
| 442 |
|
|---|
| 443 | /**
|
|---|
| 444 | * @param {HashLike} hash hash
|
|---|
| 445 | * @returns {void}
|
|---|
| 446 | */
|
|---|
| 447 | updateHash(hash) {
|
|---|
| 448 | if (this._cachedHashUpdate !== undefined) {
|
|---|
| 449 | for (const item of this._cachedHashUpdate) hash.update(item);
|
|---|
| 450 | return;
|
|---|
| 451 | }
|
|---|
| 452 | /** @type {(string | Buffer)[]} */
|
|---|
| 453 | const update = [];
|
|---|
| 454 | /** @type {string | undefined} */
|
|---|
| 455 | let currentString;
|
|---|
| 456 | const tracker = {
|
|---|
| 457 | /**
|
|---|
| 458 | * @param {string | Buffer} item item
|
|---|
| 459 | * @returns {void}
|
|---|
| 460 | */
|
|---|
| 461 | update: (item) => {
|
|---|
| 462 | if (typeof item === "string" && item.length < 10240) {
|
|---|
| 463 | if (currentString === undefined) {
|
|---|
| 464 | currentString = item;
|
|---|
| 465 | } else {
|
|---|
| 466 | currentString += item;
|
|---|
| 467 | if (currentString.length > 102400) {
|
|---|
| 468 | update.push(Buffer.from(currentString));
|
|---|
| 469 | currentString = undefined;
|
|---|
| 470 | }
|
|---|
| 471 | }
|
|---|
| 472 | } else {
|
|---|
| 473 | if (currentString !== undefined) {
|
|---|
| 474 | update.push(Buffer.from(currentString));
|
|---|
| 475 | currentString = undefined;
|
|---|
| 476 | }
|
|---|
| 477 | update.push(item);
|
|---|
| 478 | }
|
|---|
| 479 | },
|
|---|
| 480 | };
|
|---|
| 481 | this.original().updateHash(/** @type {HashLike} */ (tracker));
|
|---|
| 482 | if (currentString !== undefined) {
|
|---|
| 483 | update.push(Buffer.from(currentString));
|
|---|
| 484 | }
|
|---|
| 485 | for (const item of update) hash.update(item);
|
|---|
| 486 | this._cachedHashUpdate = update;
|
|---|
| 487 | }
|
|---|
| 488 | }
|
|---|
| 489 |
|
|---|
| 490 | module.exports = CachedSource;
|
|---|