Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(compile): correct buffered reading of assets and files #27008

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions cli/standalone/virtual_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,7 @@ impl FileBackedVfsFile {
}

fn read_to_buf(&self, buf: &mut [u8]) -> FsResult<usize> {
let pos = {
let read_pos = {
let mut pos = self.pos.lock();
let read_pos = *pos;
// advance the position due to the read
Expand All @@ -643,12 +643,12 @@ impl FileBackedVfsFile {
};
self
.vfs
.read_file(&self.file, pos, buf)
.read_file(&self.file, read_pos, buf)
.map_err(|err| err.into())
}

fn read_to_end(&self) -> FsResult<Vec<u8>> {
let pos = {
let read_pos = {
let mut pos = self.pos.lock();
let read_pos = *pos;
// todo(dsherret): should this always set it to the end of the file?
Expand All @@ -658,12 +658,12 @@ impl FileBackedVfsFile {
}
read_pos
};
if pos > self.file.len {
if read_pos > self.file.len {
return Ok(Vec::new());
}
let size = (self.file.len - pos) as usize;
let size = (self.file.len - read_pos) as usize;
let mut buf = vec![0; size];
self.vfs.read_file(&self.file, pos, &mut buf)?;
self.vfs.read_file(&self.file, read_pos, &mut buf)?;
Ok(buf)
}
}
Expand Down Expand Up @@ -893,8 +893,9 @@ impl FileBackedVfs {
buf: &mut [u8],
) -> std::io::Result<usize> {
let read_range = self.get_read_range(file, pos, buf.len() as u64)?;
buf.copy_from_slice(&self.vfs_data[read_range]);
Ok(buf.len())
let read_len = read_range.len();
buf[..read_len].copy_from_slice(&self.vfs_data[read_range]);
Ok(read_len)
}

fn get_read_range(
Expand All @@ -903,15 +904,15 @@ impl FileBackedVfs {
pos: u64,
len: u64,
) -> std::io::Result<Range<usize>> {
let data = &self.vfs_data;
let start = self.fs_root.start_file_offset + file.offset + pos;
let end = start + len;
if end > data.len() as u64 {
if pos > file.len {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"unexpected EOF",
));
}
let file_offset = self.fs_root.start_file_offset + file.offset;
let start = file_offset + pos;
let end = file_offset + std::cmp::min(pos + len, file.len);
Ok(start as usize..end as usize)
}

Expand Down
27 changes: 27 additions & 0 deletions tests/specs/compile/include/buffered_reads/__test__.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"tempDir": true,
"steps": [{
"args": "run -A setup.js",
"output": "[WILDCARD]"
}, {
"if": "unix",
"args": "compile --allow-read=data --include data --output main main.ts",
"output": "[WILDCARD]"
}, {
"if": "unix",
"commandName": "./main",
"args": [],
"output": "[WILDCARD]",
"exitCode": 0
}, {
"if": "windows",
"args": "compile --allow-read=data --include data --output main.exe main.ts",
"output": "[WILDCARD]"
}, {
"if": "windows",
"commandName": "./main.exe",
"args": [],
"output": "[WILDCARD]",
"exitCode": 0
}]
}
57 changes: 57 additions & 0 deletions tests/specs/compile/include/buffered_reads/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// buffer larger than file
{
using file = Deno.openSync(import.meta.dirname + "/data/1.txt");
const data = new Uint8Array(13);
const len = file.readSync(data);
if (len !== 13) {
throw new Error("Unexpected read length");
}
if (file.readSync(new Uint8Array(1024)) !== null) {
throw new Error("Unexpected.");
}
const textData = new TextDecoder().decode(data);
if (textData !== "Hello, world!") {
throw new Error("Unexpected file data (1): " + textData);
}
}

// buffer smaller than file
{
using file = Deno.openSync(import.meta.dirname + "/data/1.txt");
const finalData = new Uint8Array(13);
const data = new Uint8Array(2);
let pos = 0;
while (true) {
const len = file.readSync(data);
if (len === 0 || len == null) {
break;
}
finalData.set(data.subarray(0, len), pos);
pos += len;
}
const textData = new TextDecoder().decode(finalData);
if (textData !== "Hello, world!") {
throw new Error("Unexpected file data (2): " + textData);
}
}

// large amount of data, small reads
{
const bytes = new Uint8Array((1024 ** 2) * 20);
using file = Deno.openSync(import.meta.dirname + "/data/2.dat");
const buffer = new Uint8Array(2);
let pos = 0;
while (true) {
const len = file.readSync(buffer);
if (len === 0 || len == null) {
break;
}
bytes.set(buffer.subarray(0, len), pos);
pos += len;
}
for (let i = 0; i < bytes.length; i++) {
if (bytes[i] !== i % 256) {
throw new Error("Unexpected data.");
}
}
}
7 changes: 7 additions & 0 deletions tests/specs/compile/include/buffered_reads/setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Deno.mkdirSync("data");
Deno.writeTextFileSync("data/1.txt", "Hello, world!");
const bytes = new Uint8Array((1024 ** 2) * 20);
for (let i = 0; i < bytes.length; i++) {
bytes[i] = i % 256;
}
Deno.writeFileSync("data/2.dat", bytes);