// Generates the Yjs wire fixtures that define compatibility for the Rust // core. These are the contract: never edit a fixture to make a test pass. // A deliberate rule change regenerates them in the same commit. import * as Y from 'yjs' import { mkdirSync, writeFileSync } from 'node:fs' import { join, dirname } from 'node:path' import { fileURLToPath } from 'node:url' const dataDir = join(dirname(fileURLToPath(import.meta.url)), 'data') mkdirSync(dataDir, { recursive: true }) function emit(name, build) { const doc = new Y.Doc() // new Y.Doc() assigns a random clientID. Fixed IDs ensure that running the // generator twice produces byte-identical fixtures (required for the // regeneration gate that later tasks add). doc.clientID = 1 build(doc) const update = Y.encodeStateAsUpdate(doc) writeFileSync(join(dataDir, `${name}.update.bin`), Buffer.from(update)) writeFileSync( join(dataDir, `${name}.expected.json`), JSON.stringify({ text: doc.getText('content').toString(), delta: doc.getText('content').toDelta() }, null, 2) + '\n' ) console.log(`${name}: ${update.length} bytes`) } emit('hello', (doc) => { doc.getText('content').insert(0, 'hello world') }) emit('unicode', (doc) => { // Surrogate pairs and combining marks: Yjs indexes UTF-16 code units and // Rust indexes UTF-8 bytes, so this is where an index-conversion bug shows. doc.getText('content').insert(0, 'héllo 🌍 café') }) emit('formatted', (doc) => { // Rich text formatting: bold is the key assertion. The delta field captures // the formatting structure that toString() would strip, verifying that the // Rust side correctly decodes format operations. const t = doc.getText('content') t.insert(0, 'plain bold plain') t.format(6, 4, { bold: true }) }) emit('concurrent', (doc) => { // Two docs diverge and merge. The merged state is order-independent, so // Rust must arrive at the same bytes from the same inputs. const a = new Y.Doc() a.clientID = 1 const b = new Y.Doc() b.clientID = 2 // Note: doc.clientID (set to 3 here) overrides the emit() assignment above. // The clientID of this local doc must differ from a and b to ensure // deterministic merge ordering. doc.clientID = 3 a.getText('content').insert(0, 'AAA') b.getText('content').insert(0, 'BBB') Y.applyUpdate(a, Y.encodeStateAsUpdate(b)) Y.applyUpdate(b, Y.encodeStateAsUpdate(a)) Y.applyUpdate(doc, Y.encodeStateAsUpdate(a)) })