File: src/com/google/javascript/jscomp/ProcessClosurePrimitives.java
Issue: Bug in require calls processing
The Problem

ProcessClosurePrimitives pass has a bug in processRequireCall method.
The method processes goog.require calls. If a require symbol is invalid i.e is not provided anywhere, the method collects it for further error reporting. If the require symbol is valid, the method removes it from the ast.

All invalid require calls must be left for further using/checking of the code! The related comment in the code confirms this.

Nevertheless, the second condition (requiresLevel.isOn() -> see source code) is invalid and always causes removing of the requires when we want to check these requires.

In any case, the method should not use the requiresLevel to decide if we need removing. The requiresLevel should be used to check if we need error reporting. 

The Solution

Remove the condition.
Please see the attached patch.

Buggy code:
private void processRequireCall(NodeTraversal t, Node n, Node parent) {
  Node left = n.getFirstChild();
  Node arg = left.getNext();
  if (verifyLastArgumentIsString(t, left, arg)) {
    String ns = arg.getString();
    ProvidedName provided = providedNames.get(ns);
    if (provided == null || !provided.isExplicitlyProvided()) {
      unrecognizedRequires.add(
          new UnrecognizedRequire(n, ns, t.getSourceName()));
    } else {
      JSModule providedModule = provided.explicitModule;

      // This must be non-null, because there was an explicit provide.
      Preconditions.checkNotNull(providedModule);

      JSModule module = t.getModule();
      if (moduleGraph != null &&
          module != providedModule &&
          !moduleGraph.dependsOn(module, providedModule)) {
        compiler.report(
            t.makeError(n, XMODULE_REQUIRE_ERROR, ns,
                providedModule.getName(),
                module.getName()));
      }
    }

    maybeAddToSymbolTable(left);
    maybeAddStringNodeToSymbolTable(arg);

    // Requires should be removed before further processing.
    // Some clients run closure pass multiple times, first with
    // the checks for broken requires turned off. In these cases, we
    // allow broken requires to be preserved by the first run to
    // let them be caught in the subsequent run.
    if (provided != null) {
      parent.detachFromParent();
      compiler.reportCodeChange();
    }
  }
}

Fixed code:
private void processRequireCall(NodeTraversal t, Node n, Node parent) {
  Node left = n.getFirstChild();
  Node arg = left.getNext();
  if (verifyLastArgumentIsString(t, left, arg)) {
    String ns = arg.getString();
    ProvidedName provided = providedNames.get(ns);
    if (provided == null || !provided.isExplicitlyProvided()) {
      unrecognizedRequires.add(
          new UnrecognizedRequire(n, ns, t.getSourceName()));
    } else {
      JSModule providedModule = provided.explicitModule;

      // This must be non-null, because there was an explicit provide.
      Preconditions.checkNotNull(providedModule);

      JSModule module = t.getModule();
      if (moduleGraph != null &&
          module != providedModule &&
          !moduleGraph.dependsOn(module, providedModule)) {
        compiler.report(
            t.makeError(n, XMODULE_REQUIRE_ERROR, ns,
                providedModule.getName(),
                module.getName()));
      }
    }

    maybeAddToSymbolTable(left);
    maybeAddStringNodeToSymbolTable(arg);

    // Requires should be removed before further processing.
    // Some clients run closure pass multiple times, first with
    // the checks for broken requires turned off. In these cases, we
    // allow broken requires to be preserved by the first run to
    // let them be caught in the subsequent run.
    if (provided != null || requiresLevel.isOn()) {
      parent.detachFromParent();
      compiler.reportCodeChange();
    }
  }
}