deno icon indicating copy to clipboard operation
deno copied to clipboard

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Message("missing field `isEval`")'

Open jeiea opened this issue 2 years ago • 0 comments
trafficstars

Reproducible steps

Environment

> deno --version
deno 1.30.0 (release, x86_64-pc-windows-msvc)
v8 10.9.194.5
typescript 4.9.4
OS: Windows_NT x64 10.0.22621 (Windows 11)
  1. Save the following as async_to_sync.ts
Code
const workerCode = `
addEventListener("message", invokeUserCode);

async function invokeUserCode(event: Event): Promise<void> {
  const [buffer, name, ...args] = (event as MessageEvent).data as [
    SharedArrayBuffer,
    string,
    ...unknown[],
  ];
  try {
    const view = new Int32Array(buffer);
    await (globalThis as unknown as Record<
      string,
      (...args: unknown[]) => Promise<unknown>
    >)[name](
      ...args,
    );
    await update();
    Atomics.notify(view, 0, 1);
  } catch (error) {
    console.log("errored", error);
    sendErrorJson(error, { buffer });
  }
}

function sendErrorJson(
  error: unknown,
  { buffer }: { buffer: SharedArrayBuffer },
): void {
  const json = JSON.stringify(error, Object.getOwnPropertyNames(error));
  const buf = new Uint8Array(buffer, 4);
  const encoder = new TextEncoder();
  const view = new Int32Array(buffer);
  for (let read = 0; read < json.length;) {
    const result = encoder.encodeInto(json.slice(read), buf);
    view[0] = result.written;
    console.log('notify');
    Atomics.notify(view, 0, 1);

    read += result.read;
    console.log('waitAsync, view[0]: {view[0]}');
    // waitAsync is usable
    // https://github.com/denoland/deno/issues/15358
    Atomics.wait(view, 0, result.written);
    console.log("waitAsync finish");
  }
  Atomics.store(view, 0, 0);
  Atomics.notify(view, 0, 1);
}
`;

export class AsyncToSync {
  readonly #worker: Worker;

  constructor(userAsyncCode: string) {
    const blob = new Blob([userAsyncCode, workerCode], {
      type: "text/typescript",
    });
    const url = URL.createObjectURL(blob);
    // const url = new URL("./async_worker.ts", import.meta.url);
    this.#worker = new Worker(url, { type: "module" });
  }

  run(name: string, ...args: unknown[]): void {
    const buffer = new SharedArrayBuffer(1024);
    const view = new Int32Array(buffer);
    this.#worker.postMessage([buffer, name, args]);

    Atomics.wait(view, 0, 0);
    console.log("first wait exit");
    throwIfError(view, buffer);
    console.log("not thrown");
  }

  terminate(): void {
    this.#worker.terminate();
  }
}

function throwIfError(view: Int32Array, buffer: SharedArrayBuffer): void {
  if (view[0] === 0) {
    return;
  }

  const decoder = new TextDecoder();
  const buf = new Uint8Array(buffer, 4, view[0]);
  const chunks: string[] = [];
  console.log(`throwIfError out view[0]: ${view[0]}`);
  while (view[0]) {
    chunks.push(decoder.decode(buf));
    Atomics.store(view, 0, -1);
    Atomics.notify(view, 0, 1);
    Atomics.wait(view, 0, -1);
  }

  const details = JSON.parse(chunks.join(""));
  console.log("asdf");
  throw Object.assign(new Error(details.message ?? "Worker error"), {
    ...details,
  });
}

if (import.meta.main) {
  const userCode = `
async function update(): Promise<void> {
  await new Promise((resolve) => setTimeout(resolve, 500));
}`;
  const runner = new AsyncToSync(userCode);
  console.time("runner");
  runner.run("update", 3);
  console.timeEnd("runner");
  runner.terminate();
}
  1. deno run async_to_sync.ts

Expected behavior

Never panick.

Actual behavior

deno run .\src\async_to_sync.ts
errored TypeError: globalThis[name] is not a function
    at invokeUserCode (blob:null/3db6d11d-481c-4ab0-9bd5-2f327b1d3e04:18:13)
    at innerInvokeEventListeners (deno:ext/web/02_event.js:776:9)
    at invokeEventListeners (deno:ext/web/02_event.js:816:7)
    at dispatch (deno:ext/web/02_event.js:685:11)
    at dispatchEvent (deno:ext/web/02_event.js:1066:14)
    at pollForMessages (deno:runtime/js/99_main.js:159:9)
notify
waitAsync, view[0]: {view[0]}
first wait exit
throwIfError out view[0]: 516
waitAsync finish
asdf

============================================================
Deno has panicked. This is a bug in Deno. Please report this
at https://github.com/denoland/deno/issues/new.
If you can reliably reproduce this panic, include the
reproduction steps and re-run with the RUST_BACKTRACE=1 env
var set and include the backtrace in your report.

Platform: windows x86_64
Version: 1.30.0
Args: ["C:\\ProgramData\\chocolatey\\lib\\deno\\deno.exe", "run", ".\\src\\async_to_sync.ts"]

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Message("missing field `isEval`")', core\error.rs:377:71
stack backtrace:
   0:     0x7ff7b136e936 - napi_release_threadsafe_function
   1:     0x7ff7b042006b - napi_release_threadsafe_function
   2:     0x7ff7b1348efa - napi_release_threadsafe_function
   3:     0x7ff7b1372cbb - napi_release_threadsafe_function
   4:     0x7ff7b13728b1 - napi_release_threadsafe_function
   5:     0x7ff7b13724bb - napi_release_threadsafe_function
   6:     0x7ff7b03241ac - napi_fatal_error
   7:     0x7ff7b1373508 - napi_release_threadsafe_function
   8:     0x7ff7b1373275 - napi_release_threadsafe_function
   9:     0x7ff7b13731bf - napi_release_threadsafe_function
  10:     0x7ff7b1373194 - napi_release_threadsafe_function
  11:     0x7ff7b2620d55 - CrashForExceptionInNonABICompliantCodeRange
  12:     0x7ff7b2621033 - CrashForExceptionInNonABICompliantCodeRange
  13:     0x7ff7b053aa81 - napi_release_threadsafe_function
  14:     0x7ff7b063d3ac - napi_release_threadsafe_function
  15:     0x7ff7b0650ad2 - napi_release_threadsafe_function
  16:     0x7ff7b0637684 - napi_release_threadsafe_function
  17:     0x7ff7b009d39a - napi_cancel_async_work
  18:     0x7ff7b00cbdb1 - napi_cancel_async_work
  19:     0x7ff7b0087a1c - napi_cancel_async_work
  20:     0x7ff7b004da8d - napi_cancel_async_work
  21:     0x7ff7b01052ca - napi_cancel_async_work
  22:     0x7ff7b02c4f60 - napi_fatal_error
  23:     0x7ff7b0305a76 - napi_fatal_error
  24:     0x7ff7b03296bd - napi_fatal_error
  25:     0x7ff7b0050fb1 - napi_cancel_async_work
  26:     0x7ff7afe8569e - <unknown>
  27:     0x7ff7b0324da1 - napi_fatal_error
  28:     0x7ff7afecfb33 - <unknown>
  29:     0x7ff7b039f524 - napi_release_threadsafe_function
  30:     0x7ff7b25d386c - CrashForExceptionInNonABICompliantCodeRange
  31:     0x7ffc2b7126bd - BaseThreadInitThunk
  32:     0x7ffc2d8edfb8 - RtlUserThreadStart

jeiea avatar Jan 28 '23 19:01 jeiea