react / react-0.13.3 / examples / basic-commonjs / node_modules / reactify / node_modules / react-tools / node_modules / commoner / lib / cache.js
81159 viewsvar assert = require("assert");1var Q = require("q");2var fs = require("fs");3var path = require("path");4var util = require("./util");5var EventEmitter = require("events").EventEmitter;6var hasOwn = Object.prototype.hasOwnProperty;78/**9* ReadFileCache is an EventEmitter subclass that caches file contents in10* memory so that subsequent calls to readFileP return the same contents,11* regardless of any changes in the underlying file.12*/13function ReadFileCache(sourceDir, charset) {14assert.ok(this instanceof ReadFileCache);15assert.strictEqual(typeof sourceDir, "string");1617this.charset = charset;1819EventEmitter.call(this);2021Object.defineProperties(this, {22sourceDir: { value: sourceDir },23sourceCache: { value: {} }24});25}2627util.inherits(ReadFileCache, EventEmitter);28var RFCp = ReadFileCache.prototype;2930/**31* Read a file from the cache if possible, else from disk.32*/33RFCp.readFileP = function(relativePath) {34var cache = this.sourceCache;3536relativePath = path.normalize(relativePath);3738return hasOwn.call(cache, relativePath)39? cache[relativePath]40: this.noCacheReadFileP(relativePath);41};4243/**44* Read (or re-read) a file without using the cache.45*46* The new contents are stored in the cache for any future calls to47* readFileP.48*/49RFCp.noCacheReadFileP = function(relativePath) {50relativePath = path.normalize(relativePath);5152var added = !hasOwn.call(this.sourceCache, relativePath);53var promise = this.sourceCache[relativePath] = util.readFileP(54path.join(this.sourceDir, relativePath), this.charset);5556if (added) {57this.emit("added", relativePath);58}5960return promise;61};6263/**64* If you have reason to believe the contents of a file have changed, call65* this method to re-read the file and compare the new contents to the66* cached contents. If the new contents differ from the contents of the67* cache, the "changed" event will be emitted.68*/69RFCp.reportPossiblyChanged = function(relativePath) {70var self = this;71var cached = self.readFileP(relativePath);72var fresh = self.noCacheReadFileP(relativePath);7374Q.spread([75cached.catch(orNull),76fresh.catch(orNull)77], function(oldData, newData) {78if (oldData !== newData) {79self.emit("changed", relativePath);80}81}).done();82};8384/**85* Invoke the given callback for all files currently known to the86* ReadFileCache, and invoke it in the future when any new files become87* known to the cache.88*/89RFCp.subscribe = function(callback, context) {90for (var relativePath in this.sourceCache) {91if (hasOwn.call(this.sourceCache, relativePath)) {92callback.call(context || null, relativePath);93}94}9596this.on("added", function(relativePath) {97callback.call(context || null, relativePath);98});99};100101/**102* Avoid memory leaks by removing listeners and emptying the cache.103*/104RFCp.clear = function() {105this.removeAllListeners();106107for (var relativePath in this.sourceCache) {108delete this.sourceCache[relativePath];109}110};111112function orNull(err) {113return null;114}115116exports.ReadFileCache = ReadFileCache;117118119