#!/bin/sh
# Upstream targets the browser, so load the module in Node with a minimal
# window object and drive the sandbox the way pdf.js does: an init script that
# returns the message handler, code evaluated in the sandbox, then a message.
set -eu

work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT

cat > "$work/check.mjs" <<'JS'
import fs from "node:fs"

const errors = []
globalThis.window = {
  console: {log: () => {}, error: (...a) => errors.push(a.join(" ")), warn: () => {}},
  JSON,
  alert: m => errors.push("ALERT:" + m),
}

const dir = "/usr/share/javascript/pdfjs-quickjs"
const wasm = fs.readFileSync(dir + "/quickjs-eval.wasm")
const {default: QuickJS} = await import(dir + "/quickjs-eval.js")

// The glue is built with -s ENVIRONMENT=web and would fetch the payload;
// hand it the bytes instead.
const mod = await QuickJS({
  instantiateWasm(imports, success) {
    const instance = new WebAssembly.Instance(
      new WebAssembly.Module(wasm), imports)
    success(instance)
    return instance.exports
  },
  externalCall() {
    return null
  }
})

const arg = s => mod.stringToNewUTF8(s)

// The init script's value becomes the handler that commFun calls; it reports
// what it received by throwing, which the glue prints through window.console.
const init = `(function(name, data) {
  throw new Error("SEEN " + name + " " + globalThis.marker + " " + JSON.stringify(data));
})`
if (mod._init(arg(init), 0) !== 1)
  throw new Error(`init failed: ${errors.join(" | ")}`)

mod._evalInSandbox(arg("globalThis.marker = 42;"), 0)
mod._commFun(arg("ping"), arg('{"a":1}'))

const seen = errors.find(e => e.includes("SEEN"))
if (!seen)
  throw new Error(`the sandbox handler did not run: ${errors.join(" | ")}`)
if (!seen.includes('SEEN ping 42 {"a":1}'))
  throw new Error(`unexpected payload: ${seen}`)
console.log("evaluated code and passed a message through the sandbox")
JS

node "$work/check.mjs"
