11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ciconst assert = require('assert');
41cb0ef41Sopenharmony_ciconst fs = require('fs').promises;
51cb0ef41Sopenharmony_ciconst vm = require('vm');
61cb0ef41Sopenharmony_ciconst { MessageChannel, moveMessagePortToContext } = require('worker_threads');
71cb0ef41Sopenharmony_ciconst { once } = require('events');
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci(async function() {
101cb0ef41Sopenharmony_ci  const fh = await fs.open(__filename);
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci  const { port1, port2 } = new MessageChannel();
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ci  assert.throws(() => {
151cb0ef41Sopenharmony_ci    port1.postMessage(fh);
161cb0ef41Sopenharmony_ci  }, {
171cb0ef41Sopenharmony_ci    code: 'ERR_MISSING_TRANSFERABLE_IN_TRANSFER_LIST'
181cb0ef41Sopenharmony_ci  });
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ci  // Check that transferring FileHandle instances works.
211cb0ef41Sopenharmony_ci  assert.notStrictEqual(fh.fd, -1);
221cb0ef41Sopenharmony_ci  port1.postMessage(fh, [ fh ]);
231cb0ef41Sopenharmony_ci  assert.strictEqual(fh.fd, -1);
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci  const [ fh2 ] = await once(port2, 'message');
261cb0ef41Sopenharmony_ci  assert.strictEqual(Object.getPrototypeOf(fh2), Object.getPrototypeOf(fh));
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci  assert.deepStrictEqual(await fh2.readFile(), await fs.readFile(__filename));
291cb0ef41Sopenharmony_ci  await fh2.close();
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci  assert.rejects(() => fh.readFile(), { code: 'EBADF' });
321cb0ef41Sopenharmony_ci})().then(common.mustCall());
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci(async function() {
351cb0ef41Sopenharmony_ci  // Check that there is no crash if the message is never read.
361cb0ef41Sopenharmony_ci  const fh = await fs.open(__filename);
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci  const { port1 } = new MessageChannel();
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci  assert.notStrictEqual(fh.fd, -1);
411cb0ef41Sopenharmony_ci  port1.postMessage(fh, [ fh ]);
421cb0ef41Sopenharmony_ci  assert.strictEqual(fh.fd, -1);
431cb0ef41Sopenharmony_ci})().then(common.mustCall());
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci(async function() {
461cb0ef41Sopenharmony_ci  // Check that in the case of a context mismatch the message is discarded.
471cb0ef41Sopenharmony_ci  const fh = await fs.open(__filename);
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci  const { port1, port2 } = new MessageChannel();
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci  const ctx = vm.createContext();
521cb0ef41Sopenharmony_ci  const port2moved = moveMessagePortToContext(port2, ctx);
531cb0ef41Sopenharmony_ci  port2moved.onmessage = common.mustCall((msgEvent) => {
541cb0ef41Sopenharmony_ci    assert.strictEqual(msgEvent.data, 'second message');
551cb0ef41Sopenharmony_ci    port1.close();
561cb0ef41Sopenharmony_ci  });
571cb0ef41Sopenharmony_ci  // TODO(addaleax): Switch this to a 'messageerror' event once MessagePort
581cb0ef41Sopenharmony_ci  // implements EventTarget fully and in a cross-context manner.
591cb0ef41Sopenharmony_ci  port2moved.onmessageerror = common.mustCall((event) => {
601cb0ef41Sopenharmony_ci    assert.strictEqual(event.data.code,
611cb0ef41Sopenharmony_ci                       'ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE');
621cb0ef41Sopenharmony_ci  });
631cb0ef41Sopenharmony_ci  port2moved.start();
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci  assert.notStrictEqual(fh.fd, -1);
661cb0ef41Sopenharmony_ci  port1.postMessage(fh, [ fh ]);
671cb0ef41Sopenharmony_ci  assert.strictEqual(fh.fd, -1);
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci  port1.postMessage('second message');
701cb0ef41Sopenharmony_ci})().then(common.mustCall());
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci(async function() {
731cb0ef41Sopenharmony_ci  // Check that a FileHandle with a read in progress cannot be transferred.
741cb0ef41Sopenharmony_ci  const fh = await fs.open(__filename);
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  const { port1 } = new MessageChannel();
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci  const readPromise = fh.readFile();
791cb0ef41Sopenharmony_ci  assert.throws(() => {
801cb0ef41Sopenharmony_ci    port1.postMessage(fh, [fh]);
811cb0ef41Sopenharmony_ci  }, {
821cb0ef41Sopenharmony_ci    message: 'Cannot transfer FileHandle while in use',
831cb0ef41Sopenharmony_ci    name: 'DataCloneError'
841cb0ef41Sopenharmony_ci  });
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci  assert.deepStrictEqual(await readPromise, await fs.readFile(__filename));
871cb0ef41Sopenharmony_ci})().then(common.mustCall());
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci(async function() {
901cb0ef41Sopenharmony_ci  // Check that filehandles with a close in progress cannot be transferred.
911cb0ef41Sopenharmony_ci  const fh = await fs.open(__filename);
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci  const { port1 } = new MessageChannel();
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci  const closePromise = fh.close();
961cb0ef41Sopenharmony_ci  assert.throws(() => {
971cb0ef41Sopenharmony_ci    port1.postMessage(fh, [fh]);
981cb0ef41Sopenharmony_ci  }, {
991cb0ef41Sopenharmony_ci    message: 'Cannot transfer FileHandle while in use',
1001cb0ef41Sopenharmony_ci    name: 'DataCloneError'
1011cb0ef41Sopenharmony_ci  });
1021cb0ef41Sopenharmony_ci  await closePromise;
1031cb0ef41Sopenharmony_ci})().then(common.mustCall());
104