Remove `fastfs.readWhile`

Reviewed By: davidaurelio

Differential Revision: D4021265

fbshipit-source-id: 578ad54ea5a81e5b091cecafcb2fe6d08746e7f6
This commit is contained in:
Christoph Pojer 2016-10-16 18:32:07 -07:00 committed by Facebook Github Bot
parent 5fe2c32cfc
commit f53d694120
3 changed files with 14 additions and 186 deletions

View File

@ -10,10 +10,10 @@
const crypto = require('crypto'); const crypto = require('crypto');
const docblock = require('./DependencyGraph/docblock'); const docblock = require('./DependencyGraph/docblock');
const extractRequires = require('./lib/extractRequires');
const isAbsolutePath = require('absolute-path'); const isAbsolutePath = require('absolute-path');
const jsonStableStringify = require('json-stable-stringify'); const jsonStableStringify = require('json-stable-stringify');
const path = require('./fastpath'); const path = require('./fastpath');
const extractRequires = require('./lib/extractRequires');
class Module { class Module {
@ -115,12 +115,16 @@ class Module {
return {id, moduleDocBlock}; return {id, moduleDocBlock};
} }
_readDocBlock(contentPromise) { _read() {
if (!this._readPromise) {
this._readPromise = this._fastfs.readFile(this.path);
}
return this._readPromise;
}
_readDocBlock() {
if (!this._docBlock) { if (!this._docBlock) {
if (!contentPromise) { this._docBlock = this._read()
contentPromise = this._fastfs.readWhile(this.path, whileInDocBlock);
}
this._docBlock = contentPromise
.then(docBlock => this._parseDocBlock(docBlock)); .then(docBlock => this._parseDocBlock(docBlock));
} }
return this._docBlock; return this._docBlock;
@ -131,10 +135,9 @@ class Module {
this.path, this.path,
cacheKey('moduleData', transformOptions), cacheKey('moduleData', transformOptions),
() => { () => {
const fileContentPromise = this._fastfs.readFile(this.path);
return Promise.all([ return Promise.all([
fileContentPromise, this._read(),
this._readDocBlock(fileContentPromise), this._readDocBlock(),
]).then(([source, {id, moduleDocBlock}]) => { ]).then(([source, {id, moduleDocBlock}]) => {
// Ignore requires in JSON files or generated code. An example of this // Ignore requires in JSON files or generated code. An example of this
// is prebuilt files like the SourceMap library. // is prebuilt files like the SourceMap library.
@ -194,21 +197,6 @@ class Module {
} }
} }
function whileInDocBlock(chunk, i, result) {
// consume leading whitespace
if (!/\S/.test(result)) {
return true;
}
// check for start of doc block
if (!/^\s*\/(\*{2}|\*?$)/.test(result)) {
return false;
}
// check for end of doc block
return !/\*\//.test(result);
}
// use weak map to speed up hash creation of known objects // use weak map to speed up hash creation of known objects
const knownHashes = new WeakMap(); const knownHashes = new WeakMap();
function stableObjectHash(object) { function stableObjectHash(object) {

View File

@ -1,91 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
jest.autoMockOff()
.dontMock('graceful-fs');
const Fastfs = require('../fastfs');
const {EventEmitter} = require('events');
const fs = require('fs');
const path = require('path');
const fileName = path.resolve(__dirname, 'fastfs-data');
const contents = fs.readFileSync(fileName, 'utf-8');
describe('fastfs:', function() {
let fastfs;
const roots = [__dirname];
const watcher = new EventEmitter();
beforeEach(function() {
fastfs = new Fastfs(
'arbitrary',
roots,
watcher,
[`${__dirname}/fastfs-data`],
{}
);
});
describe('partial reading', () => {
// these are integrated tests that read real files from disk
pit('reads a file while a predicate returns true', function() {
return fastfs.readWhile(fileName, () => true).then(readContent =>
expect(readContent).toEqual(contents)
);
});
pit('invokes the predicate with the new chunk, the invocation index, and the result collected so far', () => {
const predicate = jest.genMockFn().mockReturnValue(true);
return fastfs.readWhile(fileName, predicate).then(() => {
let aggregated = '';
const {calls} = predicate.mock;
expect(calls).not.toEqual([]);
calls.forEach((call, i) => {
const [chunk] = call;
aggregated += chunk;
expect(chunk).not.toBe('');
expect(call).toEqual([chunk, i, aggregated]);
});
expect(aggregated).toEqual(contents);
});
});
pit('stops reading when the predicate returns false', () => {
const predicate = jest.genMockFn().mockImpl((_, i) => i !== 0);
return fastfs.readWhile(fileName, predicate).then((readContent) => {
const {calls} = predicate.mock;
expect(calls.length).toBe(1);
expect(readContent).toBe(calls[0][2]);
});
});
pit('after reading the whole file with `readWhile`, `read()` still works', () => {
// this test allows to reuse the results of `readWhile` for `readFile`
return fastfs.readWhile(fileName, () => true).then(() => {
fastfs.readFile(fileName).then(readContent =>
expect(readContent).toEqual(contents)
);
});
});
pit('after reading parts of the file with `readWhile`, `read()` still works', () => {
return fastfs.readWhile(fileName, () => false).then(() => {
fastfs.readFile(fileName).then(readContent =>
expect(readContent).toEqual(contents)
);
});
});
});
});

View File

@ -9,11 +9,11 @@
'use strict'; 'use strict';
const denodeify = require('denodeify'); const denodeify = require('denodeify');
const {EventEmitter} = require('events');
const fs = require('fs'); const fs = require('fs');
const path = require('./fastpath'); const path = require('./fastpath');
const {EventEmitter} = require('events');
const readFile = denodeify(fs.readFile); const readFile = denodeify(fs.readFile);
const stat = denodeify(fs.stat); const stat = denodeify(fs.stat);
@ -101,14 +101,6 @@ class Fastfs extends EventEmitter {
return file.read(); return file.read();
} }
readWhile(filePath, predicate) {
const file = this._getFile(filePath);
if (!file) {
throw new Error(`Unable to find file with path: ${filePath}`);
}
return file.readWhile(predicate);
}
closest(filePath, name) { closest(filePath, name) {
for (let file = this._getFile(filePath).parent; for (let file = this._getFile(filePath).parent;
file; file;
@ -235,15 +227,6 @@ class File {
return this._read; return this._read;
} }
readWhile(predicate) {
return readWhile(this.path, predicate).then(({result, completed}) => {
if (completed && !this._read) {
this._read = Promise.resolve(result);
}
return result;
});
}
stat() { stat() {
if (!this._stat) { if (!this._stat) {
this._stat = stat(this.path); this._stat = stat(this.path);
@ -303,58 +286,6 @@ class File {
} }
} }
function readWhile(filePath, predicate) {
return new Promise((resolve, reject) => {
fs.open(filePath, 'r', (openError, fd) => {
if (openError) {
reject(openError);
return;
}
read(
fd,
/*global Buffer: true*/
new Buffer(512),
makeReadCallback(fd, predicate, (readError, result, completed) => {
if (readError) {
reject(readError);
} else {
resolve({result, completed});
}
})
);
});
});
}
function read(fd, buffer, callback) {
fs.read(fd, buffer, 0, buffer.length, -1, callback);
}
function close(fd, error, result, complete, callback) {
fs.close(fd, closeError => callback(error || closeError, result, complete));
}
function makeReadCallback(fd, predicate, callback) {
let result = '';
let index = 0;
return function readCallback(error, bytesRead, buffer) {
if (error) {
close(fd, error, undefined, false, callback);
return;
}
const completed = bytesRead === 0;
const chunk = completed ? '' : buffer.toString('utf8', 0, bytesRead);
result += chunk;
if (completed || !predicate(chunk, index++, result)) {
close(fd, null, result, completed, callback);
} else {
read(fd, buffer, readCallback);
}
};
}
function isDescendant(root, child) { function isDescendant(root, child) {
return root === child || child.startsWith(root + path.sep); return root === child || child.startsWith(root + path.sep);
} }