diff --git a/cli/standalone/virtual_fs.rs b/cli/standalone/virtual_fs.rs index d1084f016c..be7e937ee1 100644 --- a/cli/standalone/virtual_fs.rs +++ b/cli/standalone/virtual_fs.rs @@ -634,7 +634,7 @@ impl FileBackedVfsFile { } fn read_to_buf(&self, buf: &mut [u8]) -> FsResult { - let pos = { + let read_pos = { let mut pos = self.pos.lock(); let read_pos = *pos; // advance the position due to the read @@ -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> { - 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? @@ -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) } } @@ -893,8 +893,9 @@ impl FileBackedVfs { buf: &mut [u8], ) -> std::io::Result { 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( @@ -903,15 +904,15 @@ impl FileBackedVfs { pos: u64, len: u64, ) -> std::io::Result> { - 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) } diff --git a/tests/specs/compile/include/buffered_reads/__test__.jsonc b/tests/specs/compile/include/buffered_reads/__test__.jsonc new file mode 100644 index 0000000000..7640fed56b --- /dev/null +++ b/tests/specs/compile/include/buffered_reads/__test__.jsonc @@ -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 + }] +} diff --git a/tests/specs/compile/include/buffered_reads/main.ts b/tests/specs/compile/include/buffered_reads/main.ts new file mode 100644 index 0000000000..7f78eab612 --- /dev/null +++ b/tests/specs/compile/include/buffered_reads/main.ts @@ -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."); + } + } +} diff --git a/tests/specs/compile/include/buffered_reads/setup.js b/tests/specs/compile/include/buffered_reads/setup.js new file mode 100644 index 0000000000..39cd5cb8b0 --- /dev/null +++ b/tests/specs/compile/include/buffered_reads/setup.js @@ -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); diff --git a/tests/specs/compile/include_data_files/__test__.jsonc b/tests/specs/compile/include/data_files/__test__.jsonc similarity index 100% rename from tests/specs/compile/include_data_files/__test__.jsonc rename to tests/specs/compile/include/data_files/__test__.jsonc diff --git a/tests/specs/compile/include_data_files/data-file.txt b/tests/specs/compile/include/data_files/data-file.txt similarity index 100% rename from tests/specs/compile/include_data_files/data-file.txt rename to tests/specs/compile/include/data_files/data-file.txt diff --git a/tests/specs/compile/include_data_files/main.js b/tests/specs/compile/include/data_files/main.js similarity index 100% rename from tests/specs/compile/include_data_files/main.js rename to tests/specs/compile/include/data_files/main.js diff --git a/tests/specs/compile/include_data_files/non_existent.out b/tests/specs/compile/include/data_files/non_existent.out similarity index 100% rename from tests/specs/compile/include_data_files/non_existent.out rename to tests/specs/compile/include/data_files/non_existent.out diff --git a/tests/specs/compile/include_data_files/output.out b/tests/specs/compile/include/data_files/output.out similarity index 100% rename from tests/specs/compile/include_data_files/output.out rename to tests/specs/compile/include/data_files/output.out diff --git a/tests/specs/compile/include_folder/__test__.jsonc b/tests/specs/compile/include/folder/__test__.jsonc similarity index 100% rename from tests/specs/compile/include_folder/__test__.jsonc rename to tests/specs/compile/include/folder/__test__.jsonc diff --git a/tests/specs/compile/include_folder/data/a.txt b/tests/specs/compile/include/folder/data/a.txt similarity index 100% rename from tests/specs/compile/include_folder/data/a.txt rename to tests/specs/compile/include/folder/data/a.txt diff --git a/tests/specs/compile/include_folder/data/b.txt b/tests/specs/compile/include/folder/data/b.txt similarity index 100% rename from tests/specs/compile/include_folder/data/b.txt rename to tests/specs/compile/include/folder/data/b.txt diff --git a/tests/specs/compile/include_folder/main.js b/tests/specs/compile/include/folder/main.js similarity index 100% rename from tests/specs/compile/include_folder/main.js rename to tests/specs/compile/include/folder/main.js diff --git a/tests/specs/compile/include_folder/output.out b/tests/specs/compile/include/folder/output.out similarity index 100% rename from tests/specs/compile/include_folder/output.out rename to tests/specs/compile/include/folder/output.out