11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ciif (!common.hasCrypto)
41cb0ef41Sopenharmony_ci  common.skip('missing crypto');
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ciconst assert = require('assert');
71cb0ef41Sopenharmony_ciconst { createSecretKey, generateKeyPairSync, randomBytes } = require('crypto');
81cb0ef41Sopenharmony_ciconst { createContext } = require('vm');
91cb0ef41Sopenharmony_ciconst {
101cb0ef41Sopenharmony_ci  MessageChannel,
111cb0ef41Sopenharmony_ci  Worker,
121cb0ef41Sopenharmony_ci  moveMessagePortToContext,
131cb0ef41Sopenharmony_ci  parentPort
141cb0ef41Sopenharmony_ci} = require('worker_threads');
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_cifunction keyToString(key) {
171cb0ef41Sopenharmony_ci  let ret;
181cb0ef41Sopenharmony_ci  if (key.type === 'secret') {
191cb0ef41Sopenharmony_ci    ret = key.export().toString('hex');
201cb0ef41Sopenharmony_ci  } else {
211cb0ef41Sopenharmony_ci    ret = key.export({ type: 'pkcs1', format: 'pem' });
221cb0ef41Sopenharmony_ci  }
231cb0ef41Sopenharmony_ci  return ret;
241cb0ef41Sopenharmony_ci}
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci// Worker threads simply reply with their representation of the received key.
271cb0ef41Sopenharmony_ciif (process.env.HAS_STARTED_WORKER) {
281cb0ef41Sopenharmony_ci  return parentPort.once('message', ({ key }) => {
291cb0ef41Sopenharmony_ci    parentPort.postMessage(keyToString(key));
301cb0ef41Sopenharmony_ci  });
311cb0ef41Sopenharmony_ci}
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci// Don't use isMainThread to allow running this test inside a worker.
341cb0ef41Sopenharmony_ciprocess.env.HAS_STARTED_WORKER = 1;
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci// The main thread generates keys and passes them to worker threads.
371cb0ef41Sopenharmony_ciconst secretKey = createSecretKey(randomBytes(32));
381cb0ef41Sopenharmony_ciconst { publicKey, privateKey } = generateKeyPairSync('rsa', {
391cb0ef41Sopenharmony_ci  modulusLength: 1024
401cb0ef41Sopenharmony_ci});
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci// Get immutable representations of all keys.
431cb0ef41Sopenharmony_ciconst keys = [secretKey, publicKey, privateKey]
441cb0ef41Sopenharmony_ci             .map((key) => [key, keyToString(key)]);
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_cifor (const [key, repr] of keys) {
471cb0ef41Sopenharmony_ci  {
481cb0ef41Sopenharmony_ci    // Test 1: No context change.
491cb0ef41Sopenharmony_ci    const { port1, port2 } = new MessageChannel();
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci    port1.postMessage({ key });
521cb0ef41Sopenharmony_ci    assert.strictEqual(keyToString(key), repr);
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci    port2.once('message', common.mustCall(({ key }) => {
551cb0ef41Sopenharmony_ci      assert.strictEqual(keyToString(key), repr);
561cb0ef41Sopenharmony_ci    }));
571cb0ef41Sopenharmony_ci  }
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  {
601cb0ef41Sopenharmony_ci    // Test 2: Across threads.
611cb0ef41Sopenharmony_ci    const worker = new Worker(__filename);
621cb0ef41Sopenharmony_ci    worker.once('message', common.mustCall((receivedRepresentation) => {
631cb0ef41Sopenharmony_ci      assert.strictEqual(receivedRepresentation, repr);
641cb0ef41Sopenharmony_ci    }));
651cb0ef41Sopenharmony_ci    worker.on('disconnect', () => console.log('disconnect'));
661cb0ef41Sopenharmony_ci    worker.postMessage({ key });
671cb0ef41Sopenharmony_ci  }
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci  {
701cb0ef41Sopenharmony_ci    // Test 3: Across contexts (should not work).
711cb0ef41Sopenharmony_ci    const { port1, port2 } = new MessageChannel();
721cb0ef41Sopenharmony_ci    const context = createContext();
731cb0ef41Sopenharmony_ci    const port2moved = moveMessagePortToContext(port2, context);
741cb0ef41Sopenharmony_ci    assert(!(port2moved instanceof Object));
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci    // TODO(addaleax): Switch this to a 'messageerror' event once MessagePort
771cb0ef41Sopenharmony_ci    // implements EventTarget fully and in a cross-context manner.
781cb0ef41Sopenharmony_ci    port2moved.onmessageerror = common.mustCall((event) => {
791cb0ef41Sopenharmony_ci      assert.strictEqual(event.data.code,
801cb0ef41Sopenharmony_ci                         'ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE');
811cb0ef41Sopenharmony_ci    });
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci    port2moved.start();
841cb0ef41Sopenharmony_ci    port1.postMessage({ key });
851cb0ef41Sopenharmony_ci    port1.close();
861cb0ef41Sopenharmony_ci  }
871cb0ef41Sopenharmony_ci}
88