mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 18:25:13 +08:00
On a mounted VFS, `readlink()`, `realpath()` and `mkdtemp()` only
returned a Buffer for `{ encoding: 'buffer' }`. The string form
`'buffer'`, any other encoding, and a Buffer `mkdtemp()` prefix were
ignored. The `VirtualFileSystem` `readlink` and `realpath` methods
ignored the encoding with `MemoryProvider` and passed it on to
`RealFSProvider`, which threw `ERR_INVALID_ARG_TYPE` for `'buffer'`,
while for other encodings `realpath()` failed and `readlink()`
returned the host path of absolute targets.
Get these paths from the provider as strings and apply the encoding
to the result, normalizing the options with `getOptions()` and
converting with `encodeRealpathResult()` as `fs` does. The latter
moves to `internal/fs/utils` so the VFS can use it.
Signed-off-by: Christian Aurich Zanettini Martins <christian.aurichzm@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66352
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
105 lines
3.3 KiB
JavaScript
105 lines
3.3 KiB
JavaScript
// Flags: --disable-warning=ExperimentalWarning
|
|
'use strict';
|
|
|
|
// readlink(), realpath() and mkdtemp() on a mounted VFS apply the encoding
|
|
// option the way fs does: given as a string or in an object, 'buffer' or any
|
|
// other encoding, and a Buffer mkdtemp() prefix always gives a Buffer. The
|
|
// VirtualFileSystem readlink and realpath methods do the same.
|
|
|
|
const common = require('../common');
|
|
const assert = require('assert');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const { promisify } = require('util');
|
|
const vfs = require('node:vfs');
|
|
const tmpdir = require('../common/tmpdir');
|
|
|
|
function decode(value, encoding) {
|
|
if (encoding === 'buffer') {
|
|
assert.ok(Buffer.isBuffer(value));
|
|
return value.toString();
|
|
}
|
|
assert.strictEqual(typeof value, 'string');
|
|
return Buffer.from(value, encoding).toString();
|
|
}
|
|
|
|
const memoryVfs = vfs.create();
|
|
memoryVfs.writeFileSync('/file.txt', 'x');
|
|
memoryVfs.symlinkSync('file.txt', '/link');
|
|
memoryVfs.symlinkSync('/file.txt', '/abs-link');
|
|
const vfsInstances = [memoryVfs];
|
|
|
|
if (common.canCreateSymLink()) {
|
|
tmpdir.refresh();
|
|
fs.writeFileSync(tmpdir.resolve('file.txt'), 'x');
|
|
fs.symlinkSync('file.txt', tmpdir.resolve('link'));
|
|
// RealFSProvider returns an absolute target inside its root as a VFS path.
|
|
fs.symlinkSync(tmpdir.resolve('file.txt'), tmpdir.resolve('abs-link'));
|
|
vfsInstances.push(vfs.create(new vfs.RealFSProvider(tmpdir.path)));
|
|
}
|
|
|
|
const readlinks = [
|
|
fs.readlinkSync,
|
|
promisify(fs.readlink),
|
|
fs.promises.readlink,
|
|
];
|
|
const realpaths = [
|
|
fs.realpathSync,
|
|
fs.realpathSync.native,
|
|
promisify(fs.realpath),
|
|
promisify(fs.realpath.native),
|
|
fs.promises.realpath,
|
|
];
|
|
const mkdtemps = [
|
|
fs.mkdtempSync,
|
|
promisify(fs.mkdtemp),
|
|
fs.promises.mkdtemp,
|
|
];
|
|
|
|
(async () => {
|
|
for (const myVfs of vfsInstances) {
|
|
const mountPoint = myVfs.mount();
|
|
const prefix = path.join(mountPoint, 'tmp-');
|
|
const vfsReadlinks = [
|
|
myVfs.readlinkSync.bind(myVfs),
|
|
promisify(myVfs.readlink.bind(myVfs)),
|
|
myVfs.promises.readlink,
|
|
];
|
|
const vfsRealpaths = [
|
|
myVfs.realpathSync.bind(myVfs),
|
|
promisify(myVfs.realpath.bind(myVfs)),
|
|
myVfs.promises.realpath,
|
|
];
|
|
|
|
for (const options of ['buffer', { encoding: 'buffer' }, 'hex', { encoding: 'hex' }]) {
|
|
const encoding = options.encoding ?? options;
|
|
|
|
for (const name of ['link', 'abs-link']) {
|
|
const link = path.join(mountPoint, name);
|
|
for (const readlink of [...readlinks, ...vfsReadlinks]) {
|
|
assert.strictEqual(decode(await readlink(link, options), encoding),
|
|
fs.readlinkSync(link));
|
|
}
|
|
for (const realpath of [...realpaths, ...vfsRealpaths]) {
|
|
assert.strictEqual(decode(await realpath(link, options), encoding),
|
|
fs.realpathSync(link));
|
|
}
|
|
}
|
|
|
|
for (const mkdtemp of mkdtemps) {
|
|
const dir = decode(await mkdtemp(prefix, options), encoding);
|
|
assert.ok(dir.startsWith(prefix));
|
|
assert.ok(fs.statSync(dir).isDirectory());
|
|
}
|
|
}
|
|
|
|
for (const mkdtemp of mkdtemps) {
|
|
const dir = await mkdtemp(Buffer.from(prefix), 'hex');
|
|
assert.ok(Buffer.isBuffer(dir));
|
|
assert.ok(fs.statSync(dir).isDirectory());
|
|
}
|
|
|
|
myVfs.unmount();
|
|
}
|
|
})().then(common.mustCall());
|