Skip to content
This repository was archived by the owner on Aug 15, 2024. It is now read-only.

Commit def1aa1

Browse files
Support createReadStream and createWriteStream.
Preliminary support for the functions by the same name from the `fs` module.
1 parent b907853 commit def1aa1

File tree

3 files changed

+133
-1
lines changed

3 files changed

+133
-1
lines changed

lib/MemoryFileSystem.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
*/
55

66
var normalize = require("./normalize");
7+
var stream = require("stream");
8+
9+
var ReadableStream = stream.Readable;
10+
var WritableStream = stream.Writable;
711

812
function MemoryFileSystem(data) {
913
this.data = data || {};
@@ -185,6 +189,60 @@ MemoryFileSystem.prototype.join = require("./join");
185189

186190
MemoryFileSystem.prototype.normalize = normalize;
187191

192+
// stream functions
193+
194+
MemoryFileSystem.prototype.createReadStream = function(path, options) {
195+
var stream = new ReadableStream();
196+
var done = false;
197+
var data;
198+
try {
199+
data = this.readFileSync(path);
200+
} catch (e) {
201+
stream._read = function() {
202+
if (done) {
203+
return;
204+
}
205+
done = true;
206+
this.emit('error', e);
207+
this.push(null);
208+
};
209+
return stream;
210+
}
211+
options = options || { };
212+
options.start = options.start || 0;
213+
options.end = options.end || data.length;
214+
stream._read = function() {
215+
if (done) {
216+
return;
217+
}
218+
done = true;
219+
this.push(data.slice(options.start, options.end));
220+
this.push(null);
221+
};
222+
return stream;
223+
};
224+
225+
MemoryFileSystem.prototype.createWriteStream = function(path, options) {
226+
var stream = new WritableStream(), self = this;
227+
try {
228+
// Zero the file and make sure it is writable
229+
this.writeFileSync(path, new Buffer(0));
230+
} catch(e) {
231+
// This or setImmediate?
232+
stream.once('prefinish', function() {
233+
stream.emit('error', e);
234+
});
235+
return stream;
236+
}
237+
var bl = [ ], len = 0;
238+
stream._write = function(chunk, encoding, callback) {
239+
bl.push(chunk);
240+
len += chunk.length;
241+
self.writeFile(path, Buffer.concat(bl, len), callback);
242+
}
243+
return stream;
244+
};
245+
188246
// async functions
189247

190248
["stat", "readdir", "mkdirp", "mkdir", "rmdir", "unlink", "readlink"].forEach(function(fn) {

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
},
2626
"homepage": "https://github.com/webpack/memory-fs",
2727
"devDependencies": {
28+
"bl": "^1.0.0",
2829
"istanbul": "^0.2.13",
2930
"mocha": "^1.20.1",
3031
"should": "^4.0.4"

test/MemoryFileSystem.js

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
var bl = require("bl");
12
var should = require("should");
23
var MemoryFileSystem = require("../lib/MemoryFileSystem");
34

@@ -224,6 +225,78 @@ describe("async", function() {
224225
});
225226
});
226227
});
228+
describe("streams", function() {
229+
describe("writable streams", function() {
230+
it("should write files", function() {
231+
var fs = new MemoryFileSystem();
232+
fs.createWriteStream("/file").end("Hello");
233+
fs.readFileSync("/file", "utf8").should.be.eql("Hello");
234+
});
235+
it("should zero files", function() {
236+
var fs = new MemoryFileSystem();
237+
fs.createWriteStream("/file").end();
238+
fs.readFileSync("/file", "utf8").should.be.eql("");
239+
});
240+
it("should accept pipes", function(done) {
241+
// TODO: Any way to avoid the asyncness of this?
242+
var fs = new MemoryFileSystem();
243+
bl(new Buffer("Hello"))
244+
.pipe(fs.createWriteStream("/file"))
245+
.once('finish', function() {
246+
fs.readFileSync("/file", "utf8").should.be.eql("Hello");
247+
done();
248+
});
249+
});
250+
it("should propagate errors", function(done) {
251+
var fs = new MemoryFileSystem();
252+
var stream = fs.createWriteStream("file");
253+
var err = false;
254+
stream.once('error', function() {
255+
err = true;
256+
}).once('finish', function() {
257+
err.should.eql(true);
258+
done();
259+
});
260+
stream.end();
261+
});
262+
});
263+
describe("readable streams", function() {
264+
it("should read files", function() {
265+
var fs = new MemoryFileSystem();
266+
fs.writeFileSync("/file", "Hello");
267+
bl(fs.createReadStream("/file"), function(err, data) {
268+
err.should.eql(undefined);
269+
data.should.eql("Hello");
270+
});
271+
});
272+
it("should respect start/end", function() {
273+
var fs = new MemoryFileSystem();
274+
fs.writeFileSync("/file", "Hello");
275+
bl(fs.createReadStream("/file", {
276+
start: 2,
277+
end: 4
278+
}), function(err, data) {
279+
err.should.eql(undefined);
280+
data.should.eql("el");
281+
});
282+
});
283+
it("should propagate errors", function(done) {
284+
var fs = new MemoryFileSystem();
285+
var stream = fs.createReadStream("file");
286+
var err = false;
287+
// Why does this dummy event need to be here? It looks like it
288+
// either has to be this or data before the stream will actually
289+
// do anything.
290+
stream.on('readable', function() { }).on('error', function() {
291+
err = true;
292+
}).on('end', function() {
293+
err.should.eql(true);
294+
done();
295+
});
296+
stream.read(0);
297+
});
298+
});
299+
});
227300
describe("normalize", function() {
228301
it("should normalize paths", function() {
229302
var fs = new MemoryFileSystem();
@@ -359,4 +432,4 @@ describe("os", function() {
359432
fileSystem.statSync("C:\\a/dir\\index").isFile().should.be.eql(true);
360433
});
361434
});
362-
});
435+
});

0 commit comments

Comments
 (0)