"use strict";

// To make it easier to follow, this code is arranged so that the functions are
// arranged in the order they are called.

const worker = new Worker("suspendTimeouts_worker.js");
worker.onerror = error => {
  const message = `error from worker: ${error.filename}:${error.lineno}: ${error.message}`;
  throw new Error(message);
};

// Create a message channel. Send one end to the worker, and return the other to
// the mochitest.
/* exported create_channel */
function create_channel() {
  const { port1, port2 } = new MessageChannel();
  info(`sending port to worker`);
  worker.postMessage({ mochitestPort: port1 }, [port1]);
  return port2;
}

// Provoke the worker into sending us a message, and then refuse to receive said
// message, causing it to be delayed for later delivery.
//
// The worker will also post a message to the MessagePort we sent it earlier.
// That message should not be delayed, as it is handled by the mochitest window,
// not the content window. Its receipt signals that the test can assume that the
// runnable for step 2) is in the main thread's event queue, so the test can
// prepare for step 3).
/* exported start_worker */
function start_worker() {
  worker.onmessage = handle_echo;

  // This should prevent worker.onmessage from being called, until
  // resumeTimeouts is called.
  //
  // This function is provided by test_suspendTimeouts.js.
  // eslint-disable-next-line no-undef
  suspendTimeouts();

  // The worker should echo this message back to us and to the mochitest.
  worker.postMessage("HALLOOOOOO"); // suitable message for echoing
  info(`posted message to worker`);
}

var resumeTimeouts_has_returned = false;

// Resume timeouts. After this call, the worker's message should not be
// delivered to our onmessage handler until control returns to the event loop.
/* exported resume_timeouts */
function resume_timeouts() {
  // This function is provided by test_suspendTimeouts.js.
  // eslint-disable-next-line no-undef
  resumeTimeouts(); // onmessage handlers should not run from this call.

  resumeTimeouts_has_returned = true;

  // When this JavaScript invocation returns to the main thread's event loop,
  // only then should onmessage handlers be invoked.
}

// The buggy code calls this handler from the resumeTimeouts call, before the
// main thread returns to the event loop. The correct code calls this only once
// the JavaScript invocation that called resumeTimeouts has run to completion.
function handle_echo({ data }) {
  ok(
    resumeTimeouts_has_returned,
    "worker message delivered from main event loop"
  );

  // Finish the mochitest.
  // This function is set and defined by test_suspendTimeouts.js
  // eslint-disable-next-line no-undef
  finish();
}
