Compare commits

...

1 Commits

Author SHA1 Message Date
Jarred Sumner
2009a1ee56 test: add fs.writeSync optional params test and fix 2025-05-28 20:26:55 -07:00
2 changed files with 119 additions and 1 deletions

View File

@@ -562,7 +562,23 @@ var access = function access(path, mode, callback) {
return fs.readSync(fd, buffer, offset, length, position);
},
writeSync = fs.writeSync.bind(fs),
writeSync = function writeSync(fd, buffer, offsetOrOptions, length, position) {
if ($isTypedArrayView(buffer)) {
let offset = offsetOrOptions;
if (arguments.length <= 3 || typeof offsetOrOptions === "object") {
if (offsetOrOptions !== undefined) {
if (typeof offsetOrOptions !== "object" || $isArray(offsetOrOptions)) {
throw $ERR_INVALID_ARG_TYPE("options", "object", offsetOrOptions);
}
}
({ offset = 0, length = buffer.byteLength - offset, position = null } = offsetOrOptions ?? {});
}
return fs.writeSync(fd, buffer, offset, length, position);
}
return fs.writeSync(fd, buffer, offsetOrOptions, length);
},
readdirSync = fs.readdirSync.bind(fs),
readFileSync = fs.readFileSync.bind(fs),
fdatasyncSync = fs.fdatasyncSync.bind(fs),

View File

@@ -0,0 +1,102 @@
const common = require('../common');
// This test ensures that fs.writeSync accepts "named parameters" object
// and doesn't interpret objects as strings
const assert = require('assert');
const fs = require('fs');
const tmpdir = require('../common/tmpdir');
tmpdir.refresh();
const dest = tmpdir.resolve('tmp.txt');
const buffer = Buffer.from('zyx');
function testInvalid(dest, expectedCode, ...bufferAndOptions) {
if (bufferAndOptions.length >= 2) {
bufferAndOptions[1] = common.mustNotMutateObjectDeep(bufferAndOptions[1]);
}
let fd;
try {
fd = fs.openSync(dest, 'w+');
assert.throws(
() => fs.writeSync(fd, ...bufferAndOptions),
{ code: expectedCode });
} finally {
if (fd != null) fs.closeSync(fd);
}
}
function testValid(dest, buffer, options) {
const length = options?.length;
let fd, bytesWritten, bytesRead;
try {
fd = fs.openSync(dest, 'w');
bytesWritten = fs.writeSync(fd, buffer, options);
} finally {
if (fd != null) fs.closeSync(fd);
}
try {
fd = fs.openSync(dest, 'r');
bytesRead = fs.readSync(fd, buffer, options);
} finally {
if (fd != null) fs.closeSync(fd);
}
assert.ok(bytesWritten >= bytesRead);
if (length !== undefined && length !== null) {
assert.strictEqual(bytesWritten, length);
assert.strictEqual(bytesRead, length);
}
}
{
// Test if second argument is not wrongly interpreted as string or options
for (const badBuffer of [
undefined, null, true, 42, 42n, Symbol('42'), NaN, [], () => {},
common.mustNotCall(),
common.mustNotMutateObjectDeep({}),
{},
{ buffer: 'amNotParam' },
{ string: 'amNotParam' },
{ buffer: new Uint8Array(1) },
{ buffer: new Uint8Array(1).buffer },
Promise.resolve(new Uint8Array(1)),
new Date(),
new String('notPrimitive'),
{ toString() { return 'amObject'; } },
{ [Symbol.toPrimitive]: (hint) => 'amObject' },
]) {
testInvalid(dest, 'ERR_INVALID_ARG_TYPE', common.mustNotMutateObjectDeep(badBuffer));
}
// First argument (buffer or string) is mandatory
testInvalid(dest, 'ERR_INVALID_ARG_TYPE');
// Various invalid options
testInvalid(dest, 'ERR_OUT_OF_RANGE', buffer, { length: 5 });
testInvalid(dest, 'ERR_OUT_OF_RANGE', buffer, { offset: 5 });
testInvalid(dest, 'ERR_OUT_OF_RANGE', buffer, { length: 1, offset: 3 });
testInvalid(dest, 'ERR_OUT_OF_RANGE', buffer, { length: -1 });
testInvalid(dest, 'ERR_OUT_OF_RANGE', buffer, { offset: -1 });
testInvalid(dest, 'ERR_INVALID_ARG_TYPE', buffer, { offset: false });
testInvalid(dest, 'ERR_INVALID_ARG_TYPE', buffer, { offset: true });
// Test compatibility with fs.readSync counterpart with reused options
for (const options of [
undefined,
null,
{},
{ length: 1 },
{ position: 5 },
{ length: 1, position: 5 },
{ length: 1, position: -1, offset: 2 },
{ length: null },
{ position: null },
{ offset: 1 },
]) {
testValid(dest, buffer, common.mustNotMutateObjectDeep(options));
}
}