1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-24 15:19:26 -05:00

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

Closes #27006
This commit is contained in:
David Sherret 2024-11-22 14:26:38 -05:00 committed by GitHub
parent 9c0e6369b2
commit 4ded7519e9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 104 additions and 12 deletions

View file

@ -634,7 +634,7 @@ impl FileBackedVfsFile {
} }
fn read_to_buf(&self, buf: &mut [u8]) -> FsResult<usize> { fn read_to_buf(&self, buf: &mut [u8]) -> FsResult<usize> {
let pos = { let read_pos = {
let mut pos = self.pos.lock(); let mut pos = self.pos.lock();
let read_pos = *pos; let read_pos = *pos;
// advance the position due to the read // advance the position due to the read
@ -643,12 +643,12 @@ impl FileBackedVfsFile {
}; };
self self
.vfs .vfs
.read_file(&self.file, pos, buf) .read_file(&self.file, read_pos, buf)
.map_err(|err| err.into()) .map_err(|err| err.into())
} }
fn read_to_end(&self) -> FsResult<Vec<u8>> { fn read_to_end(&self) -> FsResult<Vec<u8>> {
let pos = { let read_pos = {
let mut pos = self.pos.lock(); let mut pos = self.pos.lock();
let read_pos = *pos; let read_pos = *pos;
// todo(dsherret): should this always set it to the end of the file? // todo(dsherret): should this always set it to the end of the file?
@ -658,12 +658,12 @@ impl FileBackedVfsFile {
} }
read_pos read_pos
}; };
if pos > self.file.len { if read_pos > self.file.len {
return Ok(Vec::new()); 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]; 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) Ok(buf)
} }
} }
@ -893,8 +893,9 @@ impl FileBackedVfs {
buf: &mut [u8], buf: &mut [u8],
) -> std::io::Result<usize> { ) -> std::io::Result<usize> {
let read_range = self.get_read_range(file, pos, buf.len() as u64)?; let read_range = self.get_read_range(file, pos, buf.len() as u64)?;
buf.copy_from_slice(&self.vfs_data[read_range]); let read_len = read_range.len();
Ok(buf.len()) buf[..read_len].copy_from_slice(&self.vfs_data[read_range]);
Ok(read_len)
} }
fn get_read_range( fn get_read_range(
@ -903,15 +904,15 @@ impl FileBackedVfs {
pos: u64, pos: u64,
len: u64, len: u64,
) -> std::io::Result<Range<usize>> { ) -> std::io::Result<Range<usize>> {
let data = &self.vfs_data; if pos > file.len {
let start = self.fs_root.start_file_offset + file.offset + pos;
let end = start + len;
if end > data.len() as u64 {
return Err(std::io::Error::new( return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof, std::io::ErrorKind::UnexpectedEof,
"unexpected EOF", "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) Ok(start as usize..end as usize)
} }

View file

@ -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
}]
}

View file

@ -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.");
}
}
}

View file

@ -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);