Skip to content

Commit

Permalink
Merge branch 'master' into queue-microtask
Browse files Browse the repository at this point in the history
  • Loading branch information
SukkaW authored Sep 16, 2023
2 parents 8ca6d04 + 125a996 commit cfbc6d2
Show file tree
Hide file tree
Showing 11 changed files with 658 additions and 612 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
# [4.3.0](https://github.com/streamich/memfs/compare/v4.2.3...v4.3.0) (2023-09-15)


### Features

* add support for `O_SYMLINK` ([#944](https://github.com/streamich/memfs/issues/944)) ([96cbce4](https://github.com/streamich/memfs/commit/96cbce4145891af9d943d00868b3357969508330))

## [4.2.3](https://github.com/streamich/memfs/compare/v4.2.2...v4.2.3) (2023-09-15)


### Bug Fixes

* add missing nanosecond-precision properties to Stats ([#943](https://github.com/streamich/memfs/issues/943)) ([b9d4c6d](https://github.com/streamich/memfs/commit/b9d4c6daf19f75784ade8ebb8ac17afefe6442e9))

## [4.2.2](https://github.com/streamich/memfs/compare/v4.2.1...v4.2.2) (2023-09-15)


### Bug Fixes

* support directories named `__proto__` ([#945](https://github.com/streamich/memfs/issues/945)) ([8d92a0b](https://github.com/streamich/memfs/commit/8d92a0b0501eab18622febb7c4e551026b515c3b)), closes [#938](https://github.com/streamich/memfs/issues/938)

## [4.2.1](https://github.com/streamich/memfs/compare/v4.2.0...v4.2.1) (2023-08-07)


Expand Down
112 changes: 56 additions & 56 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,45 @@
{
"name": "memfs",
"version": "4.2.1",
"version": "4.3.0",
"description": "In-memory file-system with Node's fs API.",
"author": {
"name": "streamich",
"url": "https://github.com/streamich"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/streamich"
},
"keywords": [
"fs",
"filesystem",
"fs.js",
"memory-fs",
"memfs",
"file",
"file system",
"mount",
"memory",
"in-memory",
"virtual",
"test",
"testing",
"mock",
"fsa",
"file system access",
"native file system",
"webfs",
"crudfs",
"opfs",
"casfs",
"content addressable storage"
],
"homepage": "https://github.com/streamich/memfs",
"repository": {
"type": "git",
"url": "https://github.com/streamich/memfs.git"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/streamich"
},
"license": "Apache-2.0",
"author": {
"name": "streamich",
"url": "https://github.com/streamich"
},
"main": "lib/index.js",
"types": "lib/index.d.ts",
"files": [
Expand All @@ -27,47 +51,23 @@
],
"scripts": {
"build": "tsc -p .",
"build:webfs": "NODE_ENV=production webpack --config ./src/webfs/webpack.config.js",
"clean": "rimraf lib types",
"demo:crud-and-cas": "webpack serve --config ./demo/crud-and-cas/webpack.config.js",
"demo:fsa-to-node-sync-tests": "webpack serve --config ./demo/fsa-to-node-sync-tests/webpack.config.js",
"demo:fsa-to-node-zipfile": "webpack serve --config ./demo/fsa-to-node-zipfile/webpack.config.js",
"demo:git-fsa": "webpack serve --config ./demo/git-fsa/webpack.config.js",
"demo:git-opfs": "webpack serve --config ./demo/git-opfs/webpack.config.js",
"demo:webfs": "webpack serve --config ./src/webfs/webpack.config.js",
"prettier": "prettier --ignore-path .gitignore --write \"src/**/*.{ts,js}\"",
"prettier:diff": "prettier -l \"src/**/*.{ts,js}\"",
"test": "jest --maxWorkers 2",
"test:coverage": "jest --coverage",
"test:watch": "jest --watch",
"tslint": "tslint \"src/**/*.ts\" -t verbose",
"typecheck": "tsc -p .",
"watch": "watch \"npm run build\" ./src",
"build:webfs": "NODE_ENV=production webpack --config ./src/webfs/webpack.config.js",
"demo:webfs": "webpack serve --config ./src/webfs/webpack.config.js",
"demo:fsa-to-node-sync-tests": "webpack serve --config ./demo/fsa-to-node-sync-tests/webpack.config.js",
"demo:fsa-to-node-zipfile": "webpack serve --config ./demo/fsa-to-node-zipfile/webpack.config.js",
"demo:git-fsa": "webpack serve --config ./demo/git-fsa/webpack.config.js",
"demo:git-opfs": "webpack serve --config ./demo/git-opfs/webpack.config.js",
"demo:crud-and-cas": "webpack serve --config ./demo/crud-and-cas/webpack.config.js"
"watch": "watch \"npm run build\" ./src"
},
"keywords": [
"fs",
"filesystem",
"fs.js",
"memory-fs",
"memfs",
"file",
"file system",
"mount",
"memory",
"in-memory",
"virtual",
"test",
"testing",
"mock",
"fsa",
"file system access",
"native file system",
"webfs",
"crudfs",
"opfs",
"casfs",
"content addressable storage"
],
"commitlint": {
"extends": [
"@commitlint/config-conventional"
Expand All @@ -78,6 +78,16 @@
"path": "git-cz"
}
},
"prettier": {
"arrowParens": "avoid",
"bracketSpacing": true,
"printWidth": 120,
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all",
"useTabs": false
},
"release": {
"branches": [
"master",
Expand Down Expand Up @@ -110,9 +120,6 @@
"^.+\\.tsx?$": "ts-jest"
}
},
"peerDependencies": {
"tslib": "2"
},
"dependencies": {
"json-joy": "^9.2.0",
"thingies": "^1.11.1"
Expand All @@ -121,15 +128,15 @@
"@semantic-release/changelog": "^6.0.1",
"@semantic-release/git": "^10.0.1",
"@semantic-release/npm": "^9.0.1",
"@types/jest": "^27.5.2",
"@types/jest": "^29.0.0",
"@types/node": "^10.17.60",
"app-root-path": "^3.1.0",
"assert": "^2.0.0",
"buffer": "^6.0.3",
"html-webpack-plugin": "^5.5.3",
"husky": "^8.0.1",
"isomorphic-git": "^1.24.2",
"jest": "^28.1.1",
"jest": "^29.0.0",
"path-browserify": "^1.0.1",
"prettier": "^2.7.1",
"pretty-quick": "^3.1.3",
Expand All @@ -150,17 +157,10 @@
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"
},
"peerDependencies": {
"tslib": "2"
},
"engines": {
"node": ">= 4.0.0"
},
"prettier": {
"printWidth": 120,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"bracketSpacing": true,
"arrowParens": "avoid"
}
}
14 changes: 14 additions & 0 deletions src/Stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ export class Stats<T = TStatNumber> {
stats.ctimeMs = ctimeMs;
stats.birthtimeMs = ctimeMs;

if (bigint) {
stats.atimeNs = BigInt(atime.getTime()) * BigInt(1000000);
stats.mtimeNs = BigInt(mtime.getTime()) * BigInt(1000000);
const ctimeNs = BigInt(ctime.getTime()) * BigInt(1000000);
stats.ctimeNs = ctimeNs;
stats.birthtimeNs = ctimeNs;
}

stats.dev = getStatNumber(0);
stats.mode = getStatNumber(node.mode);
stats.nlink = getStatNumber(node.nlink);
Expand All @@ -68,6 +76,12 @@ export class Stats<T = TStatNumber> {
ctimeMs: T;
birthtimeMs: T;

// additional properties that exist when bigint is true
atimeNs: T extends bigint ? T : undefined;
mtimeNs: T extends bigint ? T : undefined;
ctimeNs: T extends bigint ? T : undefined;
birthtimeNs: T extends bigint ? T : undefined;

dev: T;
mode: T;
nlink: T;
Expand Down
57 changes: 56 additions & 1 deletion src/__tests__/volume.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import hasBigInt from './hasBigInt';
import { tryGetChild, tryGetChildNode } from './util';
import { genRndStr6 } from '../node/util';
import queueMicrotask from '../queueMicrotask';
import { constants } from '../constants';

const { O_RDWR, O_SYMLINK } = constants;

describe('volume', () => {
describe('filenameToSteps(filename): string[]', () => {
Expand Down Expand Up @@ -485,13 +488,26 @@ describe('volume', () => {
});
});
describe('.read(fd, buffer, offset, length, position, callback)', () => {
xit('...', () => {});
const vol = new Volume();
const data = 'trololo';
const fileNode = (vol as any).createLink(vol.root, 'text.txt').getNode();
fileNode.setString(data);
vol.symlinkSync('/text.txt', '/link.txt');

it('Attempt to read from a symlink should throw EPERM', () => {
const fd = vol.openSync('/link.txt', O_SYMLINK);
expect(vol.fstatSync(fd).isSymbolicLink()).toBe(true);
const buf = Buffer.alloc(10);
const fn = () => vol.readSync(fd, buf, 0, 10, 0);
expect(fn).toThrowError('EPERM');
});
});
describe('.readFileSync(path[, options])', () => {
const vol = new Volume();
const data = 'trololo';
const fileNode = (vol as any).createLink(vol.root, 'text.txt').getNode();
fileNode.setString(data);

it('Read file at root (/text.txt)', () => {
const buf = vol.readFileSync('/text.txt');
const str = buf.toString();
Expand Down Expand Up @@ -585,6 +601,16 @@ describe('volume', () => {
vol.closeSync(fd);
expect(vol.readFileSync('/overwrite.txt', 'utf8')).toBe('mArmagedon');
});
it('Attempt to write to a symlink should throw EBADF', () => {
const data = 'asdfasdf asdfasdf asdf';
vol.writeFileSync('/file.txt', data);
vol.symlinkSync('/file.txt', '/link.txt');

const fd = vol.openSync('/link.txt', O_SYMLINK | O_RDWR);
expect(vol.fstatSync(fd).isSymbolicLink()).toBe(true);
const fn = () => vol.writeSync(fd, 'hello');
expect(fn).toThrowError('EBADF');
});
});
describe('.write(fd, buffer, offset, length, position, callback)', () => {
it('Simple write to a file descriptor', done => {
Expand Down Expand Up @@ -765,6 +791,10 @@ describe('volume', () => {
if (hasBigInt) {
const stats = vol.lstatSync('/dojo.js', { bigint: true });
expect(typeof stats.ino).toBe('bigint');
expect(typeof stats.atimeNs).toBe('bigint');
expect(typeof stats.mtimeNs).toBe('bigint');
expect(typeof stats.ctimeNs).toBe('bigint');
expect(typeof stats.birthtimeNs).toBe('bigint');
} else {
expect(() => vol.lstatSync('/dojo.js', { bigint: true })).toThrowError();
}
Expand Down Expand Up @@ -796,6 +826,10 @@ describe('volume', () => {
if (hasBigInt) {
const stats = vol.statSync('/dojo.js', { bigint: true });
expect(typeof stats.ino).toBe('bigint');
expect(typeof stats.atimeNs).toBe('bigint');
expect(typeof stats.mtimeNs).toBe('bigint');
expect(typeof stats.ctimeNs).toBe('bigint');
expect(typeof stats.birthtimeNs).toBe('bigint');
} else {
expect(() => vol.statSync('/dojo.js', { bigint: true })).toThrowError();
}
Expand Down Expand Up @@ -827,6 +861,8 @@ describe('volume', () => {
const data = '(function(){})();';
dojo.getNode().setString(data);

vol.symlinkSync('/dojo.js', '/link.js');

it('Returns basic file stats', () => {
const fd = vol.openSync('/dojo.js', 'r');
const stats = vol.fstatSync(fd);
Expand All @@ -840,10 +876,29 @@ describe('volume', () => {
if (hasBigInt) {
const stats = vol.fstatSync(fd, { bigint: true });
expect(typeof stats.ino).toBe('bigint');
expect(typeof stats.atimeNs).toBe('bigint');
expect(typeof stats.mtimeNs).toBe('bigint');
expect(typeof stats.ctimeNs).toBe('bigint');
expect(typeof stats.birthtimeNs).toBe('bigint');
} else {
expect(() => vol.fstatSync(fd, { bigint: true })).toThrowError();
}
});
it('Returns stats about regular file for fd opened without O_SYMLINK', () => {
const fd = vol.openSync('/link.js', 0);
const stats = vol.fstatSync(fd);
expect(stats).toBeInstanceOf(Stats);
expect(stats.size).toBe(data.length);
expect(stats.isFile()).toBe(true);
expect(stats.isDirectory()).toBe(false);
});
it('Returns stats about symlink itself for fd opened with O_SYMLINK', () => {
const fd = vol.openSync('/link.js', O_SYMLINK);
const stats = vol.fstatSync(fd);
expect(stats.isSymbolicLink()).toBe(true);
expect(stats.isFile()).toBe(false);
expect(stats.size).toBe(0);
});
});
describe('.fstat(fd, callback)', () => {
xit('...', () => {});
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/volume/__snapshots__/writeSync.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`.writeSync(fd, buffer, offset, length, position) Write string to file 1`] = `
Object {
{
"/foo": "test",
}
`;
13 changes: 13 additions & 0 deletions src/__tests__/volume/mkdirSync.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { create } from '../util';
import type Stats from '../../Stats';

describe('mkdirSync', () => {
it('can create a directory', () => {
Expand Down Expand Up @@ -50,4 +51,16 @@ describe('mkdirSync', () => {
expect(error).toBeInstanceOf(Error);
expect(error.message).toMatchSnapshot();
});

/**
* See issue #938
* https://github.com/streamich/memfs/issues/938
*/
it('can create a directory with name "__proto__"', () => {
const vol = create();

vol.mkdirSync('/__proto__');

expect(vol.statSync('/__proto__').isDirectory()).toBe(true);
});
});
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const constants = {
O_NOATIME: 262144,
O_NOFOLLOW: 131072,
O_SYNC: 1052672,
O_SYMLINK: 2097152,
O_DIRECT: 16384,
O_NONBLOCK: 2048,
S_IRWXU: 448,
Expand Down
Loading

0 comments on commit cfbc6d2

Please sign in to comment.