Problem
1. WriteFile binary decode
FileSystem.WriteFile accepts file content as either a Value::Array of u64 integers or a base64 Value::String. The array path iterates every element with v.as_u64().map(|n| n as u8) — an enum-variant match per byte. For a 50 KB file this is 50,000 matches. For a 200 KB binary (e.g., .wasm written to workspace storage by an extension) this is 200,000 matches. The filter_map also silently drops elements that fail as_u64(), including negative values that TypeScript serializers can produce for bytes >127 via signed Int8Array, causing silent data corruption.
File: Source/Track/Effect/CreateEffectForRequest/FileSystem.rs
2. Empty-path guard duplication
The empty-path if path_str.is_empty() { return Err(...) } guard is copy-pasted identically across ReadFile, WriteFile, ReadDirectory, and Stat with four slightly different error strings. In Stat the guard fires after run_time.Environment.Require() whereas in ReadFile it fires before — inconsistent ordering.
Fix
- Remove the
Value::Array decode path from WriteFile. Require base64 Value::String as the sole accepted encoding. Return a clear error if an array is passed: "FileSystem.WriteFile: content must be base64-encoded string, not byte array".
- Extract the empty-path guard to a private inline helper:
#[inline]
fn require_non_empty_path(method: &str, path: &str) -> Result<(), String> {
if path.is_empty() {
Err(format!("{}: empty path (resource not found)", method))
} else {
Ok(())
}
}
- Standardize ordering: validate path before
run_time.Environment.Require() in all four handlers.
Additional Scope for Same PR
- Add a comment on the
vscode://schemas-associations/ special-case in ReadFile referencing the VS Code schema service, so future maintainers understand the origin of this hard-coded prefix.
- Log a follow-up issue: cache
FileSystemReader/FileSystemWriter as typed fields on ApplicationRunTime to eliminate the per-call Environment.Require() hash lookup.
Problem
1. WriteFile binary decode
FileSystem.WriteFileaccepts file content as either aValue::Arrayof u64 integers or a base64Value::String. The array path iterates every element withv.as_u64().map(|n| n as u8)— an enum-variant match per byte. For a 50 KB file this is 50,000 matches. For a 200 KB binary (e.g.,.wasmwritten to workspace storage by an extension) this is 200,000 matches. Thefilter_mapalso silently drops elements that failas_u64(), including negative values that TypeScript serializers can produce for bytes >127 via signedInt8Array, causing silent data corruption.File:
Source/Track/Effect/CreateEffectForRequest/FileSystem.rs2. Empty-path guard duplication
The empty-path
if path_str.is_empty() { return Err(...) }guard is copy-pasted identically acrossReadFile,WriteFile,ReadDirectory, andStatwith four slightly different error strings. InStatthe guard fires afterrun_time.Environment.Require()whereas inReadFileit fires before — inconsistent ordering.Fix
Value::Arraydecode path fromWriteFile. Require base64Value::Stringas the sole accepted encoding. Return a clear error if an array is passed:"FileSystem.WriteFile: content must be base64-encoded string, not byte array".run_time.Environment.Require()in all four handlers.Additional Scope for Same PR
vscode://schemas-associations/special-case inReadFilereferencing the VS Code schema service, so future maintainers understand the origin of this hard-coded prefix.FileSystemReader/FileSystemWriteras typed fields onApplicationRunTimeto eliminate the per-callEnvironment.Require()hash lookup.