node/test/parallel/test-fileurltopathbuffer.js
James M Snell 3f6ad56846 url: add fileURLToPathBuffer API
The existing `fileURLToPath()` does not handle the case
where the input URL contains percent-encoded characters
that are not valid UTF-8 sequences. This can lead to
issues, for instance, when the URL is constructed
using file names in non-Unicode encodings (like
Shift-JIS). This commit introduces a new API,
`fileURLToPathBuffer()`, which returns a `Buffer`
representing the path, allowing for accurate
conversion of file URLs to paths without attempting
to decode the percent-encoded bytes into characters.

PR-URL: https://github.com/nodejs/node/pull/58700
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
Reviewed-By: LiviaMedeiros <livia@cirno.name>
2025-06-14 14:06:04 -07:00

72 lines
1.9 KiB
JavaScript

'use strict';
const common = require('../common');
// This test does not work on OSX due to the way it handles
// non-Unicode sequences in file names.
if (common.isMacOS) {
common.skip('Test unsupported on OSX');
}
// Unfortunately, the test also does not work on Windows
// because the writeFileSync operation will replace the
// non-Unicode characters with replacement characters when
// it normalizes the path.
if (common.isWindows) {
common.skip('Test unsupported on Windows');
}
const tmpdir = require('../common/tmpdir');
const {
existsSync,
writeFileSync,
} = require('node:fs');
const {
ok,
throws,
} = require('node:assert');
const {
sep,
} = require('node:path');
tmpdir.refresh();
const {
pathToFileURL,
fileURLToPath,
fileURLToPathBuffer,
} = require('node:url');
const kShiftJisName = '%82%A0%82%A2%82%A4';
const kShiftJisBuffer = Buffer.from([0x82, 0xA0, 0x82, 0xA2, 0x82, 0xA4]);
const tmpdirUrl = pathToFileURL(tmpdir.path + sep);
const testPath = new URL(kShiftJisName, tmpdirUrl);
ok(testPath.pathname.endsWith(`/${kShiftJisName}`));
const tmpdirBuffer = Buffer.from(tmpdir.path + sep, 'utf8');
const testPathBuffer = Buffer.concat([tmpdirBuffer, kShiftJisBuffer]);
// We can use the Buffer version of the path to create a file and check
// its existence. But we cannot use the URL version because it contains
// non-Unicode percent-encoded characters.
throws(() => writeFileSync(testPath, 'test'), {
name: 'URIError',
});
writeFileSync(testPathBuffer, 'test');
ok(existsSync(testPathBuffer));
// Using fileURLToPath fails because the URL contains non-Unicode
// percent-encoded characters.
throws(() => existsSync(fileURLToPath(testPath)), {
name: 'URIError',
});
// This variation succeeds because the URL is converted to a buffer
// without trying to interpret the percent-encoded characters.
ok(existsSync(fileURLToPathBuffer(testPath)));