diff --git a/src/lang/wasm.ts b/src/lang/wasm.ts index 4ee6833ce..31e8d7135 100644 --- a/src/lang/wasm.ts +++ b/src/lang/wasm.ts @@ -35,7 +35,7 @@ import { Configuration } from 'wasm-lib/kcl/bindings/Configuration' import { DeepPartial } from 'lib/types' import { ProjectConfiguration } from 'wasm-lib/kcl/bindings/ProjectConfiguration' import { Sketch } from '../wasm-lib/kcl/bindings/Sketch' -import { ExecState as RawExecState } from '../wasm-lib/kcl/bindings/ExecState' +import { ExecOutcome as RustExecOutcome } from 'wasm-lib/kcl/bindings/ExecOutcome' import { ProgramMemory as RawProgramMemory } from '../wasm-lib/kcl/bindings/ProgramMemory' import { EnvironmentRef } from '../wasm-lib/kcl/bindings/EnvironmentRef' import { Environment } from '../wasm-lib/kcl/bindings/Environment' @@ -260,10 +260,10 @@ export function emptyExecState(): ExecState { } } -function execStateFromRaw(raw: RawExecState): ExecState { +function execStateFromRust(execOutcome: RustExecOutcome): ExecState { return { - memory: ProgramMemory.fromRaw(raw.modLocal.memory), - operations: raw.modLocal.operations, + memory: ProgramMemory.fromRaw(execOutcome.memory), + operations: execOutcome.operations, } } @@ -535,14 +535,14 @@ export const _executor = async ( jsAppSettings = getAllCurrentSettings(lastSettingsSnapshot) } } - const execState: RawExecState = await execute( + const execOutcome: RustExecOutcome = await execute( JSON.stringify(node), JSON.stringify(programMemoryOverride?.toRaw() || null), JSON.stringify({ settings: jsAppSettings }), engineCommandManager, fileSystemManager ) - return execStateFromRaw(execState) + return execStateFromRust(execOutcome) } catch (e: any) { console.log(e) const parsed: KclErrorWithOutputs = JSON.parse(e.toString()) diff --git a/src/wasm-lib/kcl/src/execution/cache.rs b/src/wasm-lib/kcl/src/execution/cache.rs index ea8ed1b5c..479778aa0 100644 --- a/src/wasm-lib/kcl/src/execution/cache.rs +++ b/src/wasm-lib/kcl/src/execution/cache.rs @@ -1,6 +1,5 @@ //! Functions for helping with caching an ast and finding the parts the changed. -use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::{ @@ -9,8 +8,7 @@ use crate::{ }; /// Information for the caching an AST and smartly re-executing it if we can. -#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] -#[ts(export)] +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] pub struct CacheInformation { /// The old information. pub old: Option, @@ -19,8 +17,7 @@ pub struct CacheInformation { } /// The old ast and program memory. -#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] -#[ts(export)] +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] pub struct OldAstState { /// The ast. pub ast: Node, @@ -40,8 +37,7 @@ impl From for CacheInformation { } /// The result of a cache check. -#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] -#[ts(export)] +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] pub struct CacheResult { /// Should we clear the scene and start over? pub clear_scene: bool, diff --git a/src/wasm-lib/kcl/src/execution/mod.rs b/src/wasm-lib/kcl/src/execution/mod.rs index 82378e4ed..32f3dffa0 100644 --- a/src/wasm-lib/kcl/src/execution/mod.rs +++ b/src/wasm-lib/kcl/src/execution/mod.rs @@ -51,16 +51,14 @@ use crate::{ pub use cad_op::Operation; /// State for executing a program. -#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] -#[ts(export)] +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] #[serde(rename_all = "camelCase")] pub struct ExecState { pub global: GlobalState, pub mod_local: ModuleState, } -#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] -#[ts(export)] +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] #[serde(rename_all = "camelCase")] pub struct GlobalState { /// The stable artifact ID generator. @@ -71,8 +69,7 @@ pub struct GlobalState { pub module_infos: IndexMap, } -#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] -#[ts(export)] +#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq)] #[serde(rename_all = "camelCase")] pub struct ModuleState { /// Program variable bindings. @@ -94,6 +91,18 @@ pub struct ModuleState { pub settings: MetaSettings, } +/// Outcome of executing a program. This is used in TS. +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] +#[ts(export)] +#[serde(rename_all = "camelCase")] +pub struct ExecOutcome { + /// Program variable bindings of the top-level module. + pub memory: ProgramMemory, + /// Operations that have been performed in execution order, for display in + /// the Feature Tree. + pub operations: Vec, +} + impl Default for ExecState { fn default() -> Self { Self::new() @@ -123,6 +132,18 @@ impl ExecState { }; } + /// Convert to execution outcome when running in WebAssembly. We want to + /// reduce the amount of data that crosses the WASM boundary as much as + /// possible. + pub fn to_wasm_outcome(self) -> ExecOutcome { + // Fields are opt-in so that we don't accidentally leak private internal + // state when we add more to ExecState. + ExecOutcome { + memory: self.mod_local.memory, + operations: self.mod_local.operations, + } + } + pub fn memory(&self) -> &ProgramMemory { &self.mod_local.memory } @@ -424,7 +445,7 @@ impl Environment { /// Dynamic state that depends on the dynamic flow of the program, like the call /// stack. If the language had exceptions, for example, you could store the /// stack of exception handlers here. -#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize, ts_rs::TS, JsonSchema)] +#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)] pub struct DynamicState { pub solid_ids: Vec, } @@ -462,8 +483,7 @@ impl DynamicState { } /// A generator for ArtifactIds that can be stable across executions. -#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] -#[ts(export)] +#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq)] #[serde(rename_all = "camelCase")] pub struct IdGenerator { next_id: usize, @@ -1073,7 +1093,7 @@ impl Solid { /// An solid ID and its fillet and chamfer IDs. This is needed for lazy /// fillet evaluation. -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, ts_rs::TS, JsonSchema)] +#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] pub struct SolidLazyIds { pub solid_id: uuid::Uuid, pub sketch_id: uuid::Uuid, @@ -1153,8 +1173,7 @@ pub enum BodyType { /// Info about a module. Right now, this is pretty minimal. We hope to cache /// modules here in the future. -#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, ts_rs::TS, JsonSchema)] -#[ts(export)] +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct ModuleInfo { /// The ID of the module. id: ModuleId, diff --git a/src/wasm-lib/src/wasm.rs b/src/wasm-lib/src/wasm.rs index fc84e66da..efecd97cb 100644 --- a/src/wasm-lib/src/wasm.rs +++ b/src/wasm-lib/src/wasm.rs @@ -133,7 +133,7 @@ pub async fn execute( // gloo-serialize crate instead. // DO NOT USE serde_wasm_bindgen::to_value(&exec_state).map_err(|e| e.to_string()) // it will break the frontend. - JsValue::from_serde(&exec_state).map_err(|e| e.to_string()) + JsValue::from_serde(&exec_state.to_wasm_outcome()).map_err(|e| e.to_string()) } // wasm_bindgen wrapper for execute