function createModule (name, testEnvironment, modifiers, suiteReport) {
  const parentModule = config._moduleStack.length
    ? config._moduleStack[config._moduleStack.length - 1]
    : null;
  const moduleName = parentModule !== null ? [parentModule.name, name].join(' > ') : name;

  const skip = (parentModule !== null && parentModule.skip) || modifiers.skip;
  const todo = (parentModule !== null && parentModule.todo) || modifiers.todo;

  const module = {
    name: moduleName,
    parentModule: parentModule,
    hooks: {
      before: [],
      beforeEach: [],
      afterEach: [],
      after: []
    },
    testEnvironment: extend(
      // Live inheritence as of QUnit 3. https://github.com/qunitjs/qunit/pull/1762
      (parentModule ? Object.create(parentModule.testEnvironment || {}) : {}),
      testEnvironment
    ),
    tests: [],
    moduleId: generateHash(moduleName),
    testsRun: 0,
    testsIgnored: 0,
    childModules: [],
    suiteReport: suiteReport || new SuiteReport(
      name,
      parentModule ? parentModule.suiteReport : globalSuiteReport
    ),

    // Initialised by test.js when the module start executing,
    // i.e. before the first test in this module (or a child).
    stats: null,

    // Pass along `skip` and `todo` properties from parent module, in case
    // there is one, to childs. And use own otherwise.
    // This property will be used to mark own tests and tests of child suites
    // as either `skipped` or `todo`.
    skip: skip,
    todo: skip ? false : todo,
    ignored: modifiers.ignored || false
  };

  if (parentModule) {
    parentModule.childModules.push(module);
  }

  config.modules.push(module);

  return module;
}
This does:
- Create a module object
- Link it to and from a parent module (if one is on the stack)
- Link it to a parent SuiteReport (if one is on the stack)
- Push it to `config.modules`

It does NOT push it to config._moduleStack. That's only relevant for
scoped modules, and is the responsibility of processModule().

@param {string} name
@param {Object} testEnvironment
@param {Object} modifiers
@param {SuiteReport} suiteReport Force the report, for use by the initial unnamedModule
@return {Object}