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