• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2const common = require('../common');
3const assert = require('assert');
4const fs = require('fs').promises;
5const vm = require('vm');
6const { MessageChannel, moveMessagePortToContext } = require('worker_threads');
7const { once } = require('events');
8
9(async function() {
10  const fh = await fs.open(__filename);
11
12  const { port1, port2 } = new MessageChannel();
13
14  assert.throws(() => {
15    port1.postMessage(fh);
16  }, {
17    // See the TODO about error code in node_messaging.cc.
18    code: 'ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST'
19  });
20
21  // Check that transferring FileHandle instances works.
22  assert.notStrictEqual(fh.fd, -1);
23  port1.postMessage(fh, [ fh ]);
24  assert.strictEqual(fh.fd, -1);
25
26  const [ fh2 ] = await once(port2, 'message');
27  assert.strictEqual(Object.getPrototypeOf(fh2), Object.getPrototypeOf(fh));
28
29  assert.deepStrictEqual(await fh2.readFile(), await fs.readFile(__filename));
30  await fh2.close();
31
32  assert.rejects(() => fh.readFile(), { code: 'EBADF' });
33})().then(common.mustCall());
34
35(async function() {
36  // Check that there is no crash if the message is never read.
37  const fh = await fs.open(__filename);
38
39  const { port1 } = new MessageChannel();
40
41  assert.notStrictEqual(fh.fd, -1);
42  port1.postMessage(fh, [ fh ]);
43  assert.strictEqual(fh.fd, -1);
44})().then(common.mustCall());
45
46(async function() {
47  // Check that in the case of a context mismatch the message is discarded.
48  const fh = await fs.open(__filename);
49
50  const { port1, port2 } = new MessageChannel();
51
52  const ctx = vm.createContext();
53  const port2moved = moveMessagePortToContext(port2, ctx);
54  port2moved.onmessage = common.mustCall((msgEvent) => {
55    assert.strictEqual(msgEvent.data, 'second message');
56    port1.close();
57  });
58  // TODO(addaleax): Switch this to a 'messageerror' event once MessagePort
59  // implements EventTarget fully and in a cross-context manner.
60  port2moved.onmessageerror = common.mustCall((event) => {
61    assert.strictEqual(event.data.code,
62                       'ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE');
63  });
64  port2moved.start();
65
66  assert.notStrictEqual(fh.fd, -1);
67  port1.postMessage(fh, [ fh ]);
68  assert.strictEqual(fh.fd, -1);
69
70  port1.postMessage('second message');
71})().then(common.mustCall());
72
73(async function() {
74  // Check that a FileHandle with a read in progress cannot be transferred.
75  const fh = await fs.open(__filename);
76
77  const { port1 } = new MessageChannel();
78
79  const readPromise = fh.readFile();
80  assert.throws(() => {
81    port1.postMessage(fh, [fh]);
82  }, {
83    message: 'Cannot transfer FileHandle while in use',
84    name: 'DataCloneError'
85  });
86
87  assert.deepStrictEqual(await readPromise, await fs.readFile(__filename));
88})().then(common.mustCall());
89
90(async function() {
91  // Check that filehandles with a close in progress cannot be transferred.
92  const fh = await fs.open(__filename);
93
94  const { port1 } = new MessageChannel();
95
96  const closePromise = fh.close();
97  assert.throws(() => {
98    port1.postMessage(fh, [fh]);
99  }, {
100    message: 'Cannot transfer FileHandle while in use',
101    name: 'DataCloneError'
102  });
103  await closePromise;
104})().then(common.mustCall());
105