@tishlang/tish 2.0.3 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/tish +0 -0
- package/crates/tish/Cargo.toml +1 -1
- package/crates/tish/tests/fixtures/read_file_bytes.tish +10 -0
- package/crates/tish/tests/fs_read_file_bytes.rs +45 -0
- package/crates/tish_compile/src/codegen.rs +2 -1
- package/crates/tish_eval/src/eval.rs +4 -0
- package/crates/tish_eval/src/natives.rs +16 -0
- package/crates/tish_runtime/src/lib.rs +17 -0
- package/crates/tish_vm/src/vm.rs +3 -0
- package/package.json +1 -1
- package/platform/darwin-arm64/tish +0 -0
- package/platform/darwin-x64/tish +0 -0
- package/platform/linux-arm64/tish +0 -0
- package/platform/linux-x64/tish +0 -0
- package/platform/win32-x64/tish.exe +0 -0
package/bin/tish
CHANGED
|
Binary file
|
package/crates/tish/Cargo.toml
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Fixture for issue #120: read a binary file as a byte array via tish:fs.readFileBytes.
|
|
2
|
+
// The test points RFB_FIXTURE at a file containing non-UTF-8 bytes (NUL, 0xFF, …).
|
|
3
|
+
import { readFileBytes } from "tish:fs"
|
|
4
|
+
import { process } from "tish:process"
|
|
5
|
+
|
|
6
|
+
let path = process.env.RFB_FIXTURE
|
|
7
|
+
let b = readFileBytes(path)
|
|
8
|
+
console.log("isArray:" + String(Array.isArray(b)))
|
|
9
|
+
console.log("len:" + String(b.length))
|
|
10
|
+
console.log("bytes:" + b.join(","))
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//! Issue #120: `tish:fs.readFileBytes` reads a binary file as an array of byte values (0–255)
|
|
2
|
+
//! on every backend, where the UTF-8-only `readFile` cannot. Verifies the exact bytes,
|
|
3
|
+
//! including a NUL and 0xFF (not valid UTF-8).
|
|
4
|
+
|
|
5
|
+
use std::path::PathBuf;
|
|
6
|
+
use std::process::Command;
|
|
7
|
+
|
|
8
|
+
const EXPECTED: &str = "\
|
|
9
|
+
isArray:true
|
|
10
|
+
len:7
|
|
11
|
+
bytes:0,1,2,255,128,72,73
|
|
12
|
+
";
|
|
13
|
+
|
|
14
|
+
fn run(backend: &str, fixture: &str, data_path: &str) -> String {
|
|
15
|
+
let tish = PathBuf::from(env!("CARGO_BIN_EXE_tish"));
|
|
16
|
+
let out = Command::new(&tish)
|
|
17
|
+
.args(["run", "--backend", backend, "--feature", "fs,process", fixture])
|
|
18
|
+
.env("RFB_FIXTURE", data_path)
|
|
19
|
+
.output()
|
|
20
|
+
.expect("spawn tish run");
|
|
21
|
+
assert!(
|
|
22
|
+
out.status.success(),
|
|
23
|
+
"tish run --backend {backend} failed: {}",
|
|
24
|
+
String::from_utf8_lossy(&out.stderr)
|
|
25
|
+
);
|
|
26
|
+
String::from_utf8_lossy(&out.stdout).into_owned()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
#[test]
|
|
30
|
+
fn read_file_bytes_reads_binary_on_every_backend() {
|
|
31
|
+
// A file whose bytes are not valid UTF-8 (NUL, 0xFF, 0x80) — readFile would error on it.
|
|
32
|
+
let data_path = std::env::temp_dir().join("tish_rfb_fixture.dat");
|
|
33
|
+
std::fs::write(&data_path, [0u8, 1, 2, 255, 128, 72, 73]).expect("write fixture");
|
|
34
|
+
let data_path = data_path.to_str().unwrap();
|
|
35
|
+
|
|
36
|
+
let fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
|
37
|
+
.join("tests")
|
|
38
|
+
.join("fixtures")
|
|
39
|
+
.join("read_file_bytes.tish");
|
|
40
|
+
assert!(fixture.is_file(), "missing fixture {}", fixture.display());
|
|
41
|
+
let fixture = fixture.to_str().unwrap();
|
|
42
|
+
|
|
43
|
+
assert_eq!(run("vm", fixture, data_path), EXPECTED, "vm output mismatch");
|
|
44
|
+
assert_eq!(run("interp", fixture, data_path), EXPECTED, "interp output mismatch");
|
|
45
|
+
}
|
|
@@ -1094,6 +1094,7 @@ impl Codegen {
|
|
|
1094
1094
|
"fileExists" => Some("Value::native(|args: &[Value]| tish_file_exists(args))"),
|
|
1095
1095
|
"isDir" => Some("Value::native(|args: &[Value]| tish_is_dir(args))"),
|
|
1096
1096
|
"readDir" => Some("Value::native(|args: &[Value]| tish_read_dir(args))"),
|
|
1097
|
+
"readFileBytes" => Some("Value::native(|args: &[Value]| tish_read_file_bytes(args))"),
|
|
1097
1098
|
"mkdir" => Some("Value::native(|args: &[Value]| tish_mkdir(args))"),
|
|
1098
1099
|
_ => None,
|
|
1099
1100
|
},
|
|
@@ -1455,7 +1456,7 @@ impl Codegen {
|
|
|
1455
1456
|
}
|
|
1456
1457
|
}
|
|
1457
1458
|
if self.has_feature("fs") {
|
|
1458
|
-
self.write("use tishlang_runtime::{read_file as tish_read_file, write_file as tish_write_file, file_exists as tish_file_exists, is_dir as tish_is_dir, read_dir as tish_read_dir, mkdir as tish_mkdir};\n");
|
|
1459
|
+
self.write("use tishlang_runtime::{read_file as tish_read_file, read_file_bytes as tish_read_file_bytes, write_file as tish_write_file, file_exists as tish_file_exists, is_dir as tish_is_dir, read_dir as tish_read_dir, mkdir as tish_mkdir};\n");
|
|
1459
1460
|
}
|
|
1460
1461
|
if self.has_feature("ws") {
|
|
1461
1462
|
self.write("use tishlang_runtime::{web_socket_client as tish_ws_client, web_socket_server_construct as tish_ws_server_construct};\n");
|
|
@@ -916,6 +916,10 @@ impl Evaluator {
|
|
|
916
916
|
exports.insert("fileExists".into(), Value::Native(natives::file_exists));
|
|
917
917
|
exports.insert("isDir".into(), Value::Native(natives::is_dir));
|
|
918
918
|
exports.insert("readDir".into(), Value::Native(natives::read_dir));
|
|
919
|
+
exports.insert(
|
|
920
|
+
"readFileBytes".into(),
|
|
921
|
+
Value::Native(natives::read_file_bytes),
|
|
922
|
+
);
|
|
919
923
|
exports.insert("mkdir".into(), Value::Native(natives::mkdir));
|
|
920
924
|
Ok(Value::object(exports))
|
|
921
925
|
}
|
|
@@ -420,6 +420,22 @@ pub fn read_file(args: &[Value]) -> Result<Value, String> {
|
|
|
420
420
|
}
|
|
421
421
|
}
|
|
422
422
|
|
|
423
|
+
/// Read a file as raw bytes (array of numbers 0–255) for binary data that `read_file`
|
|
424
|
+
/// (UTF-8 only) can't handle. See issue #120.
|
|
425
|
+
#[cfg(feature = "fs")]
|
|
426
|
+
pub fn read_file_bytes(args: &[Value]) -> Result<Value, String> {
|
|
427
|
+
use std::cell::RefCell;
|
|
428
|
+
use std::rc::Rc;
|
|
429
|
+
let path = args.first().map(|v| v.to_string()).unwrap_or_default();
|
|
430
|
+
match std::fs::read(&path) {
|
|
431
|
+
Ok(bytes) => {
|
|
432
|
+
let items: Vec<Value> = bytes.into_iter().map(|b| Value::Number(b as f64)).collect();
|
|
433
|
+
Ok(Value::Array(Rc::new(RefCell::new(items))))
|
|
434
|
+
}
|
|
435
|
+
Err(e) => Ok(Value::String(format!("Error: {}", e).into())),
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
423
439
|
#[cfg(feature = "fs")]
|
|
424
440
|
pub fn write_file(args: &[Value]) -> Result<Value, String> {
|
|
425
441
|
let path = args.first().map(|v| v.to_string()).unwrap_or_default();
|
|
@@ -666,6 +666,23 @@ pub fn read_file(args: &[Value]) -> Value {
|
|
|
666
666
|
}
|
|
667
667
|
}
|
|
668
668
|
|
|
669
|
+
/// Read a file as raw bytes — an array of numbers 0–255 — for binary data that `read_file`
|
|
670
|
+
/// (UTF-8 only) can't handle (images, fonts, archives). Lets pure-Tish decoders work on local
|
|
671
|
+
/// files. See issue #120.
|
|
672
|
+
#[cfg(feature = "fs")]
|
|
673
|
+
pub fn read_file_bytes(args: &[Value]) -> Value {
|
|
674
|
+
let path = args
|
|
675
|
+
.first()
|
|
676
|
+
.map(|v| v.to_display_string())
|
|
677
|
+
.unwrap_or_default();
|
|
678
|
+
match std::fs::read(&path) {
|
|
679
|
+
Ok(bytes) => Value::Array(VmRef::new(
|
|
680
|
+
bytes.into_iter().map(|b| Value::Number(b as f64)).collect(),
|
|
681
|
+
)),
|
|
682
|
+
Err(e) => make_error_value(e),
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
669
686
|
#[cfg(feature = "fs")]
|
|
670
687
|
pub fn write_file(args: &[Value]) -> Value {
|
|
671
688
|
let path = args
|
package/crates/tish_vm/src/vm.rs
CHANGED
|
@@ -169,6 +169,9 @@ fn get_builtin_export(enabled: &HashSet<String>, spec: &str, export_name: &str)
|
|
|
169
169
|
"mkdir" => Some(Value::native(|args: &[Value]| {
|
|
170
170
|
tishlang_runtime::mkdir(args)
|
|
171
171
|
})),
|
|
172
|
+
"readFileBytes" => Some(Value::native(|args: &[Value]| {
|
|
173
|
+
tishlang_runtime::read_file_bytes(args)
|
|
174
|
+
})),
|
|
172
175
|
_ => None,
|
|
173
176
|
};
|
|
174
177
|
}
|
package/package.json
CHANGED
|
Binary file
|
package/platform/darwin-x64/tish
CHANGED
|
Binary file
|
|
Binary file
|
package/platform/linux-x64/tish
CHANGED
|
Binary file
|
|
Binary file
|