• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2const common = require('../common');
3if (!common.hasCrypto)
4  common.skip('missing crypto');
5
6const assert = require('assert');
7const { createSecretKey, generateKeyPairSync, randomBytes } = require('crypto');
8const { createContext } = require('vm');
9const {
10  MessageChannel,
11  Worker,
12  moveMessagePortToContext,
13  parentPort
14} = require('worker_threads');
15
16function keyToString(key) {
17  let ret;
18  if (key.type === 'secret') {
19    ret = key.export().toString('hex');
20  } else {
21    ret = key.export({ type: 'pkcs1', format: 'pem' });
22  }
23  return ret;
24}
25
26// Worker threads simply reply with their representation of the received key.
27if (process.env.HAS_STARTED_WORKER) {
28  return parentPort.once('message', ({ key }) => {
29    parentPort.postMessage(keyToString(key));
30  });
31}
32
33// Don't use isMainThread to allow running this test inside a worker.
34process.env.HAS_STARTED_WORKER = 1;
35
36// The main thread generates keys and passes them to worker threads.
37const secretKey = createSecretKey(randomBytes(32));
38const { publicKey, privateKey } = generateKeyPairSync('rsa', {
39  modulusLength: 1024
40});
41
42// Get immutable representations of all keys.
43const keys = [secretKey, publicKey, privateKey]
44             .map((key) => [key, keyToString(key)]);
45
46for (const [key, repr] of keys) {
47  {
48    // Test 1: No context change.
49    const { port1, port2 } = new MessageChannel();
50
51    port1.postMessage({ key });
52    assert.strictEqual(keyToString(key), repr);
53
54    port2.once('message', common.mustCall(({ key }) => {
55      assert.strictEqual(keyToString(key), repr);
56    }));
57  }
58
59  {
60    // Test 2: Across threads.
61    const worker = new Worker(__filename);
62    worker.once('message', common.mustCall((receivedRepresentation) => {
63      assert.strictEqual(receivedRepresentation, repr);
64    }));
65    worker.on('disconnect', () => console.log('disconnect'));
66    worker.postMessage({ key });
67  }
68
69  {
70    // Test 3: Across contexts (should not work).
71    const { port1, port2 } = new MessageChannel();
72    const context = createContext();
73    const port2moved = moveMessagePortToContext(port2, context);
74    assert(!(port2moved instanceof Object));
75
76    // TODO(addaleax): Switch this to a 'messageerror' event once MessagePort
77    // implements EventTarget fully and in a cross-context manner.
78    port2moved.onmessageerror = common.mustCall((event) => {
79      assert.strictEqual(event.data.code,
80                         'ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE');
81    });
82
83    port2moved.start();
84    port1.postMessage({ key });
85    port1.close();
86  }
87}
88