.
 * @param {string[]} exports - An array of exports.
 * @param {string} [url=''] - The URL of the module.
 * @param {(reflect: DynamicModuleReflect) => void} evaluate - The function to evaluate the module.
 * @typedef {object} DynamicModuleReflect
 * @property {string[]} imports - The imports of the module.
 * @property {string[]} exports - The exports of the module.
 * @property {(cb: (reflect: DynamicModuleReflect) => void) => void} onReady - Callback to evaluate the module.
 */
const createDynamicModule = (imports, exports, url = '', evaluate) => {
  debug('creating ESM facade for %s with exports: %j', url, exports);
  const source = `
${ArrayPrototypeJoin(ArrayPrototypeMap(imports, createImport), '\n')}
${ArrayPrototypeJoin(ArrayPrototypeMap(exports, createExport), '\n')}
import.meta.done();
`;
  const { registerModule, compileSourceTextModule } = require('internal/modules/esm/utils');
  const m = compileSourceTextModule(`${url}`, source);

  const readyfns = new SafeSet();
  /** @type {DynamicModuleReflect} */
  const reflect = {
    exports: { __proto__: null },
    onReady: (cb) => { readyfns.add(cb); },
  };

  if (imports.length) {
    reflect.imports = { __proto__: null };
  }
  registerModule(m, {
    __proto__: null,
    initializeImportMeta: (meta, wrap) => {
      meta.exports = reflect.exports;
      if (reflect.imports) {
        meta.imports = reflect.imports;
      }
      meta.done = () => {
        evaluate(reflect);
        reflect.onReady = (cb) => cb(reflect);
        for (const fn of readyfns) {
          readyfns.delete(fn);
          fn(reflect);
        }
      };
    },
  });

  return {
    module: m,
    reflect,
  };
};

module.exports = createDynamicModule;
