automerge / automerge-classic

A JSON-like data structure (a CRDT) that can be modified concurrently by different users, and merged again automatically.
http://automerge.org/
MIT License
14.77k stars 467 forks source link

Cloudflare workers FinalizationRegistry not defined #532

Open philholden opened 1 year ago

philholden commented 1 year ago

Looks like Cloudflare workers do not support FinalizationRegistry so cannot use AutoMerge there.

Total Upload: 2446.27 KiB / gzip: 914.51 KiB

✘ [ERROR] A request to the Cloudflare API (/workers/scripts/wrangler-init) failed.

Uncaught ReferenceError: FinalizationRegistry is not defined at index.js:1479:29 [code: 10021]

https://github.com/cloudflare/workers-sdk/issues/2258

Are there any alternatives to FinalizationRegistry.

philholden commented 1 year ago

I tried building without --weak-ref this removes FinalizationRegistry lines in @automerge/automerge-wasm in node_modules.

image image

Will this cause memory leaks? If so when?

a) each time I update a document and old doc gets garbaged in JS b) Just one per import of automerge

Will memory be free when JS isolate stops running?

I was then able to upload my worker. However it looks like the worker could not see the wasm I got the following error:

"exceptions": [
    {
      "name": "TypeError",
      "message": "wasm.__wbindgen_add_to_stack_pointer is not a function",
      "timestamp": 1676066126346

from clouldflare docs it look like workers should load wasm like this:

import module from "./lib/hello.wasm"

export default {
  async fetch(request) {
    const instance = await WebAssembly.instantiate(module);
    const result = instance.exports.hello();
    return new Response(result);
  }
}

There is no top level await in workers so I tried updating automerge_wasm_bg.js in node modules like this:

import __wasm from './automerge_wasm_bg.wasm';

let wasm;
let __ready;

export let ready = new Promise(resolve => { __ready = resolve;})

async function __init() {
  wasm = (await WebAssembly.instantiate(__wasm)).exports;
  __ready();
}
__init()

And using like this:

import * as Automerge from "@automerge/automerge";
import { ready } from "@automerge/automerge-wasm";

export interface Env {}

export default {
  async fetch(
    request: Request,
    env: Env,
    ctx: ExecutionContext
  ): Promise<Response> {
    await ready;
    const doc = Automerge.init();
    doc.items = ["hello", "world"];

    return new Response("Hello World!" + doc.items[0]);
  },
};

but ready never resolves:

"exceptions": [
    {
      "name": "Error",
      "message": "The script will never generate a response.",
      "timestamp": 1676104359661
    }
  ],
philholden commented 1 year ago

repo is here: https://github.com/philholden/automerge-cloudflare-test edits applied to node_modules/@automerge/automerge-wasm/bundler/automerge_wasm_bg.js here:

https://github.com/philholden/automerge-cloudflare-test/blob/main/automerge_wasm_bg.editied.js