Expose wrapped fs functions for plugins

Unlike the wrapped files.* functions, files.fsFixPath is closer to fs.*
in API or async/sync and callbacks.
This commit is contained in:
Slava Kim
2015-07-23 18:10:27 -07:00
parent 62c99185a4
commit 95ae655c4e
5 changed files with 67 additions and 36 deletions

View File

@@ -178,7 +178,7 @@ CachingCompilerBase = class CachingCompilerBase {
// doesn't exist.
_readFileOrNull(filename) {
try {
return fs.readFile(filename, 'utf8');
return fs.readFileSync(filename, 'utf8');
} catch (e) {
if (e && e.code === 'ENOENT')
return null;

View File

@@ -110,7 +110,7 @@ class StylusCompiler extends MultiFileCachingCompiler {
if (isAbsolute || isNib || isStylusBuiltIn) {
// absolute path? let the default implementation handle this
return fs.readFile(filePath, 'utf8');
return fs.readFileSync(filePath, 'utf8');
}
const parsed = parseImportPath(filePath);

View File

@@ -1303,6 +1303,8 @@ files.readLinkToMeteorScript = function (linkLocation, platform) {
// A helpful file to import for this purpose is colon-converter.js, which also
// knows how to convert various configuration file formats.
files.fsFixPath = {};
/**
* Wrap a function from node's fs module to use the right slashes for this OS
* and run in a fiber, then assign it to the "files" namespace. Each call
@@ -1310,6 +1312,9 @@ files.readLinkToMeteorScript = function (linkLocation, platform) {
* until the call is done), unless run outside a Fiber or in noYieldsAllowed, in
* which case it uses fs.funcSync.
*
* Also creates a simpler version on files.fsFixPath.* that just fixes the path
* and fiberizes the Sync version if possible.
*
* @param {String} fsFuncName The name of the node fs function to wrap
* @param {Number[]} pathArgIndices Indices of arguments that have paths, these
* arguments will be converted to the correct OS slashes
@@ -1322,46 +1327,72 @@ files.readLinkToMeteorScript = function (linkLocation, platform) {
function wrapFsFunc(fsFuncName, pathArgIndices, options) {
options = options || {};
var fsFunc = fs[fsFuncName];
var fsFuncSync = fs[fsFuncName + "Sync"];
const fsFunc = fs[fsFuncName];
const fsFuncSync = fs[fsFuncName + "Sync"];
function wrapper(...args) {
for (var j = pathArgIndices.length - 1; j >= 0; --j) {
i = pathArgIndices[j];
args[i] = files.convertToOSPath(args[i]);
}
function makeWrapper ({alwaysSync, sync}) {
function wrapper(...args) {
for (let j = pathArgIndices.length - 1; j >= 0; --j) {
const i = pathArgIndices[j];
args[i] = files.convertToOSPath(args[i]);
}
if (Fiber.current &&
Fiber.yield && ! Fiber.yield.disallowed) {
var fut = new Future;
const canYield = Fiber.current && Fiber.yield && ! Fiber.yield.disallowed;
const shouldBeSync = alwaysSync || sync;
args.push(function callback(err, value) {
if (options.noErr) {
fut.return(err);
} else if (err) {
fut.throw(err);
} else {
fut.return(value);
if (canYield && shouldBeSync) {
const fut = new Future;
args.push(function callback(err, value) {
if (options.noErr) {
fut.return(err);
} else if (err) {
fut.throw(err);
} else {
fut.return(value);
}
});
fsFunc.apply(fs, args);
const result = fut.wait();
return options.modifyReturnValue
? options.modifyReturnValue(result)
: result;
} else if (shouldBeSync) {
// Should be sync but can't yield: we are not in a Fiber.
// Run the sync version of the fs.* method.
const result = fsFuncSync.apply(fs, args);
return options.modifyReturnValue ?
options.modifyReturnValue(result) : result;
} else if (! sync) {
// wrapping a plain async version
const cb = args[fsFunc.length - 1];
if (typeof cb === 'function') {
args[fsFunc.length - 1] = function (err, res) {
if (options.modifyReturnValue) {
res = options.modifyReturnValue(res);
}
Fiber(cb.bind(null, err, res)).run();
};
}
});
fsFunc.apply(fs, args);
return null;
}
fsFunc.apply(fs, args);
var result = fut.wait();
return options.modifyReturnValue
? options.modifyReturnValue(result)
: result;
throw new Error('unexpected');
}
// If we're not in a Fiber, run the sync version of the fs.* method.
var result = fsFuncSync.apply(fs, args);
return options.modifyReturnValue
? options.modifyReturnValue(result)
: result;
wrapper.displayName = fsFuncName;
return wrapper;
}
wrapper.displayName = fsFuncName;
return files[fsFuncName] = Profile("files." + fsFuncName, wrapper);
files[fsFuncName] = Profile('files.' + fsFuncName, makeWrapper({ alwaysSync: true }));
files.fsFixPath[fsFuncName] =
Profile('wrapped.fs.' + fsFuncName, makeWrapper({ sync: false }));
files.fsFixPath[fsFuncName + 'Sync'] =
Profile('wrapped.fs.' + fsFuncName + 'Sync', makeWrapper({ sync: true }));
}
wrapFsFunc("writeFile", [0]);

View File

@@ -828,7 +828,7 @@ _.extend(Isopack.prototype, {
extname: files.pathExtname,
sep: files.pathSep
},
fs: files
fs: files.fsFixPath
};
return Plugin;
},

View File

@@ -25,14 +25,14 @@ PrintmeCompiler.prototype.processFilesForTarget = function (inputFiles) {
});
console.log("PrintmeCompiler invocation", ++self.runCount);
if (self.diskCache) {
fs.writeFile(self.diskCache, self.runCount + '\n');
fs.writeFileSync(self.diskCache, self.runCount + '\n');
}
};
PrintmeCompiler.prototype.setDiskCacheDirectory = function (diskCacheDir) {
var self = this;
self.diskCache = path.join(diskCacheDir, 'cache');
try {
var data = fs.readFile(self.diskCache, 'utf8');
var data = fs.readFileSync(self.diskCache, 'utf8');
} catch (e) {
if (e.code !== 'ENOENT')
throw e;