From 02a09ae2d707afeb1f88f12b07397f90e3e13e31 Mon Sep 17 00:00:00 2001 From: Hare Date: Fri, 14 Aug 2026 00:31:22 +0900 Subject: [PATCH] test: verify browser WASM config parity --- crates/config-source-wasm/src/lib.rs | 8 ++- .../generated/config_source_wasm_bg.wasm | Bin 435804 -> 435980 bytes .../config-source/api.test.ts | 2 +- .../test/config-source/wasm-parity.test.ts | 67 ++++++++++++++++++ 4 files changed, 73 insertions(+), 4 deletions(-) rename web/workspace/{src/lib/workspace => test}/config-source/api.test.ts (97%) create mode 100644 web/workspace/test/config-source/wasm-parity.test.ts diff --git a/crates/config-source-wasm/src/lib.rs b/crates/config-source-wasm/src/lib.rs index e19501ad..042312bb 100644 --- a/crates/config-source-wasm/src/lib.rs +++ b/crates/config-source-wasm/src/lib.rs @@ -1,7 +1,7 @@ use config_source::{ ConfigTreeSnapshot, EvaluationResult, SnapshotEnvironment, ToolchainContract, VirtualPath, }; -use serde_wasm_bindgen::{from_value, to_value}; +use serde_wasm_bindgen::{Serializer, from_value}; use wasm_bindgen::prelude::*; #[wasm_bindgen] @@ -12,7 +12,7 @@ pub fn evaluate_snapshot(snapshot: JsValue, contract: JsValue) -> Result(value: JsValue) -> Result } fn encode(value: T) -> Result { - to_value(&value).map_err(|error| JsValue::from_str(&error.to_string())) + value + .serialize(&Serializer::json_compatible()) + .map_err(|error| JsValue::from_str(&error.to_string())) } fn js_error(error: impl std::fmt::Display) -> JsValue { diff --git a/web/workspace/src/lib/workspace/config-source/generated/config_source_wasm_bg.wasm b/web/workspace/src/lib/workspace/config-source/generated/config_source_wasm_bg.wasm index 5e6dcaddda46a2814a2063cccda3d3c017f56fe7..dbbca6626c33ffbe02c59f6b579ad0b043013c19 100644 GIT binary patch delta 1158 zcmbVKO=wd=5Z;;HBri=KzNm;;54&j(MHE}mL{XvJHsa60qhdwzugar{iU$u$>K~#M z^dPK9MXVka)GALz#Dho=MLZ}*XlX1WJxI;Lp9&V7dC5UJAZk5_i#MldeDKOG!q(i|aWwAhI6m>K zpk>zp{emJ^+@VQqURr^$fCsg-qY#pv5@GOE`lw|aR=}j#k3l}czUpuSZ-8<`6WC7f z-2`qu)P{$R$Ju_9W_QfcxAxTO0k0rNXq=@1WJe&hpfR|p>K%>3PVD4&1@cWLUuZ1( zRA4Kj-_)mp0qq&YPDypv3pMH{cfE>R%35kwz$xx73i##^QllKZ{NOo-$2feAxF(Cp zyeUBx3p9^jQ!yxl#$;niqrkx1@HOOP(r+NRs|*lE0w#2dpg~Yo849dX_N=#&f-3li z89RIbxv)8|RvH=^;0(?AOzV8lP14-N(`jcu;Exu{)Hf7!2zWsQ_4N~?A+*9ITyYYY z{QJRT4smi<;!@aFgRoW1$=JuV7+a)aU+5aQ`A>~Za8-)`%SG#6<0U`R zAMxxm*b&{#$)V+HI1OpH#mWO-GE3V5lZ>8OnFB~UD9L%`K6c4XkaWwt{#WonrQqAO#oPxy0Mm{jqOl6O|g1TXegl4LMLzC zFUcP0jUHT(={t0>rz_QgC$K$gt*KA5?!|OsHT1fs>BJ`3;o577ok6i<_sZ49j(z+4 Qb{F>a?d^+ZrxUxP-?cs)S^xk5 delta 927 zcmZuvPe>F|7@zNZGrKc8J2bmS#A@|s^&p{?P-}JC=k5wBo&%M_2#jG5B@rHiHOd0n zLx-JIP=t37z9Gbgyj+g0?Aa83@jOz_Mel#=$DJYN9UtD(J~#1s9zf zaMm+PpWBTU*|mbrP?3Wxm`YT@i*nYERY)7k*5t$rK8C1lS;doN23PTXNqpCQ&s5>7 zo~2CDiz##6L(YVj!DZ?%D&W((488!4?zFBls^ICE#jLtlAZ-^Mjbp)~1X0t9USlM9 zz%36k%P3EnK1Xi53)He5<7zv3^d089#NPaCO(fhoU8Qne+%fy8o9=F-&C%0sZn__V zA~7|@;xXA=#b3vSrlzPRuaI%oij(1@-!$KyL3w%&kN=0C4nor?AwX24vR^TWHGt5< zA-HtNT`gEx!wyK+!Ee(J*kbVoE!s^*>+;8YY zLVs$3DYpe1GmSXf0z4zQ+`|$85jkIAO=PBXtUncUrKM3Q9VdDfheV`Gmm4|ON?IlJ zY(S3Y*T>(y&bb8n=Z-(NLM6~PUOs|L$T;~A3WkOl#Bk#Bo`4$ z{o`PVPMSyRg~CNtHo+^kvMTq#uRYPAw`HSZn!V$MF{YzM)mON?L@?E z$xlZd&9;?Hgr38`tPskob0dQ{rI%wzVO*88m=~B$-V@og+RJZi6d-CUo c(GSD2zGYmHk2Vb#M�laW + +import { assertEquals } from "jsr:@std/assert"; +// The generated wasm-bindgen loader is JavaScript with an adjacent declaration file. +// @ts-expect-error Deno checks the generated JS implementation rather than its .d.ts. +import init, { + analyze_snapshot, + evaluate_snapshot, +} from "../../src/lib/workspace/config-source/generated/config_source_wasm.js"; +import type { ConfigTreeSnapshot, ToolchainContract } from "../../src/lib/workspace/config-source/types.ts"; + +const bytes = await Deno.readFile( + new URL("../../src/lib/workspace/config-source/generated/config_source_wasm_bg.wasm", import.meta.url), +); +await init({ module_or_path: bytes }); + +const snapshot: ConfigTreeSnapshot = { + revision: 4, + digest: "sha256:test-tree", + entries: { + "workspace.dcdl": { + path: "workspace.dcdl", + content_type: "decodal", + content: 'import "./lib/value.dcdl"', + content_digest: "sha256:root", + }, + "lib/value.dcdl": { + path: "lib/value.dcdl", + content_type: "decodal", + content: "{ answer = 42; }", + content_digest: "sha256:value", + }, + }, +}; + +const contract: ToolchainContract = { + contract_version: 1, + decodal_version: "0.2.0", + schema_version: 1, + entrypoints: ["workspace.dcdl"], + import_policy_version: 1, + fingerprint: "sha256:test-contract", +}; + +Deno.test("generated WASM evaluates the same virtual import contract", () => { + const result = evaluate_snapshot(snapshot, contract) as { + projections: Array<{ data_json: { answer: number } }>; + }; + assertEquals(result.projections[0].data_json, { answer: 42 }); +}); + +Deno.test("generated WASM diagnostics carry snapshot provenance", () => { + const diagnostics = analyze_snapshot( + snapshot, + "workspace.dcdl", + "{ broken = ; }", + ) as Array<{ + path: string; + revision: number; + tree_digest: string; + kind: string; + }>; + assertEquals(diagnostics[0].path, "workspace.dcdl"); + assertEquals(diagnostics[0].revision, 4); + assertEquals(diagnostics[0].tree_digest, "sha256:test-tree"); + assertEquals(diagnostics[0].kind, "syntax"); +});