diff --git a/.changeset/six-oranges-hang.md b/.changeset/six-oranges-hang.md new file mode 100644 index 00000000..3ee04b4d --- /dev/null +++ b/.changeset/six-oranges-hang.md @@ -0,0 +1,6 @@ +--- +"loro-wasm": patch +"loro-crdt": patch +--- + +Make loro-wasm work in cloudflare worker diff --git a/crates/loro-wasm/scripts/build.ts b/crates/loro-wasm/scripts/build.ts index ddce6f93..cd686121 100644 --- a/crates/loro-wasm/scripts/build.ts +++ b/crates/loro-wasm/scripts/build.ts @@ -41,8 +41,7 @@ async function build() { // const snip = `wasm-snip ./${target}/loro_wasm_bg.wasm -o ./${target}/loro_wasm_bg.wasm`; // console.log(">", snip); // await Deno.run({ cmd: snip.split(" "), cwd: LoroWasmDir }).status(); - const cmd = - `wasm-opt -Os ./${target}/loro_wasm_bg.wasm -o ./${target}/loro_wasm_bg.wasm`; + const cmd = `wasm-opt -Os ./${target}/loro_wasm_bg.wasm -o ./${target}/loro_wasm_bg.wasm`; console.log(">", cmd); await Deno.run({ cmd: cmd.split(" "), cwd: LoroWasmDir }).status(); }), @@ -58,8 +57,7 @@ async function build() { } async function cargoBuild() { - const cmd = - `cargo build --target wasm32-unknown-unknown --profile ${profile}`; + const cmd = `cargo build --target wasm32-unknown-unknown --profile ${profile}`; console.log(cmd); const status = await Deno.run({ cmd: cmd.split(" "), @@ -87,8 +85,7 @@ async function buildTarget(target: string) { } // TODO: polyfill FinalizationRegistry - const cmd = - `wasm-bindgen --weak-refs --target ${target} --out-dir ${target} ../../target/wasm32-unknown-unknown/${profileDir}/loro_wasm.wasm`; + const cmd = `wasm-bindgen --weak-refs --target ${target} --out-dir ${target} ../../target/wasm32-unknown-unknown/${profileDir}/loro_wasm.wasm`; console.log(">", cmd); await Deno.run({ cmd: cmd.split(" "), cwd: LoroWasmDir }).status(); console.log(); @@ -106,6 +103,16 @@ async function buildTarget(target: string) { wasm + "\n" + patch, ); } + if (target === "bundler") { + console.log("🔨 Patching bundler target"); + const patch = await Deno.readTextFile( + path.resolve(__dirname, "./bundler_patch.js"), + ); + await Deno.writeTextFile( + path.resolve(targetDirPath, "loro_wasm.js"), + patch, + ); + } } build(); diff --git a/crates/loro-wasm/scripts/bundler_patch.js b/crates/loro-wasm/scripts/bundler_patch.js new file mode 100644 index 00000000..28325996 --- /dev/null +++ b/crates/loro-wasm/scripts/bundler_patch.js @@ -0,0 +1,16 @@ +// See https://github.com/loro-dev/loro/issues/440 +// Without this patch, Cloudflare Worker would raise issue like: "Uncaught TypeError: wasm2.__wbindgen_start is not a function" +import * as wasm from "./loro_wasm_bg.wasm"; +import * as imports from "./loro_wasm_bg.js"; + +if (wasm.__wbindgen_start) { + imports.__wbg_set_wasm(wasm); + wasm.__wbindgen_start(); +} else { + const wkmod = await import("./loro_wasm_bg.wasm"); + const instance = new WebAssembly.Instance(wkmod.default, { + "./loro_wasm_bg.js": imports, + }); + imports.__wbg_set_wasm(instance.exports); +} +export * from "./loro_wasm_bg.js"; diff --git a/examples/loro-quill/src/App.vue b/examples/loro-quill/src/App.vue index c2d217cb..16090ccf 100644 --- a/examples/loro-quill/src/App.vue +++ b/examples/loro-quill/src/App.vue @@ -57,7 +57,7 @@ }; text.subscribe((e) => { - if (e.local) { + if (e.by === "local") { Promise.resolve().then(sync); } Promise.resolve().then(() => { diff --git a/examples/loro-quill/src/binding.ts b/examples/loro-quill/src/binding.ts index 0f20d6cd..fe446ce9 100644 --- a/examples/loro-quill/src/binding.ts +++ b/examples/loro-quill/src/binding.ts @@ -2,7 +2,7 @@ * The skeleton of this binding is learned from https://github.com/yjs/y-quill */ -import { Delta, Loro, LoroText, setDebug } from "loro-crdt"; +import { Delta, Loro, LoroText } from "loro-crdt"; import Quill, { DeltaOperation, DeltaStatic, Sources } from "quill"; // @ts-ignore import isEqual from "is-equal"; @@ -35,11 +35,14 @@ export class QuillBinding { }); this.quill = quill; this.richtext = doc.getText("text"); - this.richtext.subscribe(doc, (event) => { - Promise.resolve().then(() => { - if (!event.local && event.diff.type == "text") { - console.log(doc.peerId, "CRDT_EVENT", event); - const eventDelta = event.diff.diff; + this.richtext.subscribe((event) => { + if (event.by !== "import") { + return; + } + + for (const e of event.events) { + if (e.diff.type == "text") { + const eventDelta = e.diff.diff; const delta: Delta[] = []; let index = 0; for (let i = 0; i < eventDelta.length; i++) { @@ -74,7 +77,7 @@ export class QuillBinding { quill.setContents(new Delta(a), "this" as any); } } - }); + } }); quill.setContents( new Delta(