From b725cf488d4958116a8a5d6e384fc86731c831c3 Mon Sep 17 00:00:00 2001 From: Codex Bot Date: Fri, 23 Oct 2026 12:13:22 +0800 Subject: [PATCH] fix: publish file errors only after the task reaches failed state --- README.md | 2 +- src/api.rs | 2 +- src/tasks.rs | 9 ++++++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0e18b5e..4b1f562 100644 --- a/README.md +++ b/README.md @@ -552,6 +552,6 @@ Layout and paint drivers now prepare one occurrence at a time. Their fixed-size ui.stats().dependencyInvalidations counts observed layout/paint dependency version mismatches. lastInvalidDependency records the phase, object kind/identity and old/current versions without rendering its fields or retaining it. An input changing its globals is an expected invalidation; compare idle document versions before diagnosing a refresh loop. -ui.readText(owner,key,path[,callback]) returns an owner-scoped Task and reads a regular UTF-8 file off the VM thread. Paths use native filesystem syntax; absolute paths are recommended. The optional callback takes zero arguments and must return Unit; it runs only on successful read and can use task.result(). Without a callback, poll status then read result from code. result() is available while a success callback is running or after completion (timers return Unit); error() returns an empty String or the provider/callback error. A provider failure marks the task failed and skips its callback without stopping the VM; a source callback failure still stops the shared domain. Owner/key replacement, explicit cancellation, close/reset/VM discard and GC drop the provider lease, remove queued completion and reject late delivery. In-progress OS reads may finish, but cannot deliver after cancellation. Only the owning VM worker updates managed results and rechecks owner/key identity. No VM handles enter provider threads beyond opaque weak identities. +ui.readText(owner,key,path[,callback]) returns an owner-scoped Task and reads a regular UTF-8 file off the VM thread. Paths use native filesystem syntax; absolute paths are recommended. The optional callback takes zero arguments and must return Unit; it runs only on successful read and can use task.result(). Without a callback, poll status then read result from code. result() is available while a success callback is running or after completion (timers return Unit); error() returns an empty String until failed, then the provider/callback error. A provider failure marks the task failed and skips its callback without stopping the VM; a source callback failure still stops the shared domain. Owner/key replacement, explicit cancellation, close/reset/VM discard and GC drop the provider lease, remove queued completion and reject late delivery. In-progress OS reads may finish, but cannot deliver after cancellation. Only the owning VM worker updates managed results and rechecks owner/key identity. No VM handles enter provider threads beyond opaque weak identities. The lazy shared pool has four threads and a 64-job queue. Each runtime permits 16 outstanding file requests (one temporary replacement reservation), and each read is capped at 1 MiB by metadata plus actual streaming length; non-regular files, non-UTF-8 data and over-limit content fail rather than truncate. These limits do not constitute a full filesystem sandbox. The provider returns text in the same managed Task, not a second application-state store. Network/await support is still separate unfinished work. See examples/async-file.endor; from REPL call reader.read("/absolute/path.txt") to update its actual TextBlock, even when that object is hidden but retained. diff --git a/src/api.rs b/src/api.rs index 7c0f00b..302be1f 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1507,7 +1507,7 @@ Layout and paint drivers now prepare one occurrence at a time. Their fixed-size ui.stats().dependencyInvalidations counts observed layout/paint dependency version mismatches. lastInvalidDependency records the phase, object kind/identity and old/current versions without rendering its fields or retaining it. An input changing its globals is an expected invalidation; compare idle document versions before diagnosing a refresh loop. -ui.readText(owner,key,path[,callback]) returns an owner-scoped Task and reads a regular UTF-8 file off the VM thread. Paths use native filesystem syntax; absolute paths are recommended. The optional callback takes zero arguments and must return Unit; it runs only on successful read and can use task.result(). Without a callback, poll status then read result from code. result() is available while a success callback is running or after completion (timers return Unit); error() returns an empty String or the provider/callback error. A provider failure marks the task failed and skips its callback without stopping the VM; a source callback failure still stops the shared domain. Owner/key replacement, explicit cancellation, close/reset/VM discard and GC drop the provider lease, remove queued completion and reject late delivery. In-progress OS reads may finish, but cannot deliver after cancellation. Only the owning VM worker updates managed results and rechecks owner/key identity. No VM handles enter provider threads beyond opaque weak identities. +ui.readText(owner,key,path[,callback]) returns an owner-scoped Task and reads a regular UTF-8 file off the VM thread. Paths use native filesystem syntax; absolute paths are recommended. The optional callback takes zero arguments and must return Unit; it runs only on successful read and can use task.result(). Without a callback, poll status then read result from code. result() is available while a success callback is running or after completion (timers return Unit); error() returns an empty String until failed, then the provider/callback error. A provider failure marks the task failed and skips its callback without stopping the VM; a source callback failure still stops the shared domain. Owner/key replacement, explicit cancellation, close/reset/VM discard and GC drop the provider lease, remove queued completion and reject late delivery. In-progress OS reads may finish, but cannot deliver after cancellation. Only the owning VM worker updates managed results and rechecks owner/key identity. No VM handles enter provider threads beyond opaque weak identities. The lazy shared pool has four threads and a 64-job queue. Each runtime permits 16 outstanding file requests (one temporary replacement reservation), and each read is capped at 1 MiB by metadata plus actual streaming length; non-regular files, non-UTF-8 data and over-limit content fail rather than truncate. These limits do not constitute a full filesystem sandbox. The provider returns text in the same managed Task, not a second application-state store. Network/await support is still separate unfinished work. See examples/async-file.endor; from REPL call reader.read("/absolute/path.txt") to update its actual TextBlock, even when that object is hidden but retained. diff --git a/src/tasks.rs b/src/tasks.rs index 85067ba..8f67d9c 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -430,7 +430,14 @@ impl NativeCallable for Method { .map(|text| Value::Text(text.to_string())) .unwrap_or(Value::Nil) } - Query::Error => Value::Text(task.error.as_deref().unwrap_or_default().into()), + Query::Error => Value::Text( + if task.state == State::Failed { + task.error.as_deref().unwrap_or_default() + } else { + "" + } + .into(), + ), Query::Cancel => { if cx.store().is_read_only() { return Err(invalid(