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