only rust changes reset scene (#6060)

Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
Jess Frazelle
2025-03-29 11:43:42 -07:00
committed by GitHub
parent 6532b23f1c
commit 51c16d0048
5 changed files with 126 additions and 8 deletions

View File

@ -1,6 +1,8 @@
//! Cache testing framework.
use kcl_lib::{bust_cache, ExecError, ExecOutcome};
use kcmc::{each_cmd as mcmd, ModelingCmd};
use kittycad_modeling_cmds as kcmc;
#[derive(Debug)]
struct Variation<'a> {
@ -253,3 +255,71 @@ extrude(sketch001, length = 4)
second.artifact_graph.len()
);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_cache_empty_file_pop_cache_empty_file_planes_work() {
// Get the current working directory.
let code = "";
let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default())
.await
.unwrap();
let program = kcl_lib::Program::parse_no_errs(code).unwrap();
let outcome = ctx.run_with_caching(program).await.unwrap();
// Ensure nothing is left in the batch
assert!(ctx.engine.batch().read().await.is_empty());
assert!(ctx.engine.batch_end().read().await.is_empty());
// Ensure the planes work, and we can show or hide them.
// Hide/show the grid.
let default_planes = ctx.engine.get_default_planes().read().await.clone().unwrap();
// Assure the outcome is the same.
assert_eq!(outcome.default_planes, Some(default_planes.clone()));
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
Default::default(),
&ModelingCmd::from(mcmd::ObjectVisible {
hidden: false,
object_id: default_planes.xy,
}),
)
.await
.unwrap();
// Now simulate an engine pause/network disconnect.
// Raw dog clear the scene entirely.
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
Default::default(),
&ModelingCmd::from(mcmd::SceneClearAll {}),
)
.await
.unwrap();
// Bust the cache and reset the scene.
let outcome = ctx.bust_cache_and_reset_scene().await.unwrap();
// Get the default planes.
let default_planes = ctx.engine.get_default_planes().read().await.clone().unwrap();
assert_eq!(outcome.default_planes, Some(default_planes.clone()));
// Ensure we can show a plane.
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
Default::default(),
&ModelingCmd::from(mcmd::ObjectVisible {
hidden: false,
object_id: default_planes.xz,
}),
)
.await
.unwrap();
ctx.close().await;
}

View File

@ -529,6 +529,18 @@ impl ExecutorContext {
.await
}
pub async fn bust_cache_and_reset_scene(&self) -> Result<ExecOutcome, KclErrorWithOutputs> {
cache::bust_cache().await;
// Execute an empty program to clear and reset the scene.
// We specifically want to be returned the objects after the scene is reset.
// Like the default planes so it is easier to just execute an empty program
// after the cache is busted.
let outcome = self.run_with_caching(crate::Program::empty()).await?;
Ok(outcome)
}
async fn prepare_mem(&self, exec_state: &mut ExecState) -> Result<(), KclErrorWithOutputs> {
self.eval_prelude(exec_state, SourceRange::synthetic())
.await

View File

@ -211,6 +211,14 @@ impl Program {
pub fn recast_with_options(&self, options: &FormatOptions) -> String {
self.ast.recast(options, 0)
}
/// Create an empty program.
pub fn empty() -> Self {
Self {
ast: parsing::ast::types::Node::no_src(parsing::ast::types::Program::default()),
original_file_contents: String::new(),
}
}
}
#[inline]

View File

@ -85,6 +85,21 @@ impl Context {
}
}
/// Reset the scene and bust the cache.
/// ONLY use this if you absolutely need to reset the scene and bust the cache.
#[wasm_bindgen(js_name = bustCacheAndResetScene)]
pub async fn bust_cache_and_reset_scene(&self, settings: &str, path: Option<String>) -> Result<JsValue, String> {
console_error_panic_hook::set_once();
let ctx = self.create_executor_ctx(settings, path, false)?;
match ctx.bust_cache_and_reset_scene().await {
// The serde-wasm-bindgen does not work here because of weird HashMap issues.
// DO NOT USE serde_wasm_bindgen::to_value it will break the frontend.
Ok(outcome) => JsValue::from_serde(&outcome).map_err(|e| e.to_string()),
Err(err) => Err(serde_json::to_string(&err).map_err(|serde_err| serde_err.to_string())?),
}
}
/// Execute a program in mock mode.
#[wasm_bindgen(js_name = executeMock)]
pub async fn execute_mock(

View File

@ -146,16 +146,13 @@ export default class RustContext {
return this._defaultPlanes
}
// Clear the scene and bust the cache.
// Clear/reset the scene and bust the cache.
async clearSceneAndBustCache(
settings: DeepPartial<Configuration>,
path?: string
) {
// Send through and empty ast to clear the scene.
// This will also bust the cache and reset the default planes.
// We do it like this so it works better with adding stuff later and the
// cache.
// It also works better with the id generator.
): Promise<ExecState> {
const instance = await this._checkInstance()
const ast: Node<Program> = {
body: [],
shebang: null,
@ -172,7 +169,23 @@ export default class RustContext {
commentStart: 0,
}
await this.execute(ast, settings, path)
try {
const result = await instance.bustCacheAndResetScene(
JSON.stringify(settings),
path
)
/* Set the default planes, safe to call after execute. */
const outcome = execStateFromRust(result, ast)
this._defaultPlanes = outcome.defaultPlanes
// Return the result.
return outcome
} catch (e: any) {
const err = errFromErrWithOutputs(e)
this._defaultPlanes = err.defaultPlanes
return Promise.reject(err)
}
}
getDefaultPlaneId(name: DefaultPlaneStr): string | Error {