branch: main
shim.js
3610 bytesRaw
import { WorkerEntrypoint } from "cloudflare:workers";
import * as exports from "./index.js";

Error.stackTraceLimit = 100;

let criticalError = false;
function registerPanicHook() {
  if (exports.setPanicHook)
    exports.setPanicHook(function (message) {
      const panicError = new Error("Rust panic: " + message);
      console.error('Critical', panicError);
      $PANIC_CRITICAL_ERROR
    });
}

registerPanicHook();

let instanceId = 0;
function checkReinitialize() {
  if (criticalError) {
    console.log("Reinitializing Wasm application");
    exports.__wbg_reset_state();
    criticalError = false;
    registerPanicHook();
    instanceId++;
  }
}

addEventListener('error', (e) => {
  handleMaybeCritical(e.error);
});

function handleMaybeCritical(e) {
  if (e instanceof WebAssembly.RuntimeError) {
    console.error('Critical', e);
    criticalError = true;
  }
}

class Entrypoint extends WorkerEntrypoint {}

$HANDLERS

const instanceProxyHooks = {
  set: (target, prop, value, receiver) => Reflect.set(target.instance, prop, value, receiver),
  has: (target, prop) => Reflect.has(target.instance, prop),
  deleteProperty: (target, prop) => Reflect.deleteProperty(target.instance, prop),
  apply: (target, thisArg, args) => Reflect.apply(target.instance, thisArg, args),
  construct: (target, args, newTarget) => Reflect.construct(target.instance, args, newTarget),
  getPrototypeOf: (target) => Reflect.getPrototypeOf(target.instance),
  setPrototypeOf: (target, proto) => Reflect.setPrototypeOf(target.instance, proto),
  isExtensible: (target) => Reflect.isExtensible(target.instance),
  preventExtensions: (target) => Reflect.preventExtensions(target.instance),
  getOwnPropertyDescriptor: (target, prop) => Reflect.getOwnPropertyDescriptor(target.instance, prop),
  defineProperty: (target, prop, descriptor) => Reflect.defineProperty(target.instance, prop, descriptor),
  ownKeys: (target) => Reflect.ownKeys(target.instance),
};

const classProxyHooks = {
  construct(ctor, args, newTarget) {
    try {
      checkReinitialize();
      const instance = {
        instance: Reflect.construct(ctor, args, newTarget),
        instanceId,
        ctor,
        args,
        newTarget
      };
      return new Proxy(instance, {
        ...instanceProxyHooks,
        get(target, prop, receiver) {
          if (target.instanceId !== instanceId) {
            target.instance = Reflect.construct(target.ctor, target.args, target.newTarget);
            target.instanceId = instanceId;
          }
          const original = Reflect.get(target.instance, prop, receiver);
          if (typeof original !== 'function') return original;
          if (original.constructor === Function) {
            return new Proxy(original, {
              apply(target, thisArg, argArray) {
                checkReinitialize();
                try {
                  return target.apply(thisArg, argArray);
                } catch (e) {
                  handleMaybeCritical(e);
                  throw e;
                }
              }
            });
          } else {
            return new Proxy(original, {
              async apply(target, thisArg, argArray) {
                checkReinitialize();
                try {
                  return await target.apply(thisArg, argArray);
                } catch (e) {
                  handleMaybeCritical(e);
                  throw e;
                }
              }
            });
          }
        }
      });
    } catch (e) {
      criticalError = true;
      throw e;
    }
  }
};

export default new Proxy(Entrypoint, classProxyHooks);