Skip to content

Commit 5a52962

Browse files
committed
fix(fs): fix writeFile and writeTextFile converting UTF-8 characters in path into replacement character
closes #1849
1 parent 525abc4 commit 5a52962

File tree

4 files changed

+169
-15
lines changed

4 files changed

+169
-15
lines changed

.changes/fs-path-utf8.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"fs": "patch"
3+
"fs-js": "patch"
4+
---
5+
6+
Fix `writeFile` and `writeTextFile` converting UTF-8 characters (for example `äöü`) in the given path into replacement character (``)

plugins/fs/api-iife.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

plugins/fs/guest-js/index.ts

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,9 +1040,21 @@ async function writeFile(
10401040
throw new TypeError('Must be a file URL.')
10411041
}
10421042

1043-
await invoke('plugin:fs|write_file', data, {
1043+
// because headers only allows ISO-8859-1 strings, characters like `äöü` are not allowed
1044+
// so we encode them into bytes and append them at the end of the data to be written
1045+
// then we can only send the path bytes length in the headers
1046+
// and on rust we split the data into two parts, data and path
1047+
// and decode path into a valid `std::ffi::OsString`
1048+
const pathStr = path instanceof URL ? path.toString() : path
1049+
const pathBytes = new TextEncoder().encode(pathStr)
1050+
1051+
const bytes = new Uint8Array(data.byteLength + pathBytes.byteLength)
1052+
bytes.set(data)
1053+
bytes.set(pathBytes, data.byteLength)
1054+
1055+
await invoke('plugin:fs|write_file', bytes, {
10441056
headers: {
1045-
path: encodeURIComponent(path instanceof URL ? path.toString() : path),
1057+
path: pathBytes.byteLength.toString(),
10461058
options: JSON.stringify(options)
10471059
}
10481060
})
@@ -1070,9 +1082,23 @@ async function writeTextFile(
10701082

10711083
const encoder = new TextEncoder()
10721084

1073-
await invoke('plugin:fs|write_text_file', encoder.encode(data), {
1085+
const textData = encoder.encode(data)
1086+
1087+
// because headers only allows ISO-8859-1 strings, characters like `äöü` are not allowed
1088+
// so we encode them into bytes and append them at the end of the data to be written
1089+
// then we can only send the path bytes length in the headers
1090+
// and on rust we split the data into two parts, data and path
1091+
// and decode path into a valid `std::ffi::OsString`
1092+
const pathStr = path instanceof URL ? path.toString() : path
1093+
const pathBytes = encoder.encode(pathStr)
1094+
1095+
const bytes = new Uint8Array(textData.byteLength + pathBytes.byteLength)
1096+
bytes.set(textData)
1097+
bytes.set(pathBytes, textData.byteLength)
1098+
1099+
await invoke('plugin:fs|write_text_file', bytes, {
10741100
headers: {
1075-
path: path instanceof URL ? path.toString() : path,
1101+
path: pathBytes.byteLength.toString(),
10761102
options: JSON.stringify(options)
10771103
}
10781104
})

0 commit comments

Comments
 (0)