Comparing version 3.12.1 to 4.0.0-beta.1
125
lib/index.js
'use strict'; | ||
var realFs = require('fs'); | ||
var path = require('path'); | ||
var rewire = require('rewire'); | ||
var semver = require('semver'); | ||
var Binding = require('./binding'); | ||
var FSError = require('./error'); | ||
var FileSystem = require('./filesystem'); | ||
var FSError = require('./error'); | ||
var realBinding = process.binding('fs'); | ||
var path = require('path'); | ||
var versions = { | ||
'0.8.x': 'fs-0.8.26.js', | ||
'0.9.x': 'fs-0.9.12.js', | ||
'0.10.x': 'fs-0.10.28.js', | ||
'0.11 - 0.11.14': 'fs-0.11.13.js', | ||
'0.11.15 - 0.12.x': 'fs-0.12.0.js', | ||
'1.x.x': 'fs-1.1.0.js', | ||
'2.x.x': 'fs-2.0.0.js', | ||
'3.x.x': 'fs-3.0.0.js', | ||
'4.x.x': 'fs-4.0.0.js', | ||
'5.x.x': 'fs-5.0.0.js', | ||
'6.x.x': 'fs-6.3.0.js', | ||
'7.x.x': 'fs-7.0.0.js' | ||
}; | ||
var nodeVersion = process.versions.node; | ||
var fsName; | ||
Object.keys(versions).some(function(version) { | ||
if (semver.satisfies(nodeVersion, version)) { | ||
fsName = versions[version]; | ||
return true; | ||
} | ||
}); | ||
if (!fsName) { | ||
throw new Error('Unsupported Node version: ' + nodeVersion); | ||
} | ||
/** | ||
* Hijack the real fs module immediately so the binding can be swapped at will. | ||
* This works as expected in cases where mock-fs is required before any other | ||
* module that wraps fs exports. | ||
*/ | ||
var mockFs = rewire(path.join(__dirname, '..', 'node', fsName)); | ||
var originalBinding = mockFs.__get__('binding'); | ||
var originalStats = mockFs.Stats; | ||
for (var name in mockFs) { | ||
var descriptor = Object.getOwnPropertyDescriptor(realFs, name); | ||
if (!descriptor || descriptor && descriptor.writable) { | ||
realFs[name] = (function(mockFunction, realFunction) { | ||
return function() { | ||
var stack = new Error().stack; | ||
if (stack.indexOf('at Module.require (module') >= 0) { | ||
return realFunction.apply(realFs, arguments); | ||
} else { | ||
return mockFunction.apply(realFs, arguments); | ||
} | ||
}; | ||
}(mockFs[name], realFs[name])); | ||
} | ||
} | ||
var originalProcess = { | ||
var realBindingProps = Object.assign({}, realBinding); | ||
var realProcessProps = { | ||
cwd: process.cwd, | ||
@@ -71,8 +16,14 @@ chdir: process.chdir | ||
function setBinding(binding, Stats) { | ||
mockFs.__set__('binding', binding); | ||
mockFs.Stats = realFs.Stats = Stats; | ||
function overrideBinding(binding) { | ||
for (var key in binding) { | ||
if (typeof binding[key] === 'function') { | ||
realBinding[key] = binding[key].bind(binding); | ||
} else { | ||
realBinding[key] = binding[key]; | ||
} | ||
} | ||
} | ||
function setProcess(cwd, chdir) { | ||
function overrideProcess(cwd, chdir) { | ||
process.cwd = cwd; | ||
@@ -82,3 +33,14 @@ process.chdir = chdir; | ||
function restoreBinding() { | ||
for (var key in realBindingProps) { | ||
realBinding[key] = realBindingProps[key]; | ||
} | ||
} | ||
function restoreProcess() { | ||
for (var key in realProcessProps) { | ||
process[key] = realProcessProps[key]; | ||
} | ||
} | ||
/** | ||
@@ -96,6 +58,6 @@ * Swap out the fs bindings for a mock file system. | ||
var binding = new Binding(system); | ||
setBinding(binding, binding.Stats); | ||
overrideBinding(binding); | ||
var currentPath = process.cwd(); | ||
setProcess( | ||
overrideProcess( | ||
function cwd() { | ||
@@ -105,3 +67,3 @@ return currentPath; | ||
function chdir(directory) { | ||
if (!mockFs.statSync(directory).isDirectory()) { | ||
if (!binding.stat(path._makeLong(directory)).isDirectory()) { | ||
throw new FSError('ENOTDIR'); | ||
@@ -119,4 +81,4 @@ } | ||
exports.restore = function() { | ||
setBinding(originalBinding, originalStats); | ||
setProcess(originalProcess.cwd, originalProcess.chdir); | ||
restoreBinding(); | ||
restoreProcess(); | ||
}; | ||
@@ -126,27 +88,2 @@ | ||
/** | ||
* Create a mock fs module based on the given file system configuration. | ||
* @param {Object} config File system configuration. | ||
* @param {Object} options Any filesystem options. | ||
* @param {boolean} options.createCwd Create a directory for `process.cwd()` | ||
* (defaults to `true`). | ||
* @param {boolean} options.createTmp Create a directory for `os.tmpdir()` | ||
* (defaults to `true`). | ||
* @return {Object} A fs module with a mock file system. | ||
*/ | ||
exports.fs = function(config, options) { | ||
var system = FileSystem.create(config, options); | ||
var binding = new Binding(system); | ||
// inject the mock binding | ||
var newMockFs = rewire(path.join(__dirname, '..', 'node', fsName)); | ||
newMockFs.__set__('binding', binding); | ||
// overwrite fs.Stats from original binding | ||
newMockFs.Stats = binding.Stats; | ||
return newMockFs; | ||
}; | ||
/** | ||
* Create a file factory. | ||
@@ -153,0 +90,0 @@ */ |
{ | ||
"name": "mock-fs", | ||
"description": "A configurable mock file system. You know, for testing.", | ||
"version": "3.12.1", | ||
"version": "4.0.0-beta.1", | ||
"main": "lib/index.js", | ||
@@ -35,11 +35,7 @@ "homepage": "https://github.com/tschaub/mock-fs", | ||
"chai": "3.5.0", | ||
"eslint": "2.13.0", | ||
"eslint-config-tschaub": "6.0.0", | ||
"eslint": "^3.11.1", | ||
"eslint-config-tschaub": "^6.0.0", | ||
"mocha": "3.1.2", | ||
"rimraf": "2.5.4" | ||
}, | ||
"dependencies": { | ||
"rewire": "2.5.2", | ||
"semver": "5.3.0" | ||
} | ||
} |
@@ -29,2 +29,19 @@ # `mock-fs` | ||
## Upgrading to version 4 | ||
The `mock-fs@4` release will contain breaking changes. Instead of overriding all methods of the built-in `fs` module, the library now overrides `process.binding('fs')`. The purpose of this change is to avoid conflicts with other libraries that override `fs` methods (e.g. `graceful-fs`) and to make it possible to work with multiple Node releases without maintaining copied and slightly modified versions of Node's `fs` module. | ||
Until the `mock-fs@4.0.0` release, you can try out a beta release: | ||
``` | ||
npm install mock-fs@beta --save-dev | ||
``` | ||
The final 4.0 release may contain fewer breaking changes than the latest beta. For now, these are the breaking changes: | ||
* The `mock.fs()` function has been removed. This returned an object with `fs`-like methods without overriding the built-in `fs` module. It may be possible to bring this function back, but it is not included in the latest beta release. | ||
* The object created by `fs.Stats` is no longer an instanceof `fs.Stats` (though it has all the same properties and methods). This too may be possible to fix before the final release. | ||
* Lazy `require()` do not use the real filesystem. | ||
* Tests are no longer run in Node < 4. | ||
## Docs | ||
@@ -178,8 +195,2 @@ | ||
### Creating a new `fs` module instead of modifying the original | ||
### <a id='mockfsconfigoptions'>`mock.fs(config, options)`</a> | ||
Calling `mock()` modifies Node's built-in `fs` module. This is useful when you want to test with a mock file system. If for some reason you want to work with the real file system and an in-memory version at the same time, you can call the `mock.fs()` function. This takes the same `config` and `options` objects [described above](#mockconfigoptions) and sets up a in-memory file system. Instead of modifying the binding for the built-in `fs` module (as is done when calling `mock(config)`), the `mock.fs(config)` function returns an object with the same interface as the `fs` module, but backed by your mock file system. | ||
## Install | ||
@@ -186,0 +197,0 @@ |
@@ -462,6 +462,7 @@ 'use strict'; | ||
assert.isArray(items); | ||
assert.deepEqual(items.sort(), | ||
['dead-link', 'dir-link', 'dir-link2', 'empty', 'non-empty', | ||
'one-link.txt', 'one-link2.txt', 'one.txt', 'three.bin', | ||
'two.txt']); | ||
assert.deepEqual(items.sort(), [ | ||
'dead-link', 'dir-link', 'dir-link2', 'empty', 'non-empty', | ||
'one-link.txt', 'one-link2.txt', 'one.txt', 'three.bin', | ||
'two.txt' | ||
]); | ||
done(); | ||
@@ -482,6 +483,7 @@ }); | ||
}); | ||
assert.deepEqual(strings.sort(), | ||
['dead-link', 'dir-link', 'dir-link2', 'empty', 'non-empty', | ||
'one-link.txt', 'one-link2.txt', 'one.txt', 'three.bin', | ||
'two.txt']); | ||
assert.deepEqual(strings.sort(), [ | ||
'dead-link', 'dir-link', 'dir-link2', 'empty', 'non-empty', | ||
'one-link.txt', 'one-link2.txt', 'one.txt', 'three.bin', | ||
'two.txt' | ||
]); | ||
done(); | ||
@@ -495,6 +497,7 @@ }); | ||
assert.isArray(items); | ||
assert.deepEqual(items.sort(), | ||
['dead-link', 'dir-link', 'dir-link2', 'empty', 'non-empty', | ||
'one-link.txt', 'one-link2.txt', 'one.txt', 'three.bin', | ||
'two.txt']); | ||
assert.deepEqual(items.sort(), [ | ||
'dead-link', 'dir-link', 'dir-link2', 'empty', 'non-empty', | ||
'one-link.txt', 'one-link2.txt', 'one.txt', 'three.bin', | ||
'two.txt' | ||
]); | ||
}); | ||
@@ -1019,6 +1022,7 @@ | ||
assert.isArray(items); | ||
assert.deepEqual(items.sort(), | ||
['dead-link', 'dir-link', 'dir-link2', 'empty', 'non-empty', | ||
'one-link.txt', 'one-link2.txt', 'one.txt', 'three.bin', | ||
'two.txt']); | ||
assert.deepEqual(items.sort(), [ | ||
'dead-link', 'dir-link', 'dir-link2', 'empty', 'non-empty', | ||
'one-link.txt', 'one-link2.txt', 'one.txt', 'three.bin', | ||
'two.txt' | ||
]); | ||
}); | ||
@@ -1025,0 +1029,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
0
223
10
256608
37
7452
1
1
- Removedrewire@2.5.2
- Removedsemver@5.3.0
- Removedrewire@2.5.2(transitive)
- Removedsemver@5.3.0(transitive)