Skip to content

Commit 4ded751

Browse files
authored
fix(compile): correct buffered reading of assets and files (#27008)
Closes #27006
1 parent 9c0e636 commit 4ded751

File tree

14 files changed

+104
-12
lines changed

14 files changed

+104
-12
lines changed

cli/standalone/virtual_fs.rs

+13-12
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,7 @@ impl FileBackedVfsFile {
634634
}
635635

636636
fn read_to_buf(&self, buf: &mut [u8]) -> FsResult<usize> {
637-
let pos = {
637+
let read_pos = {
638638
let mut pos = self.pos.lock();
639639
let read_pos = *pos;
640640
// advance the position due to the read
@@ -643,12 +643,12 @@ impl FileBackedVfsFile {
643643
};
644644
self
645645
.vfs
646-
.read_file(&self.file, pos, buf)
646+
.read_file(&self.file, read_pos, buf)
647647
.map_err(|err| err.into())
648648
}
649649

650650
fn read_to_end(&self) -> FsResult<Vec<u8>> {
651-
let pos = {
651+
let read_pos = {
652652
let mut pos = self.pos.lock();
653653
let read_pos = *pos;
654654
// todo(dsherret): should this always set it to the end of the file?
@@ -658,12 +658,12 @@ impl FileBackedVfsFile {
658658
}
659659
read_pos
660660
};
661-
if pos > self.file.len {
661+
if read_pos > self.file.len {
662662
return Ok(Vec::new());
663663
}
664-
let size = (self.file.len - pos) as usize;
664+
let size = (self.file.len - read_pos) as usize;
665665
let mut buf = vec![0; size];
666-
self.vfs.read_file(&self.file, pos, &mut buf)?;
666+
self.vfs.read_file(&self.file, read_pos, &mut buf)?;
667667
Ok(buf)
668668
}
669669
}
@@ -893,8 +893,9 @@ impl FileBackedVfs {
893893
buf: &mut [u8],
894894
) -> std::io::Result<usize> {
895895
let read_range = self.get_read_range(file, pos, buf.len() as u64)?;
896-
buf.copy_from_slice(&self.vfs_data[read_range]);
897-
Ok(buf.len())
896+
let read_len = read_range.len();
897+
buf[..read_len].copy_from_slice(&self.vfs_data[read_range]);
898+
Ok(read_len)
898899
}
899900

900901
fn get_read_range(
@@ -903,15 +904,15 @@ impl FileBackedVfs {
903904
pos: u64,
904905
len: u64,
905906
) -> std::io::Result<Range<usize>> {
906-
let data = &self.vfs_data;
907-
let start = self.fs_root.start_file_offset + file.offset + pos;
908-
let end = start + len;
909-
if end > data.len() as u64 {
907+
if pos > file.len {
910908
return Err(std::io::Error::new(
911909
std::io::ErrorKind::UnexpectedEof,
912910
"unexpected EOF",
913911
));
914912
}
913+
let file_offset = self.fs_root.start_file_offset + file.offset;
914+
let start = file_offset + pos;
915+
let end = file_offset + std::cmp::min(pos + len, file.len);
915916
Ok(start as usize..end as usize)
916917
}
917918

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"tempDir": true,
3+
"steps": [{
4+
"args": "run -A setup.js",
5+
"output": "[WILDCARD]"
6+
}, {
7+
"if": "unix",
8+
"args": "compile --allow-read=data --include data --output main main.ts",
9+
"output": "[WILDCARD]"
10+
}, {
11+
"if": "unix",
12+
"commandName": "./main",
13+
"args": [],
14+
"output": "[WILDCARD]",
15+
"exitCode": 0
16+
}, {
17+
"if": "windows",
18+
"args": "compile --allow-read=data --include data --output main.exe main.ts",
19+
"output": "[WILDCARD]"
20+
}, {
21+
"if": "windows",
22+
"commandName": "./main.exe",
23+
"args": [],
24+
"output": "[WILDCARD]",
25+
"exitCode": 0
26+
}]
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// buffer larger than file
2+
{
3+
using file = Deno.openSync(import.meta.dirname + "/data/1.txt");
4+
const data = new Uint8Array(13);
5+
const len = file.readSync(data);
6+
if (len !== 13) {
7+
throw new Error("Unexpected read length");
8+
}
9+
if (file.readSync(new Uint8Array(1024)) !== null) {
10+
throw new Error("Unexpected.");
11+
}
12+
const textData = new TextDecoder().decode(data);
13+
if (textData !== "Hello, world!") {
14+
throw new Error("Unexpected file data (1): " + textData);
15+
}
16+
}
17+
18+
// buffer smaller than file
19+
{
20+
using file = Deno.openSync(import.meta.dirname + "/data/1.txt");
21+
const finalData = new Uint8Array(13);
22+
const data = new Uint8Array(2);
23+
let pos = 0;
24+
while (true) {
25+
const len = file.readSync(data);
26+
if (len === 0 || len == null) {
27+
break;
28+
}
29+
finalData.set(data.subarray(0, len), pos);
30+
pos += len;
31+
}
32+
const textData = new TextDecoder().decode(finalData);
33+
if (textData !== "Hello, world!") {
34+
throw new Error("Unexpected file data (2): " + textData);
35+
}
36+
}
37+
38+
// large amount of data, small reads
39+
{
40+
const bytes = new Uint8Array((1024 ** 2) * 20);
41+
using file = Deno.openSync(import.meta.dirname + "/data/2.dat");
42+
const buffer = new Uint8Array(2);
43+
let pos = 0;
44+
while (true) {
45+
const len = file.readSync(buffer);
46+
if (len === 0 || len == null) {
47+
break;
48+
}
49+
bytes.set(buffer.subarray(0, len), pos);
50+
pos += len;
51+
}
52+
for (let i = 0; i < bytes.length; i++) {
53+
if (bytes[i] !== i % 256) {
54+
throw new Error("Unexpected data.");
55+
}
56+
}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Deno.mkdirSync("data");
2+
Deno.writeTextFileSync("data/1.txt", "Hello, world!");
3+
const bytes = new Uint8Array((1024 ** 2) * 20);
4+
for (let i = 0; i < bytes.length; i++) {
5+
bytes[i] = i % 256;
6+
}
7+
Deno.writeFileSync("data/2.dat", bytes);

0 commit comments

Comments
 (0)