xz-compat 1.2.0 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -144,8 +144,9 @@ var Lzma2Decoder = /*#__PURE__*/ function() {
|
|
|
144
144
|
var outputBuffer = null;
|
|
145
145
|
var outputPos = 0;
|
|
146
146
|
var outputChunks = [];
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
// Use canAllocateBufferSize to dynamically check if pre-allocation is safe
|
|
148
|
+
var canPreAllocate = unpackSize && unpackSize > 0 && (0, _extractbaseiterator.canAllocateBufferSize)(unpackSize);
|
|
149
|
+
if (canPreAllocate) {
|
|
149
150
|
outputBuffer = (0, _extractbaseiterator.allocBufferUnsafe)(unpackSize);
|
|
150
151
|
}
|
|
151
152
|
var offset = 0;
|
|
@@ -214,17 +215,26 @@ var Lzma2Decoder = /*#__PURE__*/ function() {
|
|
|
214
215
|
}();
|
|
215
216
|
function decodeLzma2(input, properties, unpackSize, outputSink) {
|
|
216
217
|
// For very large outputs on old Node versions, we cannot return a single Buffer
|
|
217
|
-
//
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
218
|
+
// Use streaming mode internally to handle large outputs on modern Node
|
|
219
|
+
if (!outputSink && unpackSize && unpackSize > 0 && !(0, _extractbaseiterator.canAllocateBufferSize)(unpackSize)) {
|
|
220
|
+
// Large output - use streaming mode with internal chunking
|
|
221
|
+
var chunks = [];
|
|
222
|
+
var sink = {
|
|
223
|
+
write: function write(buffer) {
|
|
224
|
+
chunks.push(buffer);
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
var decoder = new Lzma2Decoder(properties, sink);
|
|
228
|
+
decoder.decodeWithSink(input);
|
|
229
|
+
// Combine chunks at the end - use bufferConcat for safe combination
|
|
230
|
+
return (0, _extractbaseiterator.bufferConcat)(chunks);
|
|
221
231
|
}
|
|
222
|
-
var
|
|
232
|
+
var decoder1 = new Lzma2Decoder(properties, outputSink);
|
|
223
233
|
if (outputSink) {
|
|
224
234
|
// Zero-copy mode: write to sink during decode
|
|
225
|
-
return
|
|
235
|
+
return decoder1.decodeWithSink(input);
|
|
226
236
|
}
|
|
227
237
|
// Buffering mode: returns Buffer (zero-copy)
|
|
228
|
-
return
|
|
238
|
+
return decoder1.decode(input, unpackSize);
|
|
229
239
|
}
|
|
230
240
|
/* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/xz-compat/src/lzma/sync/Lzma2Decoder.ts"],"sourcesContent":["/**\n * Synchronous LZMA2 Decoder\n *\n * LZMA2 is a container format that wraps LZMA chunks with framing.\n * Decodes LZMA2 data from a buffer or BufferList.\n */\n\nimport { allocBufferUnsafe, type BufferLike, bufferConcat, bufferFrom } from 'extract-base-iterator';\nimport { parseLzma2ChunkHeader } from '../lib/Lzma2ChunkParser.ts';\nimport { type OutputSink, parseLzma2DictionarySize } from '../types.ts';\nimport { LzmaDecoder } from './LzmaDecoder.ts';\n\n/**\n * Read multiple bytes from BufferLike into a Buffer\n */\nfunction readBytes(input: BufferLike, offset: number, length: number): Buffer {\n if (Buffer.isBuffer(input)) {\n return input.slice(offset, offset + length);\n }\n // For BufferList, create a new Buffer with the data\n const buf = bufferFrom(new Array(length));\n for (let i = 0; i < length; i++) {\n buf[i] = input.readByte(offset + i);\n }\n return buf;\n}\n\n/**\n * Synchronous LZMA2 decoder\n */\nexport class Lzma2Decoder {\n private lzmaDecoder: LzmaDecoder;\n private dictionarySize: number;\n\n constructor(properties: Buffer | Uint8Array, outputSink?: OutputSink) {\n if (!properties || properties.length < 1) {\n throw new Error('LZMA2 requires properties byte');\n }\n\n this.dictionarySize = parseLzma2DictionarySize(properties[0]);\n this.lzmaDecoder = new LzmaDecoder(outputSink);\n this.lzmaDecoder.setDictionarySize(this.dictionarySize);\n }\n\n /**\n * Reset the dictionary (for stream boundaries)\n */\n resetDictionary(): void {\n this.lzmaDecoder.resetDictionary();\n }\n\n /**\n * Reset all probability models (for stream boundaries)\n */\n resetProbabilities(): void {\n this.lzmaDecoder.resetProbabilities();\n }\n\n /**\n * Set LZMA properties\n */\n setLcLpPb(lc: number, lp: number, pb: number): boolean {\n return this.lzmaDecoder.setLcLpPb(lc, lp, pb);\n }\n\n /**\n * Feed uncompressed data to the dictionary (for subsequent LZMA chunks)\n */\n feedUncompressed(data: Buffer): void {\n this.lzmaDecoder.feedUncompressed(data);\n }\n\n /**\n * Decode raw LZMA data (used internally for LZMA2 chunks)\n * @param input - LZMA compressed data\n * @param offset - Input offset\n * @param outSize - Expected output size\n * @param solid - Use solid mode\n * @returns Decompressed data\n */\n decodeLzmaData(input: Buffer, offset: number, outSize: number, solid = false): Buffer {\n return this.lzmaDecoder.decode(input, offset, outSize, solid);\n }\n\n /**\n * Decode LZMA2 data with streaming output\n * @param input - LZMA2 compressed data (Buffer or BufferList)\n * @returns Total number of bytes written to sink\n */\n decodeWithSink(input: BufferLike): number {\n let totalBytes = 0;\n let offset = 0;\n\n while (true) {\n const result = parseLzma2ChunkHeader(input, offset);\n\n if (!result.success) {\n throw new Error('Truncated LZMA2 chunk header');\n }\n\n const chunk = result.chunk;\n\n if (chunk.type === 'end') {\n break;\n }\n\n // Handle dictionary reset\n if (chunk.dictReset) {\n this.lzmaDecoder.resetDictionary();\n }\n\n // Handle state reset\n if (chunk.stateReset) {\n this.lzmaDecoder.resetProbabilities();\n }\n\n // Apply new properties if present\n if (chunk.newProps) {\n const { lc, lp, pb } = chunk.newProps;\n this.lzmaDecoder.setLcLpPb(lc, lp, pb);\n }\n\n const dataOffset = offset + chunk.headerSize;\n const useSolid = !chunk.stateReset || (chunk.stateReset && !chunk.dictReset);\n\n if (chunk.type === 'uncompressed') {\n // Read uncompressed data directly\n const uncompData = readBytes(input, dataOffset, chunk.uncompSize);\n\n // Feed uncompressed data to dictionary so subsequent LZMA chunks can reference it\n this.lzmaDecoder.feedUncompressed(uncompData);\n\n totalBytes += uncompData.length;\n offset = dataOffset + chunk.uncompSize;\n } else {\n // LZMA compressed chunk - decode directly from BufferLike\n totalBytes += this.lzmaDecoder.decodeWithSink(input, dataOffset, chunk.uncompSize, useSolid);\n\n offset = dataOffset + chunk.compSize;\n }\n }\n\n // Flush any remaining data in the OutWindow\n this.lzmaDecoder.flushOutWindow();\n\n return totalBytes;\n }\n\n /**\n * Decode LZMA2 data\n * @param input - LZMA2 compressed data (Buffer or BufferList)\n * @param unpackSize - Expected output size (optional, for pre-allocation)\n * @returns Decompressed data\n */\n decode(input: BufferLike, unpackSize?: number): Buffer {\n // Pre-allocate output buffer if size is known and safe for this Node version\n let outputBuffer: Buffer | null = null;\n let outputPos = 0;\n const outputChunks: Buffer[] = [];\n\n const MAX_SAFE_SIZE = 256 * 1024 * 1024; // 256MB\n if (unpackSize && unpackSize > 0 && unpackSize <= MAX_SAFE_SIZE) {\n outputBuffer = allocBufferUnsafe(unpackSize);\n }\n\n let offset = 0;\n\n // Parse and decode LZMA2 chunks one at a time\n while (true) {\n const result = parseLzma2ChunkHeader(input, offset);\n\n if (!result.success) {\n throw new Error('Truncated LZMA2 chunk header');\n }\n\n const chunk = result.chunk;\n\n if (chunk.type === 'end') {\n break;\n }\n\n const dataOffset = offset + chunk.headerSize;\n\n // Handle dictionary reset\n if (chunk.dictReset) {\n this.lzmaDecoder.resetDictionary();\n }\n\n // Handle state reset\n if (chunk.stateReset) {\n this.lzmaDecoder.resetProbabilities();\n }\n\n // Apply new properties if present\n if (chunk.newProps) {\n const { lc, lp, pb } = chunk.newProps;\n this.lzmaDecoder.setLcLpPb(lc, lp, pb);\n }\n\n // Determine solid mode\n const useSolid = !chunk.stateReset || (chunk.stateReset && !chunk.dictReset);\n\n if (chunk.type === 'uncompressed') {\n // Read uncompressed data\n const uncompData = readBytes(input, dataOffset, chunk.uncompSize);\n\n // Copy to output\n if (outputBuffer) {\n uncompData.copy(outputBuffer, outputPos);\n outputPos += uncompData.length;\n } else {\n outputChunks.push(uncompData);\n }\n\n // Feed uncompressed data to dictionary so subsequent LZMA chunks can reference it\n this.lzmaDecoder.feedUncompressed(uncompData);\n\n offset = dataOffset + chunk.uncompSize;\n } else {\n // LZMA compressed chunk - decode directly from BufferLike\n if (outputBuffer) {\n // Zero-copy: decode directly into caller's buffer\n const bytesWritten = this.lzmaDecoder.decodeToBuffer(input, dataOffset, chunk.uncompSize, outputBuffer, outputPos, useSolid);\n outputPos += bytesWritten;\n } else {\n // No pre-allocation: decode to new buffer and collect chunks\n const chunkData = readBytes(input, dataOffset, chunk.compSize);\n const decoded = this.lzmaDecoder.decode(chunkData, 0, chunk.uncompSize, useSolid);\n outputChunks.push(decoded);\n }\n\n offset = dataOffset + chunk.compSize;\n }\n }\n\n // Return pre-allocated buffer or concatenated chunks\n if (outputBuffer) {\n return outputPos < outputBuffer.length ? outputBuffer.slice(0, outputPos) : outputBuffer;\n }\n // Use bufferConcat which handles large buffers safely via pairwise combination\n return bufferConcat(outputChunks);\n }\n}\n\n/**\n * Decode LZMA2 data synchronously\n * @param input - LZMA2 compressed data (Buffer or BufferList)\n * @param properties - 1-byte properties (dictionary size)\n * @param unpackSize - Expected output size (optional, autodetects if not provided)\n * @param outputSink - Optional output sink with write callback for streaming (returns bytes written)\n * @returns Decompressed data (or bytes written if outputSink provided)\n */\nexport function decodeLzma2(input: BufferLike, properties: Buffer | Uint8Array, unpackSize?: number, outputSink?: { write(buffer: Buffer): void }): Buffer | number {\n // For very large outputs on old Node versions, we cannot return a single Buffer\n // Check if output would exceed safe buffer limits\n const MAX_SAFE_SIZE = 256 * 1024 * 1024; // 256MB\n if (!outputSink && unpackSize && unpackSize > 0 && unpackSize > MAX_SAFE_SIZE) {\n throw new Error(`Cannot combine buffers: total size (${unpackSize} bytes) exceeds Node.js buffer limit. LZMA2 archives with folders larger than ${Math.floor(MAX_SAFE_SIZE / (1024 * 1024))}MB cannot be fully buffered on this Node version. Use streaming mode with an output sink instead.`);\n }\n\n const decoder = new Lzma2Decoder(properties, outputSink as OutputSink);\n if (outputSink) {\n // Zero-copy mode: write to sink during decode\n return decoder.decodeWithSink(input);\n }\n // Buffering mode: returns Buffer (zero-copy)\n return decoder.decode(input, unpackSize);\n}\n"],"names":["Lzma2Decoder","decodeLzma2","readBytes","input","offset","length","Buffer","isBuffer","slice","buf","bufferFrom","Array","i","readByte","properties","outputSink","Error","dictionarySize","parseLzma2DictionarySize","lzmaDecoder","LzmaDecoder","setDictionarySize","resetDictionary","resetProbabilities","setLcLpPb","lc","lp","pb","feedUncompressed","data","decodeLzmaData","outSize","solid","decode","decodeWithSink","totalBytes","result","parseLzma2ChunkHeader","success","chunk","type","dictReset","stateReset","newProps","dataOffset","headerSize","useSolid","uncompData","uncompSize","compSize","flushOutWindow","unpackSize","outputBuffer","outputPos","outputChunks","MAX_SAFE_SIZE","allocBufferUnsafe","copy","push","bytesWritten","decodeToBuffer","chunkData","decoded","bufferConcat","Math","floor","decoder"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/xz-compat/src/lzma/sync/Lzma2Decoder.ts"],"sourcesContent":["/**\n * Synchronous LZMA2 Decoder\n *\n * LZMA2 is a container format that wraps LZMA chunks with framing.\n * Decodes LZMA2 data from a buffer or BufferList.\n */\n\nimport { allocBufferUnsafe, type BufferLike, bufferConcat, bufferFrom, canAllocateBufferSize } from 'extract-base-iterator';\nimport { parseLzma2ChunkHeader } from '../lib/Lzma2ChunkParser.ts';\nimport { type OutputSink, parseLzma2DictionarySize } from '../types.ts';\nimport { LzmaDecoder } from './LzmaDecoder.ts';\n\n/**\n * Read multiple bytes from BufferLike into a Buffer\n */\nfunction readBytes(input: BufferLike, offset: number, length: number): Buffer {\n if (Buffer.isBuffer(input)) {\n return input.slice(offset, offset + length);\n }\n // For BufferList, create a new Buffer with the data\n const buf = bufferFrom(new Array(length));\n for (let i = 0; i < length; i++) {\n buf[i] = input.readByte(offset + i);\n }\n return buf;\n}\n\n/**\n * Synchronous LZMA2 decoder\n */\nexport class Lzma2Decoder {\n private lzmaDecoder: LzmaDecoder;\n private dictionarySize: number;\n\n constructor(properties: Buffer | Uint8Array, outputSink?: OutputSink) {\n if (!properties || properties.length < 1) {\n throw new Error('LZMA2 requires properties byte');\n }\n\n this.dictionarySize = parseLzma2DictionarySize(properties[0]);\n this.lzmaDecoder = new LzmaDecoder(outputSink);\n this.lzmaDecoder.setDictionarySize(this.dictionarySize);\n }\n\n /**\n * Reset the dictionary (for stream boundaries)\n */\n resetDictionary(): void {\n this.lzmaDecoder.resetDictionary();\n }\n\n /**\n * Reset all probability models (for stream boundaries)\n */\n resetProbabilities(): void {\n this.lzmaDecoder.resetProbabilities();\n }\n\n /**\n * Set LZMA properties\n */\n setLcLpPb(lc: number, lp: number, pb: number): boolean {\n return this.lzmaDecoder.setLcLpPb(lc, lp, pb);\n }\n\n /**\n * Feed uncompressed data to the dictionary (for subsequent LZMA chunks)\n */\n feedUncompressed(data: Buffer): void {\n this.lzmaDecoder.feedUncompressed(data);\n }\n\n /**\n * Decode raw LZMA data (used internally for LZMA2 chunks)\n * @param input - LZMA compressed data\n * @param offset - Input offset\n * @param outSize - Expected output size\n * @param solid - Use solid mode\n * @returns Decompressed data\n */\n decodeLzmaData(input: Buffer, offset: number, outSize: number, solid = false): Buffer {\n return this.lzmaDecoder.decode(input, offset, outSize, solid);\n }\n\n /**\n * Decode LZMA2 data with streaming output\n * @param input - LZMA2 compressed data (Buffer or BufferList)\n * @returns Total number of bytes written to sink\n */\n decodeWithSink(input: BufferLike): number {\n let totalBytes = 0;\n let offset = 0;\n\n while (true) {\n const result = parseLzma2ChunkHeader(input, offset);\n\n if (!result.success) {\n throw new Error('Truncated LZMA2 chunk header');\n }\n\n const chunk = result.chunk;\n\n if (chunk.type === 'end') {\n break;\n }\n\n // Handle dictionary reset\n if (chunk.dictReset) {\n this.lzmaDecoder.resetDictionary();\n }\n\n // Handle state reset\n if (chunk.stateReset) {\n this.lzmaDecoder.resetProbabilities();\n }\n\n // Apply new properties if present\n if (chunk.newProps) {\n const { lc, lp, pb } = chunk.newProps;\n this.lzmaDecoder.setLcLpPb(lc, lp, pb);\n }\n\n const dataOffset = offset + chunk.headerSize;\n const useSolid = !chunk.stateReset || (chunk.stateReset && !chunk.dictReset);\n\n if (chunk.type === 'uncompressed') {\n // Read uncompressed data directly\n const uncompData = readBytes(input, dataOffset, chunk.uncompSize);\n\n // Feed uncompressed data to dictionary so subsequent LZMA chunks can reference it\n this.lzmaDecoder.feedUncompressed(uncompData);\n\n totalBytes += uncompData.length;\n offset = dataOffset + chunk.uncompSize;\n } else {\n // LZMA compressed chunk - decode directly from BufferLike\n totalBytes += this.lzmaDecoder.decodeWithSink(input, dataOffset, chunk.uncompSize, useSolid);\n\n offset = dataOffset + chunk.compSize;\n }\n }\n\n // Flush any remaining data in the OutWindow\n this.lzmaDecoder.flushOutWindow();\n\n return totalBytes;\n }\n\n /**\n * Decode LZMA2 data\n * @param input - LZMA2 compressed data (Buffer or BufferList)\n * @param unpackSize - Expected output size (optional, for pre-allocation)\n * @returns Decompressed data\n */\n decode(input: BufferLike, unpackSize?: number): Buffer {\n // Pre-allocate output buffer if size is known and safe for this Node version\n let outputBuffer: Buffer | null = null;\n let outputPos = 0;\n const outputChunks: Buffer[] = [];\n\n // Use canAllocateBufferSize to dynamically check if pre-allocation is safe\n const canPreAllocate = unpackSize && unpackSize > 0 && canAllocateBufferSize(unpackSize);\n if (canPreAllocate) {\n outputBuffer = allocBufferUnsafe(unpackSize);\n }\n\n let offset = 0;\n\n // Parse and decode LZMA2 chunks one at a time\n while (true) {\n const result = parseLzma2ChunkHeader(input, offset);\n\n if (!result.success) {\n throw new Error('Truncated LZMA2 chunk header');\n }\n\n const chunk = result.chunk;\n\n if (chunk.type === 'end') {\n break;\n }\n\n const dataOffset = offset + chunk.headerSize;\n\n // Handle dictionary reset\n if (chunk.dictReset) {\n this.lzmaDecoder.resetDictionary();\n }\n\n // Handle state reset\n if (chunk.stateReset) {\n this.lzmaDecoder.resetProbabilities();\n }\n\n // Apply new properties if present\n if (chunk.newProps) {\n const { lc, lp, pb } = chunk.newProps;\n this.lzmaDecoder.setLcLpPb(lc, lp, pb);\n }\n\n // Determine solid mode\n const useSolid = !chunk.stateReset || (chunk.stateReset && !chunk.dictReset);\n\n if (chunk.type === 'uncompressed') {\n // Read uncompressed data\n const uncompData = readBytes(input, dataOffset, chunk.uncompSize);\n\n // Copy to output\n if (outputBuffer) {\n uncompData.copy(outputBuffer, outputPos);\n outputPos += uncompData.length;\n } else {\n outputChunks.push(uncompData);\n }\n\n // Feed uncompressed data to dictionary so subsequent LZMA chunks can reference it\n this.lzmaDecoder.feedUncompressed(uncompData);\n\n offset = dataOffset + chunk.uncompSize;\n } else {\n // LZMA compressed chunk - decode directly from BufferLike\n if (outputBuffer) {\n // Zero-copy: decode directly into caller's buffer\n const bytesWritten = this.lzmaDecoder.decodeToBuffer(input, dataOffset, chunk.uncompSize, outputBuffer, outputPos, useSolid);\n outputPos += bytesWritten;\n } else {\n // No pre-allocation: decode to new buffer and collect chunks\n const chunkData = readBytes(input, dataOffset, chunk.compSize);\n const decoded = this.lzmaDecoder.decode(chunkData, 0, chunk.uncompSize, useSolid);\n outputChunks.push(decoded);\n }\n\n offset = dataOffset + chunk.compSize;\n }\n }\n\n // Return pre-allocated buffer or concatenated chunks\n if (outputBuffer) {\n return outputPos < outputBuffer.length ? outputBuffer.slice(0, outputPos) : outputBuffer;\n }\n // Use bufferConcat which handles large buffers safely via pairwise combination\n return bufferConcat(outputChunks);\n }\n}\n\n/**\n * Decode LZMA2 data synchronously\n * @param input - LZMA2 compressed data (Buffer or BufferList)\n * @param properties - 1-byte properties (dictionary size)\n * @param unpackSize - Expected output size (optional, autodetects if not provided)\n * @param outputSink - Optional output sink with write callback for streaming (returns bytes written)\n * @returns Decompressed data (or bytes written if outputSink provided)\n */\nexport function decodeLzma2(input: BufferLike, properties: Buffer | Uint8Array, unpackSize?: number, outputSink?: { write(buffer: Buffer): void }): Buffer | number {\n // For very large outputs on old Node versions, we cannot return a single Buffer\n // Use streaming mode internally to handle large outputs on modern Node\n if (!outputSink && unpackSize && unpackSize > 0 && !canAllocateBufferSize(unpackSize)) {\n // Large output - use streaming mode with internal chunking\n const chunks: Buffer[] = [];\n const sink: OutputSink = {\n write(buffer: Buffer): void {\n chunks.push(buffer);\n },\n };\n\n const decoder = new Lzma2Decoder(properties, sink);\n decoder.decodeWithSink(input);\n\n // Combine chunks at the end - use bufferConcat for safe combination\n return bufferConcat(chunks);\n }\n\n const decoder = new Lzma2Decoder(properties, outputSink as OutputSink);\n if (outputSink) {\n // Zero-copy mode: write to sink during decode\n return decoder.decodeWithSink(input);\n }\n // Buffering mode: returns Buffer (zero-copy)\n return decoder.decode(input, unpackSize);\n}\n"],"names":["Lzma2Decoder","decodeLzma2","readBytes","input","offset","length","Buffer","isBuffer","slice","buf","bufferFrom","Array","i","readByte","properties","outputSink","Error","dictionarySize","parseLzma2DictionarySize","lzmaDecoder","LzmaDecoder","setDictionarySize","resetDictionary","resetProbabilities","setLcLpPb","lc","lp","pb","feedUncompressed","data","decodeLzmaData","outSize","solid","decode","decodeWithSink","totalBytes","result","parseLzma2ChunkHeader","success","chunk","type","dictReset","stateReset","newProps","dataOffset","headerSize","useSolid","uncompData","uncompSize","compSize","flushOutWindow","unpackSize","outputBuffer","outputPos","outputChunks","canPreAllocate","canAllocateBufferSize","allocBufferUnsafe","copy","push","bytesWritten","decodeToBuffer","chunkData","decoded","bufferConcat","chunks","sink","write","buffer","decoder"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* LZMA2 is a container format that wraps LZMA chunks with framing.
|
|
5
5
|
* Decodes LZMA2 data from a buffer or BufferList.
|
|
6
|
-
*/ import { allocBufferUnsafe, bufferConcat, bufferFrom } from 'extract-base-iterator';
|
|
6
|
+
*/ import { allocBufferUnsafe, bufferConcat, bufferFrom, canAllocateBufferSize } from 'extract-base-iterator';
|
|
7
7
|
import { parseLzma2ChunkHeader } from '../lib/Lzma2ChunkParser.js';
|
|
8
8
|
import { parseLzma2DictionarySize } from '../types.js';
|
|
9
9
|
import { LzmaDecoder } from './LzmaDecoder.js';
|
|
@@ -111,8 +111,9 @@ import { LzmaDecoder } from './LzmaDecoder.js';
|
|
|
111
111
|
let outputBuffer = null;
|
|
112
112
|
let outputPos = 0;
|
|
113
113
|
const outputChunks = [];
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
// Use canAllocateBufferSize to dynamically check if pre-allocation is safe
|
|
115
|
+
const canPreAllocate = unpackSize && unpackSize > 0 && canAllocateBufferSize(unpackSize);
|
|
116
|
+
if (canPreAllocate) {
|
|
116
117
|
outputBuffer = allocBufferUnsafe(unpackSize);
|
|
117
118
|
}
|
|
118
119
|
let offset = 0;
|
|
@@ -195,10 +196,19 @@ import { LzmaDecoder } from './LzmaDecoder.js';
|
|
|
195
196
|
* @returns Decompressed data (or bytes written if outputSink provided)
|
|
196
197
|
*/ export function decodeLzma2(input, properties, unpackSize, outputSink) {
|
|
197
198
|
// For very large outputs on old Node versions, we cannot return a single Buffer
|
|
198
|
-
//
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
199
|
+
// Use streaming mode internally to handle large outputs on modern Node
|
|
200
|
+
if (!outputSink && unpackSize && unpackSize > 0 && !canAllocateBufferSize(unpackSize)) {
|
|
201
|
+
// Large output - use streaming mode with internal chunking
|
|
202
|
+
const chunks = [];
|
|
203
|
+
const sink = {
|
|
204
|
+
write (buffer) {
|
|
205
|
+
chunks.push(buffer);
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
const decoder = new Lzma2Decoder(properties, sink);
|
|
209
|
+
decoder.decodeWithSink(input);
|
|
210
|
+
// Combine chunks at the end - use bufferConcat for safe combination
|
|
211
|
+
return bufferConcat(chunks);
|
|
202
212
|
}
|
|
203
213
|
const decoder = new Lzma2Decoder(properties, outputSink);
|
|
204
214
|
if (outputSink) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/xz-compat/src/lzma/sync/Lzma2Decoder.ts"],"sourcesContent":["/**\n * Synchronous LZMA2 Decoder\n *\n * LZMA2 is a container format that wraps LZMA chunks with framing.\n * Decodes LZMA2 data from a buffer or BufferList.\n */\n\nimport { allocBufferUnsafe, type BufferLike, bufferConcat, bufferFrom } from 'extract-base-iterator';\nimport { parseLzma2ChunkHeader } from '../lib/Lzma2ChunkParser.ts';\nimport { type OutputSink, parseLzma2DictionarySize } from '../types.ts';\nimport { LzmaDecoder } from './LzmaDecoder.ts';\n\n/**\n * Read multiple bytes from BufferLike into a Buffer\n */\nfunction readBytes(input: BufferLike, offset: number, length: number): Buffer {\n if (Buffer.isBuffer(input)) {\n return input.slice(offset, offset + length);\n }\n // For BufferList, create a new Buffer with the data\n const buf = bufferFrom(new Array(length));\n for (let i = 0; i < length; i++) {\n buf[i] = input.readByte(offset + i);\n }\n return buf;\n}\n\n/**\n * Synchronous LZMA2 decoder\n */\nexport class Lzma2Decoder {\n private lzmaDecoder: LzmaDecoder;\n private dictionarySize: number;\n\n constructor(properties: Buffer | Uint8Array, outputSink?: OutputSink) {\n if (!properties || properties.length < 1) {\n throw new Error('LZMA2 requires properties byte');\n }\n\n this.dictionarySize = parseLzma2DictionarySize(properties[0]);\n this.lzmaDecoder = new LzmaDecoder(outputSink);\n this.lzmaDecoder.setDictionarySize(this.dictionarySize);\n }\n\n /**\n * Reset the dictionary (for stream boundaries)\n */\n resetDictionary(): void {\n this.lzmaDecoder.resetDictionary();\n }\n\n /**\n * Reset all probability models (for stream boundaries)\n */\n resetProbabilities(): void {\n this.lzmaDecoder.resetProbabilities();\n }\n\n /**\n * Set LZMA properties\n */\n setLcLpPb(lc: number, lp: number, pb: number): boolean {\n return this.lzmaDecoder.setLcLpPb(lc, lp, pb);\n }\n\n /**\n * Feed uncompressed data to the dictionary (for subsequent LZMA chunks)\n */\n feedUncompressed(data: Buffer): void {\n this.lzmaDecoder.feedUncompressed(data);\n }\n\n /**\n * Decode raw LZMA data (used internally for LZMA2 chunks)\n * @param input - LZMA compressed data\n * @param offset - Input offset\n * @param outSize - Expected output size\n * @param solid - Use solid mode\n * @returns Decompressed data\n */\n decodeLzmaData(input: Buffer, offset: number, outSize: number, solid = false): Buffer {\n return this.lzmaDecoder.decode(input, offset, outSize, solid);\n }\n\n /**\n * Decode LZMA2 data with streaming output\n * @param input - LZMA2 compressed data (Buffer or BufferList)\n * @returns Total number of bytes written to sink\n */\n decodeWithSink(input: BufferLike): number {\n let totalBytes = 0;\n let offset = 0;\n\n while (true) {\n const result = parseLzma2ChunkHeader(input, offset);\n\n if (!result.success) {\n throw new Error('Truncated LZMA2 chunk header');\n }\n\n const chunk = result.chunk;\n\n if (chunk.type === 'end') {\n break;\n }\n\n // Handle dictionary reset\n if (chunk.dictReset) {\n this.lzmaDecoder.resetDictionary();\n }\n\n // Handle state reset\n if (chunk.stateReset) {\n this.lzmaDecoder.resetProbabilities();\n }\n\n // Apply new properties if present\n if (chunk.newProps) {\n const { lc, lp, pb } = chunk.newProps;\n this.lzmaDecoder.setLcLpPb(lc, lp, pb);\n }\n\n const dataOffset = offset + chunk.headerSize;\n const useSolid = !chunk.stateReset || (chunk.stateReset && !chunk.dictReset);\n\n if (chunk.type === 'uncompressed') {\n // Read uncompressed data directly\n const uncompData = readBytes(input, dataOffset, chunk.uncompSize);\n\n // Feed uncompressed data to dictionary so subsequent LZMA chunks can reference it\n this.lzmaDecoder.feedUncompressed(uncompData);\n\n totalBytes += uncompData.length;\n offset = dataOffset + chunk.uncompSize;\n } else {\n // LZMA compressed chunk - decode directly from BufferLike\n totalBytes += this.lzmaDecoder.decodeWithSink(input, dataOffset, chunk.uncompSize, useSolid);\n\n offset = dataOffset + chunk.compSize;\n }\n }\n\n // Flush any remaining data in the OutWindow\n this.lzmaDecoder.flushOutWindow();\n\n return totalBytes;\n }\n\n /**\n * Decode LZMA2 data\n * @param input - LZMA2 compressed data (Buffer or BufferList)\n * @param unpackSize - Expected output size (optional, for pre-allocation)\n * @returns Decompressed data\n */\n decode(input: BufferLike, unpackSize?: number): Buffer {\n // Pre-allocate output buffer if size is known and safe for this Node version\n let outputBuffer: Buffer | null = null;\n let outputPos = 0;\n const outputChunks: Buffer[] = [];\n\n const MAX_SAFE_SIZE = 256 * 1024 * 1024; // 256MB\n if (unpackSize && unpackSize > 0 && unpackSize <= MAX_SAFE_SIZE) {\n outputBuffer = allocBufferUnsafe(unpackSize);\n }\n\n let offset = 0;\n\n // Parse and decode LZMA2 chunks one at a time\n while (true) {\n const result = parseLzma2ChunkHeader(input, offset);\n\n if (!result.success) {\n throw new Error('Truncated LZMA2 chunk header');\n }\n\n const chunk = result.chunk;\n\n if (chunk.type === 'end') {\n break;\n }\n\n const dataOffset = offset + chunk.headerSize;\n\n // Handle dictionary reset\n if (chunk.dictReset) {\n this.lzmaDecoder.resetDictionary();\n }\n\n // Handle state reset\n if (chunk.stateReset) {\n this.lzmaDecoder.resetProbabilities();\n }\n\n // Apply new properties if present\n if (chunk.newProps) {\n const { lc, lp, pb } = chunk.newProps;\n this.lzmaDecoder.setLcLpPb(lc, lp, pb);\n }\n\n // Determine solid mode\n const useSolid = !chunk.stateReset || (chunk.stateReset && !chunk.dictReset);\n\n if (chunk.type === 'uncompressed') {\n // Read uncompressed data\n const uncompData = readBytes(input, dataOffset, chunk.uncompSize);\n\n // Copy to output\n if (outputBuffer) {\n uncompData.copy(outputBuffer, outputPos);\n outputPos += uncompData.length;\n } else {\n outputChunks.push(uncompData);\n }\n\n // Feed uncompressed data to dictionary so subsequent LZMA chunks can reference it\n this.lzmaDecoder.feedUncompressed(uncompData);\n\n offset = dataOffset + chunk.uncompSize;\n } else {\n // LZMA compressed chunk - decode directly from BufferLike\n if (outputBuffer) {\n // Zero-copy: decode directly into caller's buffer\n const bytesWritten = this.lzmaDecoder.decodeToBuffer(input, dataOffset, chunk.uncompSize, outputBuffer, outputPos, useSolid);\n outputPos += bytesWritten;\n } else {\n // No pre-allocation: decode to new buffer and collect chunks\n const chunkData = readBytes(input, dataOffset, chunk.compSize);\n const decoded = this.lzmaDecoder.decode(chunkData, 0, chunk.uncompSize, useSolid);\n outputChunks.push(decoded);\n }\n\n offset = dataOffset + chunk.compSize;\n }\n }\n\n // Return pre-allocated buffer or concatenated chunks\n if (outputBuffer) {\n return outputPos < outputBuffer.length ? outputBuffer.slice(0, outputPos) : outputBuffer;\n }\n // Use bufferConcat which handles large buffers safely via pairwise combination\n return bufferConcat(outputChunks);\n }\n}\n\n/**\n * Decode LZMA2 data synchronously\n * @param input - LZMA2 compressed data (Buffer or BufferList)\n * @param properties - 1-byte properties (dictionary size)\n * @param unpackSize - Expected output size (optional, autodetects if not provided)\n * @param outputSink - Optional output sink with write callback for streaming (returns bytes written)\n * @returns Decompressed data (or bytes written if outputSink provided)\n */\nexport function decodeLzma2(input: BufferLike, properties: Buffer | Uint8Array, unpackSize?: number, outputSink?: { write(buffer: Buffer): void }): Buffer | number {\n // For very large outputs on old Node versions, we cannot return a single Buffer\n // Check if output would exceed safe buffer limits\n const MAX_SAFE_SIZE = 256 * 1024 * 1024; // 256MB\n if (!outputSink && unpackSize && unpackSize > 0 && unpackSize > MAX_SAFE_SIZE) {\n throw new Error(`Cannot combine buffers: total size (${unpackSize} bytes) exceeds Node.js buffer limit. LZMA2 archives with folders larger than ${Math.floor(MAX_SAFE_SIZE / (1024 * 1024))}MB cannot be fully buffered on this Node version. Use streaming mode with an output sink instead.`);\n }\n\n const decoder = new Lzma2Decoder(properties, outputSink as OutputSink);\n if (outputSink) {\n // Zero-copy mode: write to sink during decode\n return decoder.decodeWithSink(input);\n }\n // Buffering mode: returns Buffer (zero-copy)\n return decoder.decode(input, unpackSize);\n}\n"],"names":["allocBufferUnsafe","bufferConcat","bufferFrom","parseLzma2ChunkHeader","parseLzma2DictionarySize","LzmaDecoder","readBytes","input","offset","length","Buffer","isBuffer","slice","buf","Array","i","readByte","Lzma2Decoder","resetDictionary","lzmaDecoder","resetProbabilities","setLcLpPb","lc","lp","pb","feedUncompressed","data","decodeLzmaData","outSize","solid","decode","decodeWithSink","totalBytes","result","success","Error","chunk","type","dictReset","stateReset","newProps","dataOffset","headerSize","useSolid","uncompData","uncompSize","compSize","flushOutWindow","unpackSize","outputBuffer","outputPos","outputChunks","MAX_SAFE_SIZE","copy","push","bytesWritten","decodeToBuffer","chunkData","decoded","properties","outputSink","dictionarySize","setDictionarySize","decodeLzma2","Math","floor","decoder"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/xz-compat/src/lzma/sync/Lzma2Decoder.ts"],"sourcesContent":["/**\n * Synchronous LZMA2 Decoder\n *\n * LZMA2 is a container format that wraps LZMA chunks with framing.\n * Decodes LZMA2 data from a buffer or BufferList.\n */\n\nimport { allocBufferUnsafe, type BufferLike, bufferConcat, bufferFrom, canAllocateBufferSize } from 'extract-base-iterator';\nimport { parseLzma2ChunkHeader } from '../lib/Lzma2ChunkParser.ts';\nimport { type OutputSink, parseLzma2DictionarySize } from '../types.ts';\nimport { LzmaDecoder } from './LzmaDecoder.ts';\n\n/**\n * Read multiple bytes from BufferLike into a Buffer\n */\nfunction readBytes(input: BufferLike, offset: number, length: number): Buffer {\n if (Buffer.isBuffer(input)) {\n return input.slice(offset, offset + length);\n }\n // For BufferList, create a new Buffer with the data\n const buf = bufferFrom(new Array(length));\n for (let i = 0; i < length; i++) {\n buf[i] = input.readByte(offset + i);\n }\n return buf;\n}\n\n/**\n * Synchronous LZMA2 decoder\n */\nexport class Lzma2Decoder {\n private lzmaDecoder: LzmaDecoder;\n private dictionarySize: number;\n\n constructor(properties: Buffer | Uint8Array, outputSink?: OutputSink) {\n if (!properties || properties.length < 1) {\n throw new Error('LZMA2 requires properties byte');\n }\n\n this.dictionarySize = parseLzma2DictionarySize(properties[0]);\n this.lzmaDecoder = new LzmaDecoder(outputSink);\n this.lzmaDecoder.setDictionarySize(this.dictionarySize);\n }\n\n /**\n * Reset the dictionary (for stream boundaries)\n */\n resetDictionary(): void {\n this.lzmaDecoder.resetDictionary();\n }\n\n /**\n * Reset all probability models (for stream boundaries)\n */\n resetProbabilities(): void {\n this.lzmaDecoder.resetProbabilities();\n }\n\n /**\n * Set LZMA properties\n */\n setLcLpPb(lc: number, lp: number, pb: number): boolean {\n return this.lzmaDecoder.setLcLpPb(lc, lp, pb);\n }\n\n /**\n * Feed uncompressed data to the dictionary (for subsequent LZMA chunks)\n */\n feedUncompressed(data: Buffer): void {\n this.lzmaDecoder.feedUncompressed(data);\n }\n\n /**\n * Decode raw LZMA data (used internally for LZMA2 chunks)\n * @param input - LZMA compressed data\n * @param offset - Input offset\n * @param outSize - Expected output size\n * @param solid - Use solid mode\n * @returns Decompressed data\n */\n decodeLzmaData(input: Buffer, offset: number, outSize: number, solid = false): Buffer {\n return this.lzmaDecoder.decode(input, offset, outSize, solid);\n }\n\n /**\n * Decode LZMA2 data with streaming output\n * @param input - LZMA2 compressed data (Buffer or BufferList)\n * @returns Total number of bytes written to sink\n */\n decodeWithSink(input: BufferLike): number {\n let totalBytes = 0;\n let offset = 0;\n\n while (true) {\n const result = parseLzma2ChunkHeader(input, offset);\n\n if (!result.success) {\n throw new Error('Truncated LZMA2 chunk header');\n }\n\n const chunk = result.chunk;\n\n if (chunk.type === 'end') {\n break;\n }\n\n // Handle dictionary reset\n if (chunk.dictReset) {\n this.lzmaDecoder.resetDictionary();\n }\n\n // Handle state reset\n if (chunk.stateReset) {\n this.lzmaDecoder.resetProbabilities();\n }\n\n // Apply new properties if present\n if (chunk.newProps) {\n const { lc, lp, pb } = chunk.newProps;\n this.lzmaDecoder.setLcLpPb(lc, lp, pb);\n }\n\n const dataOffset = offset + chunk.headerSize;\n const useSolid = !chunk.stateReset || (chunk.stateReset && !chunk.dictReset);\n\n if (chunk.type === 'uncompressed') {\n // Read uncompressed data directly\n const uncompData = readBytes(input, dataOffset, chunk.uncompSize);\n\n // Feed uncompressed data to dictionary so subsequent LZMA chunks can reference it\n this.lzmaDecoder.feedUncompressed(uncompData);\n\n totalBytes += uncompData.length;\n offset = dataOffset + chunk.uncompSize;\n } else {\n // LZMA compressed chunk - decode directly from BufferLike\n totalBytes += this.lzmaDecoder.decodeWithSink(input, dataOffset, chunk.uncompSize, useSolid);\n\n offset = dataOffset + chunk.compSize;\n }\n }\n\n // Flush any remaining data in the OutWindow\n this.lzmaDecoder.flushOutWindow();\n\n return totalBytes;\n }\n\n /**\n * Decode LZMA2 data\n * @param input - LZMA2 compressed data (Buffer or BufferList)\n * @param unpackSize - Expected output size (optional, for pre-allocation)\n * @returns Decompressed data\n */\n decode(input: BufferLike, unpackSize?: number): Buffer {\n // Pre-allocate output buffer if size is known and safe for this Node version\n let outputBuffer: Buffer | null = null;\n let outputPos = 0;\n const outputChunks: Buffer[] = [];\n\n // Use canAllocateBufferSize to dynamically check if pre-allocation is safe\n const canPreAllocate = unpackSize && unpackSize > 0 && canAllocateBufferSize(unpackSize);\n if (canPreAllocate) {\n outputBuffer = allocBufferUnsafe(unpackSize);\n }\n\n let offset = 0;\n\n // Parse and decode LZMA2 chunks one at a time\n while (true) {\n const result = parseLzma2ChunkHeader(input, offset);\n\n if (!result.success) {\n throw new Error('Truncated LZMA2 chunk header');\n }\n\n const chunk = result.chunk;\n\n if (chunk.type === 'end') {\n break;\n }\n\n const dataOffset = offset + chunk.headerSize;\n\n // Handle dictionary reset\n if (chunk.dictReset) {\n this.lzmaDecoder.resetDictionary();\n }\n\n // Handle state reset\n if (chunk.stateReset) {\n this.lzmaDecoder.resetProbabilities();\n }\n\n // Apply new properties if present\n if (chunk.newProps) {\n const { lc, lp, pb } = chunk.newProps;\n this.lzmaDecoder.setLcLpPb(lc, lp, pb);\n }\n\n // Determine solid mode\n const useSolid = !chunk.stateReset || (chunk.stateReset && !chunk.dictReset);\n\n if (chunk.type === 'uncompressed') {\n // Read uncompressed data\n const uncompData = readBytes(input, dataOffset, chunk.uncompSize);\n\n // Copy to output\n if (outputBuffer) {\n uncompData.copy(outputBuffer, outputPos);\n outputPos += uncompData.length;\n } else {\n outputChunks.push(uncompData);\n }\n\n // Feed uncompressed data to dictionary so subsequent LZMA chunks can reference it\n this.lzmaDecoder.feedUncompressed(uncompData);\n\n offset = dataOffset + chunk.uncompSize;\n } else {\n // LZMA compressed chunk - decode directly from BufferLike\n if (outputBuffer) {\n // Zero-copy: decode directly into caller's buffer\n const bytesWritten = this.lzmaDecoder.decodeToBuffer(input, dataOffset, chunk.uncompSize, outputBuffer, outputPos, useSolid);\n outputPos += bytesWritten;\n } else {\n // No pre-allocation: decode to new buffer and collect chunks\n const chunkData = readBytes(input, dataOffset, chunk.compSize);\n const decoded = this.lzmaDecoder.decode(chunkData, 0, chunk.uncompSize, useSolid);\n outputChunks.push(decoded);\n }\n\n offset = dataOffset + chunk.compSize;\n }\n }\n\n // Return pre-allocated buffer or concatenated chunks\n if (outputBuffer) {\n return outputPos < outputBuffer.length ? outputBuffer.slice(0, outputPos) : outputBuffer;\n }\n // Use bufferConcat which handles large buffers safely via pairwise combination\n return bufferConcat(outputChunks);\n }\n}\n\n/**\n * Decode LZMA2 data synchronously\n * @param input - LZMA2 compressed data (Buffer or BufferList)\n * @param properties - 1-byte properties (dictionary size)\n * @param unpackSize - Expected output size (optional, autodetects if not provided)\n * @param outputSink - Optional output sink with write callback for streaming (returns bytes written)\n * @returns Decompressed data (or bytes written if outputSink provided)\n */\nexport function decodeLzma2(input: BufferLike, properties: Buffer | Uint8Array, unpackSize?: number, outputSink?: { write(buffer: Buffer): void }): Buffer | number {\n // For very large outputs on old Node versions, we cannot return a single Buffer\n // Use streaming mode internally to handle large outputs on modern Node\n if (!outputSink && unpackSize && unpackSize > 0 && !canAllocateBufferSize(unpackSize)) {\n // Large output - use streaming mode with internal chunking\n const chunks: Buffer[] = [];\n const sink: OutputSink = {\n write(buffer: Buffer): void {\n chunks.push(buffer);\n },\n };\n\n const decoder = new Lzma2Decoder(properties, sink);\n decoder.decodeWithSink(input);\n\n // Combine chunks at the end - use bufferConcat for safe combination\n return bufferConcat(chunks);\n }\n\n const decoder = new Lzma2Decoder(properties, outputSink as OutputSink);\n if (outputSink) {\n // Zero-copy mode: write to sink during decode\n return decoder.decodeWithSink(input);\n }\n // Buffering mode: returns Buffer (zero-copy)\n return decoder.decode(input, unpackSize);\n}\n"],"names":["allocBufferUnsafe","bufferConcat","bufferFrom","canAllocateBufferSize","parseLzma2ChunkHeader","parseLzma2DictionarySize","LzmaDecoder","readBytes","input","offset","length","Buffer","isBuffer","slice","buf","Array","i","readByte","Lzma2Decoder","resetDictionary","lzmaDecoder","resetProbabilities","setLcLpPb","lc","lp","pb","feedUncompressed","data","decodeLzmaData","outSize","solid","decode","decodeWithSink","totalBytes","result","success","Error","chunk","type","dictReset","stateReset","newProps","dataOffset","headerSize","useSolid","uncompData","uncompSize","compSize","flushOutWindow","unpackSize","outputBuffer","outputPos","outputChunks","canPreAllocate","copy","push","bytesWritten","decodeToBuffer","chunkData","decoded","properties","outputSink","dictionarySize","setDictionarySize","decodeLzma2","chunks","sink","write","buffer","decoder"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xz-compat",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "XZ Decompression Library",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"extract",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"version": "tsds version"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"extract-base-iterator": "^3.
|
|
56
|
+
"extract-base-iterator": "^3.4.3",
|
|
57
57
|
"install-module-linked": "^1.3.16",
|
|
58
58
|
"os-shim": "^0.1.3"
|
|
59
59
|
},
|