Compare commits

...

1 Commits

Author SHA1 Message Date
c7b7b91129 Reduce the amount of data sent back to JS/TS from WASM 2024-12-28 19:24:38 -05:00
3 changed files with 38 additions and 7 deletions

View File

@ -35,7 +35,7 @@ import { Configuration } from 'wasm-lib/kcl/bindings/Configuration'
import { DeepPartial } from 'lib/types' import { DeepPartial } from 'lib/types'
import { ProjectConfiguration } from 'wasm-lib/kcl/bindings/ProjectConfiguration' import { ProjectConfiguration } from 'wasm-lib/kcl/bindings/ProjectConfiguration'
import { Sketch } from '../wasm-lib/kcl/bindings/Sketch' import { Sketch } from '../wasm-lib/kcl/bindings/Sketch'
import { ExecState as RawExecState } from '../wasm-lib/kcl/bindings/ExecState' import { ExecOutcome } from 'wasm-lib/kcl/bindings/ExecOutcome'
import { ProgramMemory as RawProgramMemory } from '../wasm-lib/kcl/bindings/ProgramMemory' import { ProgramMemory as RawProgramMemory } from '../wasm-lib/kcl/bindings/ProgramMemory'
import { EnvironmentRef } from '../wasm-lib/kcl/bindings/EnvironmentRef' import { EnvironmentRef } from '../wasm-lib/kcl/bindings/EnvironmentRef'
import { Environment } from '../wasm-lib/kcl/bindings/Environment' import { Environment } from '../wasm-lib/kcl/bindings/Environment'
@ -260,10 +260,10 @@ export function emptyExecState(): ExecState {
} }
} }
function execStateFromRaw(raw: RawExecState): ExecState { function execStateFromRust(execOutcome: ExecOutcome): ExecState {
return { return {
memory: ProgramMemory.fromRaw(raw.modLocal.memory), memory: ProgramMemory.fromRaw(execOutcome.memory),
operations: raw.modLocal.operations, operations: execOutcome.operations,
} }
} }
@ -535,14 +535,14 @@ export const _executor = async (
jsAppSettings = getAllCurrentSettings(lastSettingsSnapshot) jsAppSettings = getAllCurrentSettings(lastSettingsSnapshot)
} }
} }
const execState: RawExecState = await execute( const execOutcome: ExecOutcome = await execute(
JSON.stringify(node), JSON.stringify(node),
JSON.stringify(programMemoryOverride?.toRaw() || null), JSON.stringify(programMemoryOverride?.toRaw() || null),
JSON.stringify({ settings: jsAppSettings }), JSON.stringify({ settings: jsAppSettings }),
engineCommandManager, engineCommandManager,
fileSystemManager fileSystemManager
) )
return execStateFromRaw(execState) return execStateFromRust(execOutcome)
} catch (e: any) { } catch (e: any) {
console.log(e) console.log(e)
const parsed: KclErrorWithOutputs = JSON.parse(e.toString()) const parsed: KclErrorWithOutputs = JSON.parse(e.toString())

View File

@ -94,6 +94,18 @@ pub struct ModuleState {
pub settings: MetaSettings, pub settings: MetaSettings,
} }
/// Outcome from executing a program. This is used in WebAssembly/WASM.
#[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<Operation>,
}
impl Default for ExecState { impl Default for ExecState {
fn default() -> Self { fn default() -> Self {
Self::new() Self::new()
@ -123,6 +135,25 @@ impl ExecState {
}; };
} }
/// Convert to an output for WebAssembly/WASM.
pub fn to_wasm_outcome(mut self) -> ExecOutcome {
// Clear closed-over program memory inside closures. This is
// destructive. It greatly reduces the amount of data crossing the WASM
// boundary that we won't ever use.
for env in self.mut_memory().environments.iter_mut() {
for (_, value) in env.bindings.iter_mut() {
if let KclValue::Function { memory, .. } = value {
*memory = Box::new(ProgramMemory::new());
}
}
}
ExecOutcome {
memory: self.mod_local.memory,
operations: self.mod_local.operations,
}
}
pub fn memory(&self) -> &ProgramMemory { pub fn memory(&self) -> &ProgramMemory {
&self.mod_local.memory &self.mod_local.memory
} }

View File

@ -133,7 +133,7 @@ pub async fn execute(
// gloo-serialize crate instead. // gloo-serialize crate instead.
// DO NOT USE serde_wasm_bindgen::to_value(&exec_state).map_err(|e| e.to_string()) // DO NOT USE serde_wasm_bindgen::to_value(&exec_state).map_err(|e| e.to_string())
// it will break the frontend. // 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 // wasm_bindgen wrapper for execute