Repository: google/closure-compiler
Pull request #1042 (2015-07-15 22:07:03)

CommonJS processing: Consider "module" scope
When rewriting a CommonJS module, only process `module.exports` when
`module` is not defined in current scope.

For example, if a function has a parameter `module`, references to `module.exports` should not be replaced with the new module name (e.g. `module$foobar`)

```
var foo = function (module) {
    module.exports = "foo";
};
module.exports = "bar";
```

https://groups.google.com/forum/#!topic/closure-compiler-discuss/AklSy5PNQ_I

concavelenz: Martin, does this conflict with these your proposed changes?
mprobst: It might merge conflict due to the change from `test(...)` to `testModules(...)`, but content wise it's fine.

Patch:
diff --git a/contrib/externs/angular-1.4.js b/contrib/externs/angular-1.4.js
index 138f56ef4..3ec4cfbdb 100644
--- a/contrib/externs/angular-1.4.js
+++ b/contrib/externs/angular-1.4.js
@@ -343,7 +343,7 @@ angular.LinkingFunctions.post = function(scope, iElement, iAttrs, controller) {
 
 /**
  * @typedef {{
- *   bindToController: (boolean|!Object<string, string>|undefined),
+ *   bindToController: (boolean|undefined),
  *   compile: (function(
  *       !angular.JQLite=, !angular.Attributes=, Function=)|undefined),
  *   controller: (angular.Injectable|string|undefined),
@@ -372,6 +372,85 @@ angular.LinkingFunctions.post = function(scope, iElement, iAttrs, controller) {
  */
 angular.Directive;
 
+/**
+ * @param {!angular.JQLite=} tElement
+ * @param {!angular.Attributes=} tAttrs
+ * @param {Function=} transclude
+ * @return {Function|angular.LinkingFunctions|undefined}
+ */
+angular.Directive.compile = function(tElement, tAttrs, transclude) {};
+
+angular.Directive.controller = function() {};
+
+/**
+ * @type {string|undefined}
+ */
+angular.Directive.controllerAs;
+
+/**
+ * @type {(
+ *   function(!angular.Scope=, !angular.JQLite=, !angular.Attributes=,
+ *     (!Object|!Array.<!Object>)=)|
+ *   !angular.LinkingFunctions|
+ *   undefined
+ * )}
+ */
+angular.Directive.link;
+
+/**
+ * @type {(string|undefined)}
+ */
+angular.Directive.name;
+
+/**
+ * @type {(number|undefined)}
+ */
+angular.Directive.priority;
+
+/**
+ * @type {(boolean|undefined)}
+ */
+angular.Directive.replace;
+
+/**
+ * @type {(string|Array.<string>|undefined)}
+ */
+angular.Directive.require;
+
+/**
+ * @type {(string|undefined)}
+ */
+angular.Directive.restrict;
+
+/**
+ * @type {(boolean|Object.<string, string>|undefined)}
+ */
+angular.Directive.scope;
+
+/**
+ * @type {(
+ *   string|
+ *   function(!angular.JQLite=,!angular.Attributes=): string|
+ *   undefined
+ * )}
+ */
+angular.Directive.template;
+
+/**
+ * @type {(string|function(!angular.JQLite=, !angular.Attributes=)|undefined)}
+ */
+angular.Directive.templateUrl;
+
+/**
+ * @type {(boolean|undefined)}
+ */
+angular.Directive.terminal;
+
+/**
+ * @type {(boolean|string|undefined)}
+ */
+angular.Directive.transclude;
+
 /**
  * @typedef {(Function|Array.<string|Function>)}
  */
@@ -449,11 +528,6 @@ angular.JQLite.prototype.css = function(nameOrObject, opt_value) {};
  */
 angular.JQLite.prototype.data = function(opt_key, opt_value) {};
 
-/**
- * @return {!angular.JQLite}
- */
-angular.JQLite.prototype.detach = function() {};
-
 /**
  * @param {number} index
  * @return {!angular.JQLite}
diff --git a/contrib/externs/chrome_extensions.js b/contrib/externs/chrome_extensions.js
index 5ff7fd43f..7e586b2c7 100644
--- a/contrib/externs/chrome_extensions.js
+++ b/contrib/externs/chrome_extensions.js
@@ -247,7 +247,69 @@ chrome.app.runtime.LaunchItem.prototype.entry;
 chrome.app.runtime.LaunchItem.prototype.type;
 
 
-/** @type {!ChromeObjectEvent} */
+
+/**
+ * @constructor
+ * @see http://developer.chrome.com/apps/app_runtime.html
+ */
+chrome.app.runtime.LaunchData = function() {};
+
+
+/** @type {string|undefined} */
+chrome.app.runtime.LaunchData.prototype.id;
+
+
+/** @type {!Array.<!chrome.app.runtime.LaunchItem>|undefined} */
+chrome.app.runtime.LaunchData.prototype.items;
+
+
+/** @type {string|undefined} */
+chrome.app.runtime.LaunchData.prototype.url;
+
+
+/** @type {string|undefined} */
+chrome.app.runtime.LaunchData.prototype.referrerUrl;
+
+
+/** @type {boolean|undefined} */
+chrome.app.runtime.LaunchData.prototype.isKioskSession;
+
+
+
+/**
+ * The type of chrome.app.runtime.onLaunched.
+ * @constructor
+ */
+chrome.app.runtime.LaunchEvent = function() {};
+
+
+/**
+ * @param {function(!chrome.app.runtime.LaunchData)} callback
+ * @see http://developer.chrome.com/apps/app.runtime.html#event-onLaunched
+ */
+chrome.app.runtime.LaunchEvent.prototype.addListener = function(callback) {};
+
+
+/**
+ * @param {function(!chrome.app.runtime.LaunchData)} callback
+ */
+chrome.app.runtime.LaunchEvent.prototype.removeListener = function(callback) {};
+
+
+/**
+ * @param {function(!chrome.app.runtime.LaunchData)} callback
+ * @return {boolean}
+ */
+chrome.app.runtime.LaunchEvent.prototype.hasListener = function(callback) {};
+
+
+/**
+ * @return {boolean}
+ */
+chrome.app.runtime.LaunchEvent.prototype.hasListeners = function() {};
+
+
+/** @type {!chrome.app.runtime.LaunchEvent} */
 chrome.app.runtime.onLaunched;
 
 
diff --git a/contrib/externs/facebook_javascript_sdk.js b/contrib/externs/facebook_javascript_sdk.js
index 755550f70..71984b058 100644
--- a/contrib/externs/facebook_javascript_sdk.js
+++ b/contrib/externs/facebook_javascript_sdk.js
@@ -25,49 +25,49 @@ var FB = {};
 
 /**
  * @see http://developers.facebook.com/docs/reference/javascript/fb.getsession/
- * @return {Object<string,*>}
+ * @return {Object.<*,*>}
  */
 FB.getSession = function() { };
 
 /**
  * @see http://developers.facebook.com/docs/reference/javascript/fb.api/
  * @param {string} path
- * @param {(string|Object<string, *>|function(Object<string,*>))=} method
- * @param {(Object<string, *>|function(Object<string,*>))=} params
- * @param {function(Object<string,*>)=} callback
+ * @param {(string|Object.<string, *>|function(Object.<*,*>))=} method
+ * @param {(Object.<string, *>|function(Object.<*,*>))=} params
+ * @param {function(Object.<*,*>)=} callback
  */
 FB.api = function(path, method, params, callback) { };
 
 /**
  * @see http://developers.facebook.com/docs/reference/javascript/fb.getloginstatus/
- * @param {function(Object<string,*>)} callback
+ * @param {function(Object.<*,*>)} callback
  * @param {boolean=} force
  */
 FB.getLoginStatus = function(callback, force) {};
 
 /**
  * @see http://developers.facebook.com/docs/reference/javascript/fb.init/
- * @param {Object<string,*>=} opt_opts
+ * @param {Object.<string,*>=} opt_opts
  */
 FB.init = function(opt_opts) {};
 
 /**
  * @see http://developers.facebook.com/docs/reference/javascript/fb.login/
- * @param {function(Object<string,*>)} callback
- * @param {Object<string,*>=} opt_opts
+ * @param {function(Object.<*,*>)} callback
+ * @param {Object.<string,*>=} opt_opts
  */
 FB.login = function(callback, opt_opts) {};
 
 /**
  * @see http://developers.facebook.com/docs/reference/javascript/fb.logout/
- * @param {function(Object<string,*>)=} callback
+ * @param {function(Object.<*,*>)=} callback
  */
 FB.logout = function(callback) {};
 
 /**
  * @see http://developers.facebook.com/docs/reference/javascript/fb.ui/
- * @param {Object<string, *>} params
- * @param {function(Object<string,*>)=} callback
+ * @param {Object.<string, *>} params
+ * @param {function(Object.<*,*>)=} callback
  */
 FB.ui = function(params, callback) { };
 
@@ -77,14 +77,14 @@ FB.Event = {};
 /**
  * @see http://developers.facebook.com/docs/reference/javascript/fb.Event.subscribe/
  * @param {string} eventName
- * @param {function(Object<string,*>)} callback
+ * @param {function(Object.<*,*>)} callback
  */
 FB.Event.subscribe = function(eventName, callback) {};
 
 /**
  * @see http://developers.facebook.com/docs/reference/javascript/fb.Event.unsubscribe/
  * @param {string} eventName
- * @param {function(Object<string,*>)} callback
+ * @param {function(Object.<*,*>)} callback
  */
 FB.Event.unsubscribe = function(eventName, callback) {};
 
@@ -94,7 +94,7 @@ FB.XFBML = {};
 /**
  * @see http://developers.facebook.com/docs/reference/javascript/fb.XFBML.parse/
  * @param {Element=} node
- * @param {function(Object<string,*>)=} callback
+ * @param {function(Object.<*,*>)=} callback
  */
 FB.XFBML.parse = function(node, callback) {};
 
@@ -119,9 +119,9 @@ FB.Data.query = function(template, var_data) {};
 
 /**
  * @see http://developers.facebook.com/docs/reference/javascript/fb.data.waiton/
- * @param {Array<*>} dependencies
- * @param {function(Object<string,*>)} callback
- * @return {Object<string,*>}
+ * @param {Array.<*>} dependencies
+ * @param {function(Object.<*,*>)} callback
+ * @return {Object.<*,*>}
  */
 FB.Data.waitOn = function(dependencies, callback) {};
 
@@ -137,12 +137,12 @@ FB.Canvas.setAutoResize = function(onOrOff, interval) {};
 
 /**
  * @see http://developers.facebook.com/docs/reference/javascript/fb.Canvas.setSize/
- * @param {Object<string, number>} params
+ * @param {Object.<*, number>} params
  */
 FB.Canvas.setSize = function(params) {};
 
 /**
  * @see https://developers.facebook.com/docs/reference/javascript/FB.Canvas.getPageInfo/
- * @param {function(Object<string,*>)} callback
+ * @param {function(Object.<*,*>)} callback
  */
 FB.Canvas.getPageInfo = function(callback) {};
diff --git a/externs/html5.js b/externs/html5.js
index b5dc50ef1..c6c525ef2 100644
--- a/externs/html5.js
+++ b/externs/html5.js
@@ -512,16 +512,9 @@ function TextMetrics() {}
 TextMetrics.prototype.width;
 
 /**
- * @param {Uint8ClampedArray|number} dataOrWidth In the first form, this is the
- *     array of pixel data.  In the second form, this is the image width.
- * @param {number} widthOrHeight In the first form, this is the image width.  In
- *     the second form, this is the image height.
- * @param {number=} opt_height In the first form, this is the optional image
- *     height.  The second form omits this argument.
- * @see https://html.spec.whatwg.org/multipage/scripting.html#imagedata
  * @constructor
  */
-function ImageData(dataOrWidth, widthOrHeight, opt_height) {}
+function ImageData() {}
 
 /** @type {Uint8ClampedArray} */
 ImageData.prototype.data;
diff --git a/externs/w3c_css.js b/externs/w3c_css.js
index adde423a0..5bd5c8a63 100644
--- a/externs/w3c_css.js
+++ b/externs/w3c_css.js
@@ -2043,11 +2043,6 @@ Document.prototype.elementFromPoint = function(x, y) {};
  */
 Document.prototype.caretPositionFromPoint = function(x, y) {};
 
-/**
- * @type {Element}
- * @see http://dev.w3.org/csswg/cssom-view/#dom-document-scrollingelement
- */
-Document.prototype.scrollingElement;
 
 /**
  * @constructor
diff --git a/src/com/google/javascript/jscomp/AbstractCommandLineRunner.java b/src/com/google/javascript/jscomp/AbstractCommandLineRunner.java
index 13d7bb5bc..546fc691f 100644
--- a/src/com/google/javascript/jscomp/AbstractCommandLineRunner.java
+++ b/src/com/google/javascript/jscomp/AbstractCommandLineRunner.java
@@ -259,18 +259,7 @@ abstract class AbstractCommandLineRunner<A extends Compiler,
 
     if (config.warningGuards != null) {
       for (WarningGuardSpec.Entry entry : config.warningGuards.entries) {
-        if ("*".equals(entry.groupName)) {
-          Set<String> groupNames =
-              diagnosticGroups.getRegisteredGroups().keySet();
-          for (String groupName : groupNames) {
-            if (!DiagnosticGroups.wildcardExcludedGroups.contains(groupName)) {
-              diagnosticGroups.setWarningLevel(options, groupName, entry.level);
-            }
-          }
-        } else {
-          diagnosticGroups.setWarningLevel(options, entry.groupName,
-              entry.level);
-        }
+        diagnosticGroups.setWarningLevel(options, entry.groupName, entry.level);
       }
     }
 
@@ -389,6 +378,7 @@ abstract class AbstractCommandLineRunner<A extends Compiler,
       }
     }
 
+    options.acceptConstKeyword = config.acceptConstKeyword;
     options.transformAMDToCJSModules = config.transformAMDToCJSModules;
     options.processCommonJSModules = config.processCommonJSModules;
     options.commonJSModulePathPrefix = config.commonJSModulePathPrefix;
@@ -2012,6 +2002,16 @@ abstract class AbstractCommandLineRunner<A extends Compiler,
       return this;
     }
 
+    private boolean acceptConstKeyword = false;
+
+    /**
+     * Sets whether to accept usage of 'const' keyword.
+     */
+    CommandLineConfig setAcceptConstKeyword(boolean acceptConstKeyword) {
+      this.acceptConstKeyword = acceptConstKeyword;
+      return this;
+    }
+
     private String languageIn = "";
     private String languageOut = "";
 
diff --git a/src/com/google/javascript/jscomp/AbstractCompiler.java b/src/com/google/javascript/jscomp/AbstractCompiler.java
index df62c2e66..9330f67bd 100644
--- a/src/com/google/javascript/jscomp/AbstractCompiler.java
+++ b/src/com/google/javascript/jscomp/AbstractCompiler.java
@@ -267,6 +267,11 @@ public abstract class AbstractCompiler implements SourceExcerptProvider {
    */
   abstract boolean acceptEcmaScript5();
 
+  /**
+   * @return Whether the compiler accepts `const' keyword.
+   */
+  abstract boolean acceptConstKeyword();
+
   /**
    * Represents the different contexts for which the compiler could have
    * distinct configurations.
diff --git a/src/com/google/javascript/jscomp/AstValidator.java b/src/com/google/javascript/jscomp/AstValidator.java
index ed62a10e9..f4f0be69d 100644
--- a/src/com/google/javascript/jscomp/AstValidator.java
+++ b/src/com/google/javascript/jscomp/AstValidator.java
@@ -53,9 +53,7 @@ public final class AstValidator implements CompilerPass {
       @Override
       public void handleViolation(String message, Node n) {
         throw new IllegalStateException(
-            message + ". Reference node:\n" + n.toStringTree()
-            + "\n Parent node:\n"
-            + ((n.getParent() != null) ? n.getParent().toStringTree() : " no parent "));
+            message + ". Reference node:\n" + n.toStringTree());
       }
     });
   }
diff --git a/src/com/google/javascript/jscomp/CheckProvides.java b/src/com/google/javascript/jscomp/CheckProvides.java
index 0a961d4b3..cb5f5503c 100644
--- a/src/com/google/javascript/jscomp/CheckProvides.java
+++ b/src/com/google/javascript/jscomp/CheckProvides.java
@@ -77,16 +77,12 @@ class CheckProvides implements HotSwapCompilerPass {
         case Token.FUNCTION:
           visitFunctionNode(n, parent);
           break;
-        case Token.CLASS:
-          visitClassNode(n);
-          break;
         case Token.SCRIPT:
           visitScriptNode();
       }
     }
 
     private void visitFunctionNode(Node n, Node parent) {
-      // TODO(user): Use NodeUtil.getBestJSDocInfo/getFunctionName to recognize all functions.
       Node name = null;
       JSDocInfo info = parent.getJSDocInfo();
       if (info != null && info.isConstructor()) {
@@ -109,13 +105,6 @@ class CheckProvides implements HotSwapCompilerPass {
       }
     }
 
-    private void visitClassNode(Node classNode) {
-      String name = NodeUtil.getClassName(classNode);
-      if (name != null) {
-        ctors.put(name, classNode);
-      }
-    }
-
     private void visitScriptNode() {
       for (Map.Entry<String, Node> ctorEntry : ctors.entrySet()) {
         String ctor = ctorEntry.getKey();
diff --git a/src/com/google/javascript/jscomp/CheckRequiresForConstructors.java b/src/com/google/javascript/jscomp/CheckRequiresForConstructors.java
index 8e47a2c3e..9d32bce8a 100644
--- a/src/com/google/javascript/jscomp/CheckRequiresForConstructors.java
+++ b/src/com/google/javascript/jscomp/CheckRequiresForConstructors.java
@@ -20,6 +20,7 @@ import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableSet;
+import com.google.javascript.jscomp.NodeTraversal.Callback;
 import com.google.javascript.jscomp.NodeUtil.Visitor;
 import com.google.javascript.rhino.JSDocInfo;
 import com.google.javascript.rhino.JSTypeExpression;
@@ -48,25 +49,14 @@ import java.util.Set;
  * </ul>
  *
  */
-class CheckRequiresForConstructors implements HotSwapCompilerPass, NodeTraversal.Callback {
+class CheckRequiresForConstructors implements HotSwapCompilerPass {
   private final AbstractCompiler compiler;
   private final CodingConvention codingConvention;
 
-  private final Set<String> constructors = new HashSet<>();
-  private final Map<String, Node> requires = new HashMap<>();
-
-  // Adding an entry to usages indicates that the name is used and should be required.
-  private final Map<String, Node> usages = new HashMap<>();
-
-  // Adding an entry to weakUsages indicates that the name is used, but in a way which may not
-  // require a goog.require, such as in a @type annotation. If the only usages of a name are
-  // in weakUsages, don't give a missingRequire warning, nor an extraRequire warning.
-  private final Map<String, Node> weakUsages = new HashMap<>();
-
   // Warnings
-  static final DiagnosticType MISSING_REQUIRE_WARNING =
-      DiagnosticType.disabled(
-          "JSC_MISSING_REQUIRE_WARNING", "''{0}'' used but not goog.require''d");
+  static final DiagnosticType MISSING_REQUIRE_WARNING = DiagnosticType.disabled(
+      "JSC_MISSING_REQUIRE_WARNING",
+      "''{0}'' used but not goog.require''d");
 
   static final DiagnosticType EXTRA_REQUIRE_WARNING = DiagnosticType.disabled(
       "JSC_EXTRA_REQUIRE_WARNING",
@@ -86,12 +76,14 @@ class CheckRequiresForConstructors implements HotSwapCompilerPass, NodeTraversal
    */
   @Override
   public void process(Node externs, Node root) {
-    NodeTraversal.traverseRoots(compiler, this, externs, root);
+    Callback callback = new CheckRequiresForConstructorsCallback();
+    NodeTraversal.traverseRoots(compiler, callback, externs, root);
   }
 
   @Override
   public void hotSwapScript(Node scriptRoot, Node originalRoot) {
-    new NodeTraversal(compiler, this).traverse(scriptRoot);
+    Callback callback = new CheckRequiresForConstructorsCallback();
+    new NodeTraversal(compiler, callback).traverse(scriptRoot);
   }
 
   // Return true if the name is a class name (starts with an uppercase
@@ -115,6 +107,23 @@ class CheckRequiresForConstructors implements HotSwapCompilerPass, NodeTraversal
     return null;
   }
 
+  /**
+   * This class "records" each constructor and goog.require visited and creates
+   * a warning for each new node without an appropriate goog.require node.
+   *
+   */
+  private class CheckRequiresForConstructorsCallback implements Callback {
+    private final Set<String> constructors = new HashSet<>();
+    private final Map<String, Node> requires = new HashMap<>();
+
+    // Adding an entry to usages indicates that the name is used and should be required.
+    private final Map<String, Node> usages = new HashMap<>();
+
+    // Adding an entry to weakUsages indicates that the name is used, but in a way which may not
+    // require a goog.require, such as in a @type annotation. If the only usages of a name are
+    // in weakUsages, don't give a missingRequire warning, nor an extraRequire warning.
+    private final Map<String, Node> weakUsages = new HashMap<>();
+
     @Override
     public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
       return parent == null || !parent.isScript() || !t.getInput().isExtern();
@@ -408,4 +417,5 @@ class CheckRequiresForConstructors implements HotSwapCompilerPass, NodeTraversal
 
       NodeUtil.visitPreOrder(rootTypeNode, visitor, pred);
     }
+  }
 }
diff --git a/src/com/google/javascript/jscomp/CodeGenerator.java b/src/com/google/javascript/jscomp/CodeGenerator.java
index edb2f82b5..beb12a624 100644
--- a/src/com/google/javascript/jscomp/CodeGenerator.java
+++ b/src/com/google/javascript/jscomp/CodeGenerator.java
@@ -20,7 +20,6 @@ import static java.nio.charset.StandardCharsets.US_ASCII;
 
 import com.google.common.base.Preconditions;
 import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
-import com.google.javascript.rhino.JSDocInfo.Visibility;
 import com.google.javascript.rhino.Node;
 import com.google.javascript.rhino.Token;
 import com.google.javascript.rhino.TokenStream;
@@ -515,7 +514,6 @@ class CodeGenerator {
                   || n.getParent().isRecordType()
                   || n.getParent().isIndexSignature());
 
-          maybeAddAccessibilityModifier(n);
           if (n.isStaticMember()) {
             add("static ");
           }
@@ -960,7 +958,6 @@ class CodeGenerator {
         }
 
       case Token.COMPUTED_PROP:
-        maybeAddAccessibilityModifier(n);
         if (n.getBooleanProp(Node.COMPUTED_PROP_GETTER)) {
           add("get ");
         } else if (n.getBooleanProp(Node.COMPUTED_PROP_SETTER)) {
@@ -1271,13 +1268,6 @@ class CodeGenerator {
     }
   }
 
-  private void maybeAddAccessibilityModifier(Node n) {
-    Visibility access = (Visibility) n.getProp(Node.ACCESS_MODIFIER);
-    if (access != null) {
-      add(access.toString().toLowerCase() + " ");
-    }
-  }
-
   private void maybeAddTypeDecl(Node n) {
     if (n.getDeclaredTypeExpression() != null) {
       add(":");
diff --git a/src/com/google/javascript/jscomp/CollapseProperties.java b/src/com/google/javascript/jscomp/CollapseProperties.java
index 44db651de..e22373bd6 100644
--- a/src/com/google/javascript/jscomp/CollapseProperties.java
+++ b/src/com/google/javascript/jscomp/CollapseProperties.java
@@ -172,7 +172,7 @@ class CollapseProperties implements CompilerPass {
           } else if (ref.type == Type.ALIASING_GET
               && ref.scope.isGlobal()
               && ref.getTwin() == null) { // ignore aliases in chained assignments
-            if (inlineGlobalAliasIfPossible(name, ref, namespace)) {
+            if (inlineGlobalAliasIfPossible(ref, namespace)) {
               name.removeRef(ref);
             }
           }
@@ -201,19 +201,14 @@ class CollapseProperties implements CompilerPass {
    * @return Whether the alias was inlined.
    */
   private boolean inlineGlobalAliasIfPossible(
-      Name name, Ref alias, GlobalNamespace namespace) {
+      Ref alias, GlobalNamespace namespace) {
     // Ensure that the alias is assigned to global name at that the
     // declaration.
+
     Node aliasParent = alias.node.getParent();
-    if (aliasParent.isAssign() && NodeUtil.isExecutedExactlyOnce(aliasParent)
-        // We special-case for constructors here, to inline constructor aliases
-        // more aggressively in global scope.
-        // We do this because constructor properties are always collapsed,
-        // so we want to inline the aliases also to avoid breakages.
-        || aliasParent.isName() && name.isConstructor()) {
-      Node lvalue = aliasParent.isName() ? aliasParent : aliasParent.getFirstChild();
-      if (lvalue.isQualifiedName()) {
-        name = namespace.getSlot(lvalue.getQualifiedName());
+    if (aliasParent.isAssign() && NodeUtil.isExecutedExactlyOnce(aliasParent)) {
+      if (aliasParent.getFirstChild().isQualifiedName()) {
+        Name name = namespace.getSlot(aliasParent.getFirstChild().getQualifiedName());
         if (name != null && isInlinableGlobalAlias(name)) {
           List<AstChange> newNodes = new ArrayList<>();
 
@@ -636,7 +631,7 @@ class CollapseProperties implements CompilerPass {
       for (int i = 1; i < depth && n.hasChildren(); i++) {
         n = n.getFirstChild();
       }
-      if (n.isGetProp() && n.getFirstChild().isGetProp()) {
+      if (n.hasChildren()) {
         flattenNameRef(alias, n.getFirstChild(), n, originalName);
       }
     }
@@ -652,9 +647,6 @@ class CollapseProperties implements CompilerPass {
    */
   private void flattenNameRef(String alias, Node n, Node parent,
       String originalName) {
-    Preconditions.checkArgument(n.isGetProp(),
-        "Expected GETPROP, found %s. Node: %s", Token.name(n.getType()), n);
-
     // BEFORE:
     //   getprop
     //     getprop
diff --git a/src/com/google/javascript/jscomp/CommandLineRunner.java b/src/com/google/javascript/jscomp/CommandLineRunner.java
index 9e35a1bc2..e5672c9df 100644
--- a/src/com/google/javascript/jscomp/CommandLineRunner.java
+++ b/src/com/google/javascript/jscomp/CommandLineRunner.java
@@ -312,7 +312,7 @@ public class CommandLineRunner extends
         hidden = true,
         handler = WarningGuardErrorOptionHandler.class,
         usage = "Make the named class of warnings an error. Options:" +
-        DiagnosticGroups.DIAGNOSTIC_GROUP_NAMES + ". '*' adds all supported.")
+        DiagnosticGroups.DIAGNOSTIC_GROUP_NAMES)
     private List<String> jscompError = new ArrayList<>();
 
     // Used to define the flag, values are stored by the handler.
@@ -321,8 +321,7 @@ public class CommandLineRunner extends
         hidden = true,
         handler = WarningGuardWarningOptionHandler.class,
         usage = "Make the named class of warnings a normal warning. " +
-        "Options:" + DiagnosticGroups.DIAGNOSTIC_GROUP_NAMES +
-        ". '*' adds all supported.")
+        "Options:" + DiagnosticGroups.DIAGNOSTIC_GROUP_NAMES)
     private List<String> jscompWarning = new ArrayList<>();
 
     // Used to define the flag, values are stored by the handler.
@@ -331,7 +330,7 @@ public class CommandLineRunner extends
         hidden = true,
         handler = WarningGuardOffOptionHandler.class,
         usage = "Turn off the named class of warnings. Options:" +
-        DiagnosticGroups.DIAGNOSTIC_GROUP_NAMES + ". '*' adds all supported.")
+        DiagnosticGroups.DIAGNOSTIC_GROUP_NAMES)
     private List<String> jscompOff = new ArrayList<>();
 
     @Option(name = "--define",
@@ -503,6 +502,11 @@ public class CommandLineRunner extends
         usage = "Prints out a JSON file of dependencies between modules.")
     private String outputModuleDependencies = "";
 
+    @Option(name = "--accept_const_keyword",
+        hidden = true,
+        usage = "Allows usage of const keyword.")
+    private boolean acceptConstKeyword = false;
+
     // TODO(tbreisacher): Remove the "(experimental)" for ES6 when it's stable enough.
     @Option(name = "--language_in",
         hidden = true,
@@ -1075,6 +1079,7 @@ public class CommandLineRunner extends
           .setClosureEntryPoints(flags.closureEntryPoint)
           .setOutputManifest(ImmutableList.of(flags.outputManifest))
           .setOutputModuleDependencies(flags.outputModuleDependencies)
+          .setAcceptConstKeyword(flags.acceptConstKeyword)
           .setLanguageIn(flags.languageIn)
           .setLanguageOut(flags.languageOut)
           .setProcessCommonJSModules(flags.processCommonJsModules)
diff --git a/src/com/google/javascript/jscomp/Compiler.java b/src/com/google/javascript/jscomp/Compiler.java
index 50e2a5f2a..ce00e1791 100644
--- a/src/com/google/javascript/jscomp/Compiler.java
+++ b/src/com/google/javascript/jscomp/Compiler.java
@@ -347,10 +347,12 @@ public class Compiler extends AbstractCompiler {
     reconcileOptionsWithGuards();
 
     // Initialize the warnings guard.
-    this.warningsGuard =
-        new ComposeWarningsGuard(
-            new SuppressDocWarningsGuard(getDiagnosticGroups().getRegisteredGroups()),
-            options.getWarningsGuard());
+    List<WarningsGuard> guards = ImmutableList.of(
+        new SuppressDocWarningsGuard(
+            getDiagnosticGroups().getRegisteredGroups()),
+        options.getWarningsGuard());
+
+    this.warningsGuard = new ComposeWarningsGuard(guards);
   }
 
   /**
@@ -810,7 +812,10 @@ public class Compiler extends AbstractCompiler {
     // the client wanted since they probably meant to use their
     // own PassConfig object.
     Preconditions.checkNotNull(passes);
-    Preconditions.checkState(this.passes == null, "setPassConfig was already called");
+
+    if (this.passes != null) {
+      throw new IllegalStateException("this.passes has already been assigned");
+    }
     this.passes = passes;
   }
 
@@ -2125,6 +2130,12 @@ public class Compiler extends AbstractCompiler {
             "unexpected language mode: " + options.getLanguageIn());
     }
   }
+
+  @Override
+  public boolean acceptConstKeyword() {
+    return options.acceptConstKeyword;
+  }
+
   @Override
   Config getParserConfig(ConfigContext context) {
     if (parserConfig == null) {
@@ -2171,6 +2182,7 @@ public class Compiler extends AbstractCompiler {
         isIdeMode(),
         options.isParseJsDocDocumentation(),
         mode,
+        acceptConstKeyword(),
         options.extraAnnotationNames);
   }
 
diff --git a/src/com/google/javascript/jscomp/CompilerOptions.java b/src/com/google/javascript/jscomp/CompilerOptions.java
index 02562b414..7bde719fe 100644
--- a/src/com/google/javascript/jscomp/CompilerOptions.java
+++ b/src/com/google/javascript/jscomp/CompilerOptions.java
@@ -90,6 +90,11 @@ public class CompilerOptions implements Serializable {
     skipTranspilationAndCrash = value;
   }
 
+  /**
+   * Whether the compiler accepts the `const' keyword.
+   */
+  boolean acceptConstKeyword;
+
   /**
    * Whether the compiler accepts type syntax ({@code var foo: string;}).
    */
@@ -176,12 +181,12 @@ public class CompilerOptions implements Serializable {
   /** Checks that all symbols are defined */
   public boolean checkSymbols;
 
-  /**
-   * Deprecated. The checks that used to be controlled by this flag are now on by default,
-   * and this setter is a no-op. You can safely remove this call from your code.
-   */
-  @Deprecated
-  public void setAggressiveVarCheck(CheckLevel level) {}
+  public CheckLevel aggressiveVarCheck;
+
+  /** Checks for suspicious variable definitions and undefined variables */
+  public void setAggressiveVarCheck(CheckLevel level) {
+    this.aggressiveVarCheck = level;
+  }
 
   /** Checks for suspicious statements that have no effect */
   public boolean checkSuspiciousCode;
@@ -434,6 +439,9 @@ public class CompilerOptions implements Serializable {
   /** Collapses multiple variable declarations into one */
   public boolean collapseVariableDeclarations;
 
+  /** Group multiple variable declarations into one */
+  boolean groupVariableDeclarations;
+
   /**
    * Collapses anonymous function declarations into named function
    * declarations
@@ -963,6 +971,7 @@ public class CompilerOptions implements Serializable {
     languageOut = LanguageMode.NO_TRANSPILE;
 
     // Language variation
+    acceptConstKeyword = false;
     acceptTypeSyntax = false;
 
     // Checks
@@ -970,6 +979,7 @@ public class CompilerOptions implements Serializable {
     devMode = DevMode.OFF;
     checkDeterminism = false;
     checkSymbols = false;
+    aggressiveVarCheck = CheckLevel.OFF;
     checkSuspiciousCode = false;
     checkTypes = false;
     reportMissingOverride = CheckLevel.OFF;
@@ -1015,6 +1025,7 @@ public class CompilerOptions implements Serializable {
     removeUnusedLocalVars = false;
     aliasExternals = false;
     collapseVariableDeclarations = false;
+    groupVariableDeclarations = false;
     collapseAnonymousFunctions = false;
     aliasableStrings = Collections.emptySet();
     aliasStringsBlacklist = "";
@@ -1479,6 +1490,13 @@ public class CompilerOptions implements Serializable {
     this.chainCalls = value;
   }
 
+  /**
+   * If true, accept `const' keyword.
+   */
+  public void setAcceptConstKeyword(boolean value) {
+    this.acceptConstKeyword = value;
+  }
+
   /**
    * Enable run-time type checking, which adds JS type assertions for debugging.
    *
@@ -1928,6 +1946,10 @@ public class CompilerOptions implements Serializable {
     this.collapseVariableDeclarations = enabled;
   }
 
+  public void setGroupVariableDeclarations(boolean enabled) {
+    this.groupVariableDeclarations = enabled;
+  }
+
   public void setCollapseAnonymousFunctions(boolean enabled) {
     this.collapseAnonymousFunctions = enabled;
   }
@@ -2094,6 +2116,7 @@ public class CompilerOptions implements Serializable {
 
   public void setClosurePass(boolean closurePass) {
     this.closurePass = closurePass;
+    setAggressiveVarCheck(CheckLevel.ERROR);
   }
 
   public void setPreserveGoogRequires(boolean preserveGoogRequires) {
diff --git a/src/com/google/javascript/jscomp/ControlFlowAnalysis.java b/src/com/google/javascript/jscomp/ControlFlowAnalysis.java
index dbb7f86f4..d34d5b525 100644
--- a/src/com/google/javascript/jscomp/ControlFlowAnalysis.java
+++ b/src/com/google/javascript/jscomp/ControlFlowAnalysis.java
@@ -247,7 +247,6 @@ final class ControlFlowAnalysis implements Callback, CompilerPass {
     if (parent != null) {
       switch (parent.getType()) {
         case Token.FOR:
-        case Token.FOR_OF:
           // Only traverse the body of the for loop.
           return n == parent.getLastChild();
 
@@ -270,8 +269,6 @@ final class ControlFlowAnalysis implements Callback, CompilerPass {
         case Token.BREAK:
         case Token.EXPR_RESULT:
         case Token.VAR:
-        case Token.LET:
-        case Token.CONST:
         case Token.RETURN:
         case Token.THROW:
           return false;
@@ -303,7 +300,6 @@ final class ControlFlowAnalysis implements Callback, CompilerPass {
       case Token.DO:
         handleDo(n);
         return;
-      case Token.FOR_OF:
       case Token.FOR:
         handleFor(n);
         return;
@@ -394,21 +390,7 @@ final class ControlFlowAnalysis implements Callback, CompilerPass {
   }
 
   private void handleFor(Node forNode) {
-    if (NodeUtil.isForIn(forNode) || forNode.isForOf()) {
-      // We have:  for (index in collection) { body }
-      // or:       for (item of collection) { body }
-      Node item = forNode.getFirstChild();
-      Node collection = item.getNext();
-      Node body = collection.getNext();
-      // The collection behaves like init.
-      createEdge(collection, Branch.UNCOND, forNode);
-      // The edge that transfer control to the beginning of the loop body.
-      createEdge(forNode, Branch.ON_TRUE, computeFallThrough(body));
-      // The edge to end of the loop.
-      createEdge(forNode, Branch.ON_FALSE,
-          computeFollowNode(forNode, this));
-      connectToPossibleExceptionHandler(forNode, collection);
-    } else {
+    if (forNode.getChildCount() == 4) {
       // We have for (init; cond; iter) { body }
       Node init = forNode.getFirstChild();
       Node cond = init.getNext();
@@ -432,6 +414,19 @@ final class ControlFlowAnalysis implements Callback, CompilerPass {
       connectToPossibleExceptionHandler(init, init);
       connectToPossibleExceptionHandler(forNode, cond);
       connectToPossibleExceptionHandler(iter, iter);
+    } else {
+      // We have for (item in collection) { body }
+      Node item = forNode.getFirstChild();
+      Node collection = item.getNext();
+      Node body = collection.getNext();
+      // The collection behaves like init.
+      createEdge(collection, Branch.UNCOND, forNode);
+      // The edge that transfer control to the beginning of the loop body.
+      createEdge(forNode, Branch.ON_TRUE, computeFallThrough(body));
+      // The edge to end of the loop.
+      createEdge(forNode, Branch.ON_FALSE,
+          computeFollowNode(forNode, this));
+      connectToPossibleExceptionHandler(forNode, collection);
     }
   }
 
@@ -739,8 +734,7 @@ final class ControlFlowAnalysis implements Callback, CompilerPass {
           return computeFollowNode(fromNode, parent, cfa);
         }
       case Token.FOR:
-      case Token.FOR_OF:
-        if (parent.isForOf() || NodeUtil.isForIn(parent)) {
+        if (NodeUtil.isForIn(parent)) {
           return parent;
         } else {
           return parent.getFirstChild().getNext().getNext();
@@ -801,8 +795,7 @@ final class ControlFlowAnalysis implements Callback, CompilerPass {
       case Token.DO:
         return computeFallThrough(n.getFirstChild());
       case Token.FOR:
-      case Token.FOR_OF:
-        if (n.isForOf() || NodeUtil.isForIn(n)) {
+        if (NodeUtil.isForIn(n)) {
           return n.getFirstChild().getNext();
         }
         return computeFallThrough(n.getFirstChild());
@@ -925,7 +918,6 @@ final class ControlFlowAnalysis implements Callback, CompilerPass {
   public static boolean mayThrowException(Node n) {
     switch (n.getType()) {
       case Token.CALL:
-      case Token.TAGGED_TEMPLATELIT:
       case Token.GETPROP:
       case Token.GETELEM:
       case Token.THROW:
@@ -953,7 +945,6 @@ final class ControlFlowAnalysis implements Callback, CompilerPass {
   static boolean isBreakStructure(Node n, boolean labeled) {
     switch (n.getType()) {
       case Token.FOR:
-      case Token.FOR_OF:
       case Token.DO:
       case Token.WHILE:
       case Token.SWITCH:
@@ -973,7 +964,6 @@ final class ControlFlowAnalysis implements Callback, CompilerPass {
   static boolean isContinueStructure(Node n) {
     switch (n.getType()) {
       case Token.FOR:
-      case Token.FOR_OF:
       case Token.DO:
       case Token.WHILE:
         return true;
diff --git a/src/com/google/javascript/jscomp/DefaultPassConfig.java b/src/com/google/javascript/jscomp/DefaultPassConfig.java
index 45cfc81c4..2371989e9 100644
--- a/src/com/google/javascript/jscomp/DefaultPassConfig.java
+++ b/src/com/google/javascript/jscomp/DefaultPassConfig.java
@@ -203,11 +203,6 @@ public final class DefaultPassConfig extends PassConfig {
     // Verify JsDoc annotations
     checks.add(checkJsDoc);
 
-    if (options.getLanguageIn() == LanguageMode.ECMASCRIPT6_TYPED
-        && options.getLanguageOut() != LanguageMode.ECMASCRIPT6_TYPED) {
-      checks.add(convertEs6TypedToEs6);
-    }
-
     // Early ES6 transpilation.
     // Includes ES6 features that are straightforward to transpile.
     // We won't handle them natively in the rest of the compiler, so we always
@@ -228,13 +223,20 @@ public final class DefaultPassConfig extends PassConfig {
       checks.add(declaredGlobalExternsOnWindow);
     }
 
-    checks.add(checkVariableReferences);
+    if (options.getLanguageIn().isEs6OrHigher() || options.aggressiveVarCheck.isOn()) {
+      checks.add(checkVariableReferences);
+    }
 
     if (!options.skipNonTranspilationPasses && options.closurePass) {
       checks.add(closureGoogScopeAliases);
       checks.add(closureRewriteClass);
     }
 
+    if (options.getLanguageIn() == LanguageMode.ECMASCRIPT6_TYPED
+        && options.getLanguageOut() != LanguageMode.ECMASCRIPT6_TYPED) {
+      checks.add(convertEs6TypedToEs6);
+    }
+
     if (options.enables(DiagnosticGroups.MISSING_REQUIRE)
         || options.enables(DiagnosticGroups.EXTRA_REQUIRE)) {
       checks.add(checkRequires);
@@ -242,10 +244,6 @@ public final class DefaultPassConfig extends PassConfig {
 
     checks.add(checkSideEffects);
 
-    if (options.checkProvides.isOn() || options.enables(DiagnosticGroups.MISSING_PROVIDE)) {
-      checks.add(checkProvides);
-    }
-
     // Late ES6 transpilation.
     // Includes ES6 features that are best handled natively by the compiler.
     // As we convert more passes to handle these features, we will be moving the transpilation
@@ -282,6 +280,10 @@ public final class DefaultPassConfig extends PassConfig {
       checks.add(angularPass);
     }
 
+    if (options.checkProvides.isOn() || options.enables(DiagnosticGroups.MISSING_PROVIDE)) {
+      checks.add(checkProvides);
+    }
+
     // The following passes are more like "preprocessor" passes.
     // It's important that they run before most checking passes.
     // Perhaps this method should be renamed?
@@ -738,6 +740,10 @@ public final class DefaultPassConfig extends PassConfig {
       passes.add(renameVars);
     }
 
+    if (options.groupVariableDeclarations) {
+      passes.add(groupVariableDeclarations);
+    }
+
     // This pass should run after names stop changing.
     if (options.processObjectPropertyString) {
       passes.add(objectPropertyStringPostprocess);
@@ -1412,7 +1418,8 @@ public final class DefaultPassConfig extends PassConfig {
       new HotSwapPassFactory("checkVariableReferences", true) {
     @Override
     protected HotSwapCompilerPass create(AbstractCompiler compiler) {
-      return new VariableReferenceCheck(compiler);
+      return new VariableReferenceCheck(
+          compiler, options.aggressiveVarCheck);
     }
   };
 
@@ -2199,6 +2206,17 @@ public final class DefaultPassConfig extends PassConfig {
     }
   };
 
+  /**
+   * Simple global collapses of variable declarations.
+   */
+  private final PassFactory groupVariableDeclarations =
+      new PassFactory("groupVariableDeclarations", true) {
+    @Override
+    protected CompilerPass create(AbstractCompiler compiler) {
+      return new GroupVariableDeclarations(compiler);
+    }
+  };
+
   /**
    * Extracts common sub-expressions.
    */
diff --git a/src/com/google/javascript/jscomp/DiagnosticGroups.java b/src/com/google/javascript/jscomp/DiagnosticGroups.java
index afd32d8cc..c5e377591 100644
--- a/src/com/google/javascript/jscomp/DiagnosticGroups.java
+++ b/src/com/google/javascript/jscomp/DiagnosticGroups.java
@@ -18,7 +18,6 @@ package com.google.javascript.jscomp;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
 import com.google.javascript.jscomp.lint.CheckEmptyStatements;
 import com.google.javascript.jscomp.lint.CheckEnums;
 import com.google.javascript.jscomp.lint.CheckInterfaces;
@@ -29,7 +28,6 @@ import com.google.javascript.jscomp.newtypes.JSTypeCreatorFromJSDoc;
 
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Set;
 
 /**
  * Named groups of DiagnosticTypes exposed by Compiler.
@@ -39,9 +37,6 @@ public class DiagnosticGroups {
   static final DiagnosticType UNUSED =
       DiagnosticType.warning("JSC_UNUSED", "{0}");
 
-  public static final Set<String> wildcardExcludedGroups =
-      ImmutableSet.of("reportUnknownTypes");
-
   public DiagnosticGroups() {}
 
   private static final Map<String, DiagnosticGroup> groupsByName =
diff --git a/src/com/google/javascript/jscomp/Es6ConvertSuper.java b/src/com/google/javascript/jscomp/Es6ConvertSuper.java
index aea144a67..cb67cfade 100644
--- a/src/com/google/javascript/jscomp/Es6ConvertSuper.java
+++ b/src/com/google/javascript/jscomp/Es6ConvertSuper.java
@@ -188,7 +188,6 @@ public final class Es6ConvertSuper implements NodeTraversal.Callback, HotSwapCom
 
   @Override
   public void process(Node externs, Node root) {
-    NodeTraversal.traverse(compiler, externs, this);
     NodeTraversal.traverse(compiler, root, this);
   }
 
diff --git a/src/com/google/javascript/jscomp/Es6RenameVariablesInParamLists.java b/src/com/google/javascript/jscomp/Es6RenameVariablesInParamLists.java
index 2684f3837..33e2448b3 100644
--- a/src/com/google/javascript/jscomp/Es6RenameVariablesInParamLists.java
+++ b/src/com/google/javascript/jscomp/Es6RenameVariablesInParamLists.java
@@ -86,7 +86,6 @@ public final class Es6RenameVariablesInParamLists extends AbstractPostOrderCallb
 
   @Override
   public void process(Node externs, Node root) {
-    NodeTraversal.traverse(compiler, externs, this);
     NodeTraversal.traverse(compiler, root, this);
   }
 
diff --git a/src/com/google/javascript/jscomp/Es6RewriteArrowFunction.java b/src/com/google/javascript/jscomp/Es6RewriteArrowFunction.java
index 746d4f322..5658731d8 100644
--- a/src/com/google/javascript/jscomp/Es6RewriteArrowFunction.java
+++ b/src/com/google/javascript/jscomp/Es6RewriteArrowFunction.java
@@ -23,7 +23,7 @@ import com.google.javascript.rhino.Token;
  * Converts ES6 arrow functions to standard anonymous ES3 functions.
  */
 public class Es6RewriteArrowFunction extends NodeTraversal.AbstractPreOrderCallback
-    implements HotSwapCompilerPass {
+    implements CompilerPass {
 
   static final DiagnosticType THIS_REFERENCE_IN_ARROWFUNC_OF_OBJLIT = DiagnosticType.warning(
       "JSC_THIS_REFERENCE_IN_ARROWFUNC_OF_OBJLIT",
@@ -43,15 +43,9 @@ public class Es6RewriteArrowFunction extends NodeTraversal.AbstractPreOrderCallb
 
   @Override
   public void process(Node externs, Node root) {
-    NodeTraversal.traverse(compiler, externs, this);
     NodeTraversal.traverse(compiler, root, this);
   }
 
-  @Override
-  public void hotSwapScript(Node scriptRoot, Node originalRoot) {
-    NodeTraversal.traverse(compiler, scriptRoot, this);
-  }
-
   @Override
   public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
     switch (n.getType()) {
diff --git a/src/com/google/javascript/jscomp/Es6RewriteDestructuring.java b/src/com/google/javascript/jscomp/Es6RewriteDestructuring.java
index 799ceb340..dfa3bd945 100644
--- a/src/com/google/javascript/jscomp/Es6RewriteDestructuring.java
+++ b/src/com/google/javascript/jscomp/Es6RewriteDestructuring.java
@@ -23,7 +23,7 @@ import com.google.javascript.rhino.Token;
 /**
  * Rewrites ES6 destructuring patterns and default parameters to valid ES3 code.
  */
-public final class Es6RewriteDestructuring implements NodeTraversal.Callback, HotSwapCompilerPass {
+public final class Es6RewriteDestructuring implements NodeTraversal.Callback, CompilerPass {
   private final AbstractCompiler compiler;
 
   private static final String DESTRUCTURING_TEMP_VAR = "$jscomp$destructuring$var";
@@ -36,15 +36,9 @@ public final class Es6RewriteDestructuring implements NodeTraversal.Callback, Ho
 
   @Override
   public void process(Node externs, Node root) {
-    NodeTraversal.traverse(compiler, externs, this);
     NodeTraversal.traverse(compiler, root, this);
   }
 
-  @Override
-  public void hotSwapScript(Node scriptRoot, Node originalRoot) {
-    NodeTraversal.traverse(compiler, scriptRoot, this);
-  }
-
   @Override
   public boolean shouldTraverse(NodeTraversal nodeTraversal, Node n, Node parent) {
     switch (n.getType()) {
diff --git a/src/com/google/javascript/jscomp/Es6SplitVariableDeclarations.java b/src/com/google/javascript/jscomp/Es6SplitVariableDeclarations.java
index 9f706ee9c..28730a4c9 100644
--- a/src/com/google/javascript/jscomp/Es6SplitVariableDeclarations.java
+++ b/src/com/google/javascript/jscomp/Es6SplitVariableDeclarations.java
@@ -46,7 +46,6 @@ public final class Es6SplitVariableDeclarations extends
 
   @Override
   public void process(Node externs, Node root) {
-    NodeTraversal.traverse(compiler, externs, this);
     NodeTraversal.traverse(compiler, root, this);
   }
 
diff --git a/src/com/google/javascript/jscomp/Es6SyntacticScopeCreator.java b/src/com/google/javascript/jscomp/Es6SyntacticScopeCreator.java
index 9c967360b..24a1cbf75 100644
--- a/src/com/google/javascript/jscomp/Es6SyntacticScopeCreator.java
+++ b/src/com/google/javascript/jscomp/Es6SyntacticScopeCreator.java
@@ -17,8 +17,6 @@
 package com.google.javascript.jscomp;
 
 import com.google.common.base.Preconditions;
-import com.google.javascript.jscomp.SyntacticScopeCreator.DefaultRedeclarationHandler;
-import com.google.javascript.jscomp.SyntacticScopeCreator.RedeclarationHandler;
 import com.google.javascript.rhino.InputId;
 import com.google.javascript.rhino.Node;
 import com.google.javascript.rhino.Token;
@@ -217,6 +215,23 @@ class Es6SyntacticScopeCreator implements ScopeCreator {
     }
   }
 
+  /**
+   * Interface for injectable duplicate handling.
+   */
+  interface RedeclarationHandler {
+    void onRedeclaration(
+        Scope s, String name, Node n, CompilerInput input);
+  }
+
+  /**
+   * The default handler for duplicate declarations.
+   */
+  private static class DefaultRedeclarationHandler implements RedeclarationHandler {
+    @Override
+    public void onRedeclaration(
+        Scope s, String name, Node n, CompilerInput input) {}
+  }
+
   private void declareVar(Node n) {
     declareVar(scope, n);
   }
diff --git a/src/com/google/javascript/jscomp/Es6ToEs3ClassSideInheritance.java b/src/com/google/javascript/jscomp/Es6ToEs3ClassSideInheritance.java
index bd938d3e9..f20c172d2 100644
--- a/src/com/google/javascript/jscomp/Es6ToEs3ClassSideInheritance.java
+++ b/src/com/google/javascript/jscomp/Es6ToEs3ClassSideInheritance.java
@@ -62,7 +62,7 @@ import java.util.Set;
  *
  * @author mattloring@google.com (Matthew Loring)
  */
-public final class Es6ToEs3ClassSideInheritance implements HotSwapCompilerPass {
+public final class Es6ToEs3ClassSideInheritance implements CompilerPass {
 
   final AbstractCompiler compiler;
 
@@ -85,18 +85,10 @@ public final class Es6ToEs3ClassSideInheritance implements HotSwapCompilerPass {
   @Override
   public void process(Node externs, Node root) {
     FindStaticMembers findStaticMembers = new FindStaticMembers();
-    NodeTraversal.traverse(compiler, externs, findStaticMembers);
     NodeTraversal.traverse(compiler, root, findStaticMembers);
     processInherits(findStaticMembers.inheritsCalls);
   }
 
-  @Override
-  public void hotSwapScript(Node scriptRoot, Node originalRoot) {
-    FindStaticMembers findStaticMembers = new FindStaticMembers();
-    NodeTraversal.traverse(compiler, scriptRoot, findStaticMembers);
-    processInherits(findStaticMembers.inheritsCalls);
-  }
-
   private void processInherits(List<Node> inheritsCalls) {
     for (Node n : inheritsCalls) {
       Node parent = n.getParent();
diff --git a/src/com/google/javascript/jscomp/Es6ToEs3Converter.java b/src/com/google/javascript/jscomp/Es6ToEs3Converter.java
index 8340d0ec9..461abc4a8 100644
--- a/src/com/google/javascript/jscomp/Es6ToEs3Converter.java
+++ b/src/com/google/javascript/jscomp/Es6ToEs3Converter.java
@@ -96,7 +96,6 @@ public final class Es6ToEs3Converter implements NodeTraversal.Callback, HotSwapC
 
   @Override
   public void process(Node externs, Node root) {
-    NodeTraversal.traverse(compiler, externs, this);
     NodeTraversal.traverse(compiler, root, this);
   }
 
diff --git a/src/com/google/javascript/jscomp/Es6TypedToEs6Converter.java b/src/com/google/javascript/jscomp/Es6TypedToEs6Converter.java
index dc4a382b4..e35f7e5da 100644
--- a/src/com/google/javascript/jscomp/Es6TypedToEs6Converter.java
+++ b/src/com/google/javascript/jscomp/Es6TypedToEs6Converter.java
@@ -20,7 +20,6 @@ import com.google.javascript.jscomp.Es6ToEs3Converter.ClassDeclarationMetadata;
 import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
 import com.google.javascript.rhino.IR;
 import com.google.javascript.rhino.JSDocInfo;
-import com.google.javascript.rhino.JSDocInfo.Visibility;
 import com.google.javascript.rhino.JSDocInfoBuilder;
 import com.google.javascript.rhino.JSTypeExpression;
 import com.google.javascript.rhino.Node;
@@ -56,10 +55,6 @@ public final class Es6TypedToEs6Converter
       "Currently only member variables are supported in record types, please consider "
           + "using interfaces instead.");
 
-  static final DiagnosticType COMPUTED_PROP_ACCESS_MODIFIER = DiagnosticType.error(
-      "JSC_UNSUPPORTED_ACCESS_MODIFIER",
-      "Accessibility is not checked on computed properties");
-
   private final AbstractCompiler compiler;
 
   Es6TypedToEs6Converter(AbstractCompiler compiler) {
@@ -68,7 +63,6 @@ public final class Es6TypedToEs6Converter
 
   @Override
   public void process(Node externs, Node scriptRoot) {
-    NodeTraversal.traverse(compiler, externs, this);
     NodeTraversal.traverse(compiler, scriptRoot, this);
   }
 
@@ -108,7 +102,7 @@ public final class Es6TypedToEs6Converter
         visitTypeAlias(t, n, parent);
         break;
       case Token.DECLARE:
-        visitAmbientDeclaration(n);
+        visitAmbientDeclaration(n, parent);
         break;
       default:
     }
@@ -127,7 +121,7 @@ public final class Es6TypedToEs6Converter
           return;
         }
       }
-      name.removeProp(Node.GENERIC_TYPE_LIST);
+      name.putProp(Node.GENERIC_TYPE_LIST, null);
       jsDocNode.setJSDocInfo(doc.build());
     }
   }
@@ -140,7 +134,7 @@ public final class Es6TypedToEs6Converter
         Node type = convertWithLocation(child);
         doc.recordImplementedInterface(new JSTypeExpression(type, n.getSourceFileName()));
       }
-      n.removeProp(Node.IMPLEMENTS);
+      n.putProp(Node.IMPLEMENTS, null);
     }
 
     Node classMembers = n.getLastChild();
@@ -154,7 +148,6 @@ public final class Es6TypedToEs6Converter
 
       // Functions are handled by the regular Es6ToEs3Converter
       if (!member.isMemberVariableDef() && !member.getBooleanProp(Node.COMPUTED_PROP_VARIABLE)) {
-        maybeAddVisibility(member);
         continue;
       }
 
@@ -232,8 +225,6 @@ public final class Es6TypedToEs6Converter
             prototypeAcess);
     // Copy type information.
     maybeVisitColonType(member, member);
-    maybeAddVisibility(member);
-
     qualifiedMemberAccess.setJSDocInfo(member.getJSDocInfo());
     Node newNode = NodeUtil.newExpr(qualifiedMemberAccess);
     return newNode.useSourceInfoIfMissingFromForTree(member);
@@ -269,16 +260,10 @@ public final class Es6TypedToEs6Converter
     compiler.reportCodeChange();
   }
 
-  private void maybeAddVisibility(Node n) {
-    Visibility access = (Visibility) n.getProp(Node.ACCESS_MODIFIER);
-    if (access != null) {
-      if (n.isComputedProp()) {
-        compiler.report(JSError.make(n, COMPUTED_PROP_ACCESS_MODIFIER));
-      }
-      JSDocInfoBuilder memberDoc = JSDocInfoBuilder.maybeCopyFrom(n.getJSDocInfo());
-      memberDoc.recordVisibility(access);
-      n.setJSDocInfo(memberDoc.build());
-      n.removeProp(Node.ACCESS_MODIFIER);
+  private void maybeClearColonType(Node n, boolean hasColonType) {
+    if (hasColonType) {
+      n.setDeclaredTypeExpression(null);
+      compiler.reportCodeChange();
     }
   }
 
@@ -313,10 +298,7 @@ public final class Es6TypedToEs6Converter
     info = builder.build();
     jsDocNode.setJSDocInfo(info);
 
-    if (hasColonType) {
-      n.setDeclaredTypeExpression(null);
-      compiler.reportCodeChange();
-    }
+    maybeClearColonType(n, hasColonType);
   }
 
   private void visitTypeAlias(NodeTraversal t, Node n, Node parent) {
@@ -334,9 +316,10 @@ public final class Es6TypedToEs6Converter
     compiler.reportCodeChange();
   }
 
-  private void visitAmbientDeclaration(Node n) {
+  private void visitAmbientDeclaration(Node n, Node parent) {
     Node child = n.removeFirstChild();
     JSDocInfoBuilder builder = JSDocInfoBuilder.maybeCopyFrom(child.getJSDocInfo());
+    builder.addSuppression("duplicate");
     switch (child.getType()) {
       case Token.FUNCTION:
         child.replaceChild(child.getLastChild(), IR.block().useSourceInfoFrom(child));
@@ -351,10 +334,6 @@ public final class Es6TypedToEs6Converter
           }
         }
         break;
-      case Token.ENUM:
-      case Token.VAR:
-        builder.addSuppression("duplicate");
-        break;
       case Token.LET:
         child.setType(Token.VAR);
         break;
@@ -365,8 +344,7 @@ public final class Es6TypedToEs6Converter
     }
     child.setJSDocInfo(builder.build());
 
-    n.detachFromParent();
-    compiler.getSynthesizedExternsInput().getAstRoot(compiler).addChildToBack(child);
+    parent.replaceChild(n, child);
     compiler.reportCodeChange();
   }
 
diff --git a/src/com/google/javascript/jscomp/ExternExportsPass.java b/src/com/google/javascript/jscomp/ExternExportsPass.java
index e77a733e8..5c01e4815 100644
--- a/src/com/google/javascript/jscomp/ExternExportsPass.java
+++ b/src/com/google/javascript/jscomp/ExternExportsPass.java
@@ -73,8 +73,8 @@ final class ExternExportsPass extends NodeTraversal.AbstractPostOrderCallback
     protected final Node value;
 
     Export(String symbolName, Node value) {
-      this.symbolName = Preconditions.checkNotNull(symbolName);
-      this.value = Preconditions.checkNotNull(value);
+      this.symbolName = symbolName;
+      this.value = value;
     }
 
     /**
@@ -329,7 +329,7 @@ final class ExternExportsPass extends NodeTraversal.AbstractPostOrderCallback
     public PropertyExport(String exportPath, String symbolName, Node value) {
       super(symbolName, value);
 
-      this.exportPath = Preconditions.checkNotNull(exportPath);
+      this.exportPath = exportPath;
     }
 
     @Override
@@ -528,11 +528,12 @@ final class ExternExportsPass extends NodeTraversal.AbstractPostOrderCallback
 
     String constructorName = NodeUtil.getFunctionName(constructorNode);
     String propertyName = definitionNode.getLastChild().getString();
-    String prototypeName = constructorName + ".prototype";
-    Node propertyNameNode = NodeUtil.newQName(compiler, "this." + propertyName);
 
     // Add the export to the list.
-    this.exports.add(new PropertyExport(prototypeName, propertyName, propertyNameNode));
+    this.exports.add(
+        new PropertyExport(constructorName + ".prototype",
+                           propertyName,
+                           NodeUtil.getRValueOfLValue(definitionNode)));
   }
 
 }
diff --git a/src/com/google/javascript/jscomp/FindExportableNodes.java b/src/com/google/javascript/jscomp/FindExportableNodes.java
index ca30af123..887b375a3 100644
--- a/src/com/google/javascript/jscomp/FindExportableNodes.java
+++ b/src/com/google/javascript/jscomp/FindExportableNodes.java
@@ -83,18 +83,6 @@ class FindExportableNodes extends AbstractPostOrderCallback {
           }
           break;
 
-        case Token.CLASS:
-          if (parent.isScript()) {
-            export = NodeUtil.getClassName(n);
-            context = new GenerateNodeContext(n, Mode.EXPORT);
-          }
-          break;
-
-        case Token.MEMBER_FUNCTION_DEF:
-          export = n.getString();
-          context = new GenerateNodeContext(n, Mode.EXPORT);
-          break;
-
         case Token.ASSIGN:
           Node grandparent = parent.getParent();
           if (parent.isExprResult() &&
diff --git a/src/com/google/javascript/jscomp/GenerateExports.java b/src/com/google/javascript/jscomp/GenerateExports.java
index 1de6d9660..bfab82e5a 100644
--- a/src/com/google/javascript/jscomp/GenerateExports.java
+++ b/src/com/google/javascript/jscomp/GenerateExports.java
@@ -107,11 +107,6 @@ class GenerateExports implements CompilerPass {
           && parentNode.getLastChild().getString().equals(PROTOTYPE_PROPERTY)) {
         grandparent = parentNode.getFirstChild().getQualifiedName();
       }
-    } else if (node.getParent().isMemberFunctionDef()) {
-      Node classNode = node.getParent().getParent().getParent();
-      parent = NodeUtil.getClassName(classNode);
-      parent += node.getParent().isStaticMember() ? "" : ".prototype";
-      export = parent + "." + export;
     }
 
     boolean useExportSymbol = true;
@@ -120,8 +115,6 @@ class GenerateExports implements CompilerPass {
       useExportSymbol = false;
     } else if (parent != null && exports.containsKey(parent)) {
       useExportSymbol = false;
-    } else if (node.getParent().isMemberFunctionDef()) {
-      useExportSymbol = false;
     }
 
     Node call;
@@ -197,12 +190,8 @@ class GenerateExports implements CompilerPass {
    * @return property name.
    */
   private static String getPropertyName(Node node) {
-    Preconditions.checkArgument(node.isGetProp() || node.getParent().isMemberFunctionDef());
-    if (node.isGetProp()) {
-      return node.getLastChild().getString();
-    } else {
-      return node.getParent().getString();
-    }
+    Preconditions.checkArgument(node.isGetProp());
+    return node.getLastChild().getString();
   }
 
   /** Lazily create a "new" externs root for undeclared variables. */
diff --git a/src/com/google/javascript/jscomp/GlobalNamespace.java b/src/com/google/javascript/jscomp/GlobalNamespace.java
index ae755b760..c9f17b964 100644
--- a/src/com/google/javascript/jscomp/GlobalNamespace.java
+++ b/src/com/google/javascript/jscomp/GlobalNamespace.java
@@ -1201,10 +1201,6 @@ class GlobalNamespace
     private static JSDocInfo getDocInfoForDeclaration(Ref ref) {
       if (ref.node != null) {
         Node refParent = ref.node.getParent();
-        if (refParent == null) {
-          // May happen when inlineAliases removes refs from the AST.
-          return null;
-        }
         switch (refParent.getType()) {
           case Token.FUNCTION:
           case Token.ASSIGN:
diff --git a/src/com/google/javascript/jscomp/GlobalTypeInfo.java b/src/com/google/javascript/jscomp/GlobalTypeInfo.java
index 6b0141cdc..fa587c11c 100644
--- a/src/com/google/javascript/jscomp/GlobalTypeInfo.java
+++ b/src/com/google/javascript/jscomp/GlobalTypeInfo.java
@@ -186,11 +186,11 @@ class GlobalTypeInfo implements CompilerPass {
           + "Expected: {0}\n"
           + "Found: {1}");
 
-  static final DiagnosticType NAMESPACE_MODIFIED_AFTER_FINALIZATION =
+  static final DiagnosticType NOMINAL_TYPE_MODIFIED_AFTER_FINALIZATION =
       DiagnosticType.warning(
-          "JSC_NAMESPACE_MODIFIED_AFTER_FINALIZATION",
-          "Cannot add more properties to namespace {0}."
-          + " The namespace (or one of its subtypes) has been assigned to a @const name: {1}.");
+          "JSC_NOMINAL_TYPE_MODIFIED_AFTER_FINALIZATION",
+          "Cannot add more properties to type {0}."
+          + " The type (or one of its subtypes) has been assigned to a @const name: {1}.");
 
   static final DiagnosticGroup ALL_DIAGNOSTICS = new DiagnosticGroup(
       ANONYMOUS_NOMINAL_TYPE,
@@ -210,7 +210,7 @@ class GlobalTypeInfo implements CompilerPass {
       LENDS_ON_BAD_TYPE,
       MALFORMED_ENUM,
       MISPLACED_CONST_ANNOTATION,
-      NAMESPACE_MODIFIED_AFTER_FINALIZATION,
+      NOMINAL_TYPE_MODIFIED_AFTER_FINALIZATION,
       REDECLARED_PROPERTY,
       SETTER_WITH_RETURN,
       STRUCTDICT_WITHOUT_CTOR,
@@ -510,7 +510,7 @@ class GlobalTypeInfo implements CompilerPass {
     }
 
     // Finalize nominal type once all properties are added.
-    rawType.finalize(constDeclNode);
+    rawType.finalizeNominalType(constDeclNode);
   }
 
   private void checkSuperProperty(
@@ -1011,8 +1011,6 @@ class GlobalTypeInfo implements CompilerPass {
       //   warnings.add(JSError.make(nameNode,
       //         VarCheck.UNDEFINED_VAR_ERROR, nameNode.getString()));
       // }
-
-      this.currentScope.declareUnknownTypes(warnings);
     }
 
     /**
@@ -1267,7 +1265,7 @@ class GlobalTypeInfo implements CompilerPass {
       }
       if (rawType.isFinalized()) {
         warnings.add(JSError.make(getProp,
-                NAMESPACE_MODIFIED_AFTER_FINALIZATION,
+                NOMINAL_TYPE_MODIFIED_AFTER_FINALIZATION,
                 rawType.getName(),
                 rawType.getConstDeclNode().toString()));
         return;
@@ -1330,7 +1328,7 @@ class GlobalTypeInfo implements CompilerPass {
       RawNominalType classType = currentScope.getNominalType(ctorQname);
       if (classType.isFinalized()) {
         warnings.add(JSError.make(getProp,
-                NAMESPACE_MODIFIED_AFTER_FINALIZATION,
+                NOMINAL_TYPE_MODIFIED_AFTER_FINALIZATION,
                 classType.getName(),
                 classType.getConstDeclNode().toString()));
         return;
@@ -1383,13 +1381,6 @@ class GlobalTypeInfo implements CompilerPass {
         return;
       }
       Namespace ns = currentScope.getNamespace(QualifiedName.fromNode(recv));
-      if (ns.isFinalized()) {
-        warnings.add(JSError.make(recv,
-                NAMESPACE_MODIFIED_AFTER_FINALIZATION,
-                ns.getName(),
-                ns.getConstDeclNode().toString()));
-        return;
-      }
       JSDocInfo jsdoc = NodeUtil.getBestJSDocInfo(declNode);
       JSType propDeclType = getDeclaredTypeOfNode(jsdoc, currentScope);
       boolean isConst = isConst(declNode);
@@ -1669,21 +1660,17 @@ class GlobalTypeInfo implements CompilerPass {
     // ProcessScope, so it's generally NOT safe to convert them to jstypes until
     // after ProcessScope is done.
     // So, we only do limited inference of namespace properties here.
-    // We finalize namespace types early if needed, and later warn if new
-    // properties are added to a namespace that is already finalized.
+    // We finalize nominal types early if needed, and later warn if new
+    // properties are added to a nominal type that is already finalized.
     private JSType simpleInferDeclaration(Declaration decl, Node constDeclNode) {
       if (decl == null) {
         return null;
       }
       if (constDeclNode != null) {
-        Namespace ns = decl.getNamespace();
-        if (ns != null) {
-          if (ns instanceof RawNominalType) {
-            checkAndFinalizeNominalType((RawNominalType) ns, constDeclNode);
-          } else {
-            ns.finalize(constDeclNode);
-          }
-          return ns.toJSType(commonTypes);
+        RawNominalType rawType = decl.getNominal();
+        if (rawType != null) {
+          checkAndFinalizeNominalType(rawType, constDeclNode);
+          return rawType.toJSType(commonTypes);
         }
       }
       if (decl.getTypeOfSimpleDecl() != null) {
@@ -2144,8 +2131,6 @@ class GlobalTypeInfo implements CompilerPass {
     }
 
     private void addUnknownTypeNames(List<String> names) {
-      // TODO(dimvar): if sm uses a goog.forwardDeclare in a local scope, give
-      // an error instead of crashing.
       Preconditions.checkState(this.isTopLevel());
       unknownTypeNames.addAll(names);
     }
@@ -2411,8 +2396,7 @@ class GlobalTypeInfo implements CompilerPass {
     private void addNamespace(Node qnameNode, boolean isFromExterns) {
       Preconditions.checkArgument(!isNamespace(qnameNode));
       if (qnameNode.isName()) {
-        String varName = qnameNode.getString();
-        localNamespaces.put(varName, new NamespaceLit(varName));
+        localNamespaces.put(qnameNode.getString(), new NamespaceLit());
         if (isFromExterns) {
           // We don't know the full type of a namespace until after we see all
           // its properties. But we want to add it to the externs, otherwise it
@@ -2600,17 +2584,8 @@ class GlobalTypeInfo implements CompilerPass {
       qualifiedEnums = null;
     }
 
-    private void declareUnknownTypes(WarningReporter warnings) {
-      for (String name : this.unknownTypeNames) {
-        declareUnknownType(QualifiedName.fromQualifiedString(name), warnings);
-      }
-    }
-
-    private void declareUnknownType(QualifiedName qname, WarningReporter warnings) {
+    private void declareUnknownType(QualifiedName qname) {
       if (qname.isIdentifier() || null == getNamespace(qname.getLeftmostName())) {
-        // TODO(dimvar): If the code before the return is deleted, no unit tests fail.
-        // That's because we consider the unknown type a global variable, which we type ?.
-        // Any reason to keep this code, or just delete it?
         String name = qname.getLeftmostName();
         if (!locals.containsKey(name)) {
           externs.put(name, JSType.UNKNOWN);
@@ -2625,30 +2600,23 @@ class GlobalTypeInfo implements CompilerPass {
       while (!props.isIdentifier() && !leftmost.hasSubnamespace(props.getAllButRightmost())) {
         props = props.getAllButRightmost();
       }
-      Namespace ns = props.isIdentifier()
-          ? leftmost : leftmost.getSubnamespace(props.getAllButRightmost());
-      if (!ns.isFinalized()) {
-        String pname = props.getRightmostName();
-        ns.addUndeclaredProperty(pname, null, JSType.UNKNOWN, /* isConst */ false);
-      } else {
-        Preconditions.checkNotNull(ns.getConstDeclNode(),
-            "Namespace %s was finalized incorrectly", ns.getName());
-        // ns was used as the rhs of an assign where the lhs is @const, but it
-        // contains an unknown type, so we can't infer its type correctly.
-        warnings.add(JSError.make(ns.getConstDeclNode(), COULD_NOT_INFER_CONST_TYPE));
-      }
+      Namespace ns =
+          props.isIdentifier() ? leftmost : leftmost.getSubnamespace(props.getAllButRightmost());
+      String pname = props.getRightmostName();
+      ns.addUndeclaredProperty(pname, null, JSType.UNKNOWN, /* isConst */ false);
     }
 
     private void removeTmpData() {
+      for (String name : unknownTypeNames) {
+        declareUnknownType(QualifiedName.fromQualifiedString(name));
+      }
       unknownTypeNames = ImmutableSet.of();
       JSTypes commonTypes = getCommonTypes();
       // For now, we put types of namespaces directly into the locals.
       // Alternatively, we could move this into NewTypeInference.initEdgeEnvs
       for (Map.Entry<String, NamespaceLit> entry : localNamespaces.entrySet()) {
         String name = entry.getKey();
-        NamespaceLit nslit = entry.getValue();
-        nslit.finalize(null);
-        JSType t = nslit.toJSType(commonTypes);
+        JSType t = entry.getValue().toJSType(commonTypes);
         // If it's a function namespace, add the function type to the result
         if (localFunDefs.containsKey(name)) {
           t = t.withFunction(
@@ -2662,9 +2630,7 @@ class GlobalTypeInfo implements CompilerPass {
         }
       }
       for (Map.Entry<String, EnumType> entry : localEnums.entrySet()) {
-        EnumType et = entry.getValue();
-        et.finalize(null);
-        locals.put(entry.getKey(), et.toJSType(commonTypes));
+        locals.put(entry.getKey(), entry.getValue().toJSType(commonTypes));
       }
       for (String typedefName : localTypedefs.keySet()) {
         locals.put(typedefName, JSType.UNDEFINED);
diff --git a/src/com/google/javascript/jscomp/GroupVariableDeclarations.java b/src/com/google/javascript/jscomp/GroupVariableDeclarations.java
new file mode 100644
index 000000000..d9a146211
--- /dev/null
+++ b/src/com/google/javascript/jscomp/GroupVariableDeclarations.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2010 The Closure Compiler Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.javascript.jscomp;
+
+import com.google.javascript.jscomp.NodeTraversal.ScopedCallback;
+import com.google.javascript.rhino.IR;
+import com.google.javascript.rhino.Node;
+
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * Groups multiple variable declarations (that may or may not be contiguous)
+ * in the same scope into a single one. i.e.
+ *
+ * <pre>
+ * var a, b = 10;
+ * f1();
+ * var c, d;
+ * ... some other code ...
+ * var x, y, z = 100;
+ * ... some other code ...
+ * var p = 200, q = 300;
+ * </pre>
+ *
+ * becomes:
+ *
+ * <pre>
+ * var a, b = 10, c, d, x, y, z;
+ * f1();
+ * ... some other code ...
+ * z = 100;
+ * ... some other code ...
+ * var p = 200, q = 300;
+ * </pre>
+ *
+ * This reduces the generated uncompressed code size.
+ *
+ * For any scope, we use the first VAR statement as the statement to collapse
+ * the other declarations into. For other VAR statements in the scope, we only
+ * consider ones that either (a) have no variable that is initialized in the
+ * the statement, or (b) have exactly one variable that is initialized (e.g.
+ * the "var x, y, z = 100;" statement in the example above. VAR statements
+ * with more than one variable initialization are not collapsed. This is
+ * because doing so would increase uncompressed code size.
+ *
+ */
+class GroupVariableDeclarations implements CompilerPass, ScopedCallback {
+  private final AbstractCompiler compiler;
+
+  GroupVariableDeclarations(AbstractCompiler compiler) {
+    this.compiler = compiler;
+  }
+
+  @Override
+  public void process(Node externs, Node root) {
+    NodeTraversal.traverse(compiler, root, this);
+  }
+
+  @Override
+  public void enterScope(NodeTraversal t) {
+    Set<Node> varNodes = new LinkedHashSet<>();
+    Iterator<Var> scopeVarIter = t.getScope().getVars();
+    while (scopeVarIter.hasNext()) {
+      Node parentNode = scopeVarIter.next().getParentNode();
+      if (parentNode.isVar()) {
+        varNodes.add(parentNode);
+      }
+    }
+    if (varNodes.size() <= 1) {
+      return;
+    }
+    Iterator<Node> varNodeIter = varNodes.iterator();
+    Node firstVarNode = varNodeIter.next();
+    while (varNodeIter.hasNext()) {
+      Node varNode = varNodeIter.next();
+      applyGroupingToVar(firstVarNode, varNode);
+    }
+  }
+
+  @Override
+  public void exitScope(NodeTraversal t) {
+  }
+
+  @Override
+  public boolean shouldTraverse(NodeTraversal nodeTraversal, Node n,
+                                Node parent) {
+    return true;
+  }
+
+  @Override
+  public void visit(NodeTraversal t, Node n, Node parent) {
+  }
+
+  /**
+   * Attempts to collapse groupVar. This can only happen if groupVar has at most
+   * one variable initialization (it may have multiple variable declarations).
+   * If successful, then detaches groupVar's children and appends them to
+   * firstVar
+   *
+   * @param firstVar The first VAR {@code Node} in that scope. This is the node
+   *                 that we want to collapse groupVar into
+   * @param groupVar The VAR {@code Node} that we want to try collapsing
+   *                 into the first VAR node of that scope
+   */
+  private void applyGroupingToVar(Node firstVar, Node groupVar) {
+    Node child = groupVar.getFirstChild();
+    // if some variable is initialized, then the corresponding NAME node will be
+    // stored here
+    Node initializedName = null;
+    while (child != null) {
+      if (child.hasChildren()) {
+        // check that no more than one var is initialized
+        if (initializedName != null) {
+          return;
+        }
+        initializedName = child;
+      }
+      child = child.getNext();
+    }
+
+    // we will be modifying the groupVar subtree so get its parent
+    Node groupVarParent = groupVar.getParent();
+
+
+    if (initializedName != null) {
+      if (NodeUtil.isForIn(groupVarParent)) {
+        // The target of the for-in expression must be an assignable expression.
+        return;
+      }
+
+      // we have an initialized var in the VAR node. We will replace the
+      // VAR node with an assignment.
+
+      // first create a detached childless clone of initializedName.
+      Node clone = initializedName.cloneNode();
+      // replace
+      groupVar.replaceChild(initializedName, clone);
+      // add the assignment now.
+      Node initializedVal = initializedName.removeFirstChild();
+      Node assignmentNode = IR.assign(initializedName, initializedVal);
+      if (groupVarParent.isFor()) {
+        // Handle For and For-In Loops specially. For these, we do not need
+        // to construct an EXPR_RESULT node.
+        groupVarParent.replaceChild(groupVar, assignmentNode);
+      } else {
+        Node exprNode = NodeUtil.newExpr(assignmentNode);
+        groupVarParent.replaceChild(groupVar, exprNode);
+      }
+    } else {
+      // There is no initialized var. But we need to handle FOR and
+      // FOR-IN loops specially
+      if (groupVarParent.isFor()) {
+        if (NodeUtil.isForIn(groupVarParent)) {
+          // In For-In loop, we replace the VAR node with a NAME node
+          Node nameNodeClone = groupVar.getFirstChild().cloneNode();
+          groupVarParent.replaceChild(groupVar, nameNodeClone);
+        } else {
+          // In For loop, we replace the VAR node with an EMPTY node
+          Node emptyNode = IR.empty();
+          groupVarParent.replaceChild(groupVar, emptyNode);
+        }
+      } else {
+        // we can safely remove the VAR node
+        groupVarParent.removeChild(groupVar);
+      }
+    }
+
+    Node children = groupVar.removeChildren();
+    firstVar.addChildrenToBack(children);
+
+    compiler.reportCodeChange();
+  }
+}
diff --git a/src/com/google/javascript/jscomp/NodeUtil.java b/src/com/google/javascript/jscomp/NodeUtil.java
index 61615ba81..ada369d77 100644
--- a/src/com/google/javascript/jscomp/NodeUtil.java
+++ b/src/com/google/javascript/jscomp/NodeUtil.java
@@ -124,12 +124,6 @@ public final class NodeUtil {
    */
   static TernaryValue getPureBooleanValue(Node n) {
     switch (n.getType()) {
-      case Token.TEMPLATELIT:
-        if (n.hasOneChild()) {
-          return TernaryValue.forBoolean(!n.getFirstChild().getString().isEmpty());
-        }
-        break;
-
       case Token.STRING:
         return TernaryValue.forBoolean(n.getString().length() > 0);
 
@@ -163,7 +157,6 @@ public final class NodeUtil {
 
       case Token.TRUE:
       case Token.REGEXP:
-      case Token.CLASS:
         return TernaryValue.TRUE;
 
       case Token.ARRAYLIT:
@@ -499,7 +492,6 @@ public final class NodeUtil {
    * <li>{@code &#123;name: function() ...&#125;}</li>
    * <li>{@code function name() ...}</li>
    * <li>{@code var name = function() ...}</li>
-   * <li>{@code var obj = {name() {} ...}}</li>
    * <li>{@code qualified.name = function() ...}</li>
    * <li>{@code var name2 = function name1() ...}</li>
    * <li>{@code qualified.name2 = function name1() ...}</li>
@@ -518,10 +510,9 @@ public final class NodeUtil {
       return name;
     }
 
-    // Check for the form { 'x' : function() { }} and {x() {}}
+    // Check for the form { 'x' : function() { } }
     Node parent = n.getParent();
     switch (parent.getType()) {
-      case Token.MEMBER_FUNCTION_DEF:
       case Token.SETTER_DEF:
       case Token.GETTER_DEF:
       case Token.STRING_KEY:
@@ -2076,8 +2067,13 @@ public final class NodeUtil {
       case Token.DO:
         return n.getLastChild();
       case Token.FOR:
-        return NodeUtil.isForIn(n) ? null : n.getFirstChild().getNext();
-      case Token.FOR_OF:
+        switch (n.getChildCount()) {
+          case 3:
+            return null;
+          case 4:
+            return n.getFirstChild().getNext();
+        }
+        throw new IllegalArgumentException("malformed 'for' statement " + n);
       case Token.CASE:
         return null;
     }
@@ -2109,7 +2105,7 @@ public final class NodeUtil {
           return false;
         }
         Node child = n.getFirstChild();
-        return child != null && !child.isScript(); // Optimization for empty blocks
+        return child != null && !child.isScript();
       case Token.FOR:
       case Token.FOR_OF:
         return true;
@@ -3662,8 +3658,8 @@ public final class NodeUtil {
         return getBestJSDocInfo(parent);
       } else if (isObjectLitKey(parent)) {
         return parent.getJSDocInfo();
-      } else if (parent.isFunction() || parent.isClass()) {
-        // FUNCTION and CLASS may be inside ASSIGN
+      } else if (parent.isFunction()) {
+        // FUNCTION may be inside ASSIGN
         return getBestJSDocInfo(parent);
       } else if (NodeUtil.isNameDeclaration(parent) && parent.hasOneChild()) {
         return parent.getJSDocInfo();
diff --git a/src/com/google/javascript/jscomp/ProcessCommonJSModules.java b/src/com/google/javascript/jscomp/ProcessCommonJSModules.java
index 4cbc4100f..802faff53 100644
--- a/src/com/google/javascript/jscomp/ProcessCommonJSModules.java
+++ b/src/com/google/javascript/jscomp/ProcessCommonJSModules.java
@@ -44,6 +44,7 @@ public final class ProcessCommonJSModules implements CompilerPass {
   private static final String MODULE_NAME_PREFIX = "module$";
 
   private static final String EXPORTS = "exports";
+  private static final String MODULE = "module";
 
   private final Compiler compiler;
   private final ES6ModuleLoader loader;
@@ -168,7 +169,13 @@ public final class ProcessCommonJSModules implements CompilerPass {
 
       if (n.isGetProp() &&
           "module.exports".equals(n.getQualifiedName())) {
-        moduleExportRefs.add(n);
+        Var v = t.getScope().getVar(MODULE);
+        // only rewrite "module.exports" if "module" is a free variable,
+        // meaning it is not defined in the current scope as a local
+        // variable or function parameter
+        if (v == null) {
+          moduleExportRefs.add(n);
+        }
       }
 
       if (n.isName() && EXPORTS.equals(n.getString())) {
diff --git a/src/com/google/javascript/jscomp/ReferenceCollectingCallback.java b/src/com/google/javascript/jscomp/ReferenceCollectingCallback.java
index 3668afb01..a388049c6 100644
--- a/src/com/google/javascript/jscomp/ReferenceCollectingCallback.java
+++ b/src/com/google/javascript/jscomp/ReferenceCollectingCallback.java
@@ -647,7 +647,7 @@ class ReferenceCollectingCallback implements ScopedCallback,
     private static boolean isDeclarationHelper(Node node) {
       Node parent = node.getParent();
 
-      // Special case for class B extends A, A is not a declaration.
+      // Special case for class B extends A, A is not a redeclaration.
       if (parent.isClass() && node != parent.getFirstChild()) {
         return false;
       }
@@ -672,11 +672,6 @@ class ReferenceCollectingCallback implements ScopedCallback,
         return isDeclarationHelper(parent);
       }
 
-      // Special case for arrow function
-      if (parent.isArrowFunction()) {
-        return node == parent.getFirstChild();
-      }
-
       return DECLARATION_PARENTS.contains(parent.getType());
     }
 
@@ -692,10 +687,6 @@ class ReferenceCollectingCallback implements ScopedCallback,
       return getParent().isConst();
     }
 
-    boolean isClassDeclaration() {
-      return getParent().isClass() && getNode() == getParent().getFirstChild();
-    }
-
     boolean isHoistedFunction() {
       return NodeUtil.isHoistedFunctionDeclaration(getParent());
     }
@@ -704,10 +695,11 @@ class ReferenceCollectingCallback implements ScopedCallback,
      * Determines whether the variable is initialized at the declaration.
      */
     boolean isInitializingDeclaration() {
-      // VAR and LET are the only types of variable declarations that may not initialize
-      // their variables. Catch blocks, named functions, and parameters all do.
-      return (isDeclaration() && !getParent().isVar() && !getParent().isLet())
-        || nameNode.getFirstChild() != null;
+      // VAR is the only type of variable declaration that may not initialize
+      // its variable. Catch blocks, named functions, and parameters all do.
+      return isDeclaration() &&
+          !getParent().isVar() ||
+          nameNode.getFirstChild() != null;
     }
 
    /**
@@ -755,7 +747,6 @@ class ReferenceCollectingCallback implements ScopedCallback,
           || (parentType == Token.CONST && nameNode.getFirstChild() != null)
           || parentType == Token.INC
           || parentType == Token.DEC
-          || parentType == Token.CATCH
           || (NodeUtil.isAssignmentOp(parent)
               && parent.getFirstChild() == nameNode)
           || isLhsOfForInExpression(nameNode);
diff --git a/src/com/google/javascript/jscomp/Scope.java b/src/com/google/javascript/jscomp/Scope.java
index a43032bce..a4c3028a1 100644
--- a/src/com/google/javascript/jscomp/Scope.java
+++ b/src/com/google/javascript/jscomp/Scope.java
@@ -173,11 +173,7 @@ public class Scope implements StaticScope {
       if (scope.vars.containsKey(name)) {
         return true;
       }
-
-      // In ES6, we create a separate "function parameter scope" above the function block scope to
-      // handle default parameters. Since nothing in the function block scope is allowed to shadow
-      // the variables in the function scope, we treat the two scopes as one in this method.
-      if (scope.isFunctionBlockScope() || (scope.parent != null && recurse)) {
+      if (scope.parent != null && recurse) {
         scope = scope.parent;
         continue;
       }
@@ -185,18 +181,6 @@ public class Scope implements StaticScope {
     }
   }
 
-  public boolean isDeclaredInFunction(String name) {
-    if (vars.containsKey(name)) {
-      return true;
-    }
-    Scope parent = getParent();
-    if (parent != null && parent.getRootNode().isFunction()
-        && parent.isDeclared(name, false)) {
-      return true;
-    }
-    return false;
-  }
-
   /**
    * Return an iterator over all of the variables declared in this scope.
    */
diff --git a/src/com/google/javascript/jscomp/SyntacticScopeCreator.java b/src/com/google/javascript/jscomp/SyntacticScopeCreator.java
index 5567b4abd..9b127442f 100644
--- a/src/com/google/javascript/jscomp/SyntacticScopeCreator.java
+++ b/src/com/google/javascript/jscomp/SyntacticScopeCreator.java
@@ -192,9 +192,10 @@ class SyntacticScopeCreator implements ScopeCreator {
   /**
    * The default handler for duplicate declarations.
    */
-  static class DefaultRedeclarationHandler implements RedeclarationHandler {
+  private static class DefaultRedeclarationHandler implements RedeclarationHandler {
     @Override
-    public void onRedeclaration(Scope s, String name, Node n, CompilerInput input) {}
+    public void onRedeclaration(
+        Scope s, String name, Node n, CompilerInput input) {}
   }
 
   /**
diff --git a/src/com/google/javascript/jscomp/TypeCheck.java b/src/com/google/javascript/jscomp/TypeCheck.java
index fd3e6aa22..9e70fe7fd 100644
--- a/src/com/google/javascript/jscomp/TypeCheck.java
+++ b/src/com/google/javascript/jscomp/TypeCheck.java
@@ -2218,16 +2218,6 @@ public final class TypeCheck implements NodeTraversal.Callback, CompilerPass {
         }
       }
     }
-    if (type.isOrdinaryFunction()) {
-      FunctionType function = type.toMaybeFunctionType();
-      for (Node parameter : function.getParameters()) {
-        JSType result = findObjectWithNonStringifiableKey(parameter.getJSType());
-        if (result != null) {
-          return result;
-        }
-      }
-      return findObjectWithNonStringifiableKey(function.getReturnType());
-    }
     return null;
   }
 
diff --git a/src/com/google/javascript/jscomp/Var.java b/src/com/google/javascript/jscomp/Var.java
index 1f34d5970..e73084eb6 100644
--- a/src/com/google/javascript/jscomp/Var.java
+++ b/src/com/google/javascript/jscomp/Var.java
@@ -185,20 +185,10 @@ public class Var implements StaticSlot, StaticRef {
     return declarationType() == Token.CONST;
   }
 
-  boolean isClass() {
-    return declarationType() == Token.CLASS;
-  }
-
   boolean isParam() {
     return declarationType() == Token.PARAM_LIST;
   }
 
-  boolean isDefaultParam() {
-    Node parent = nameNode.getParent();
-    return parent.getParent().isParamList() && parent.isDefaultValue()
-        && parent.getFirstChild() == nameNode;
-  }
-
   private int declarationType() {
     final Set<Integer> types = ImmutableSet.of(
         Token.VAR,
diff --git a/src/com/google/javascript/jscomp/VarCheck.java b/src/com/google/javascript/jscomp/VarCheck.java
index 9989c4501..09c6c2bb6 100644
--- a/src/com/google/javascript/jscomp/VarCheck.java
+++ b/src/com/google/javascript/jscomp/VarCheck.java
@@ -80,11 +80,6 @@ class VarCheck extends AbstractPostOrderCallback implements
         "JSC_VAR_ARGUMENTS_SHADOWED_ERROR",
         "Shadowing \"arguments\" is not allowed");
 
-  static final DiagnosticType LET_CONST_MULTIPLY_DECLARED_ERROR =
-      DiagnosticType.error(
-          "JSC_LET_CONST_MULTIPLY_DECLARED_ERROR",
-          "Duplicate let / const declaration in the same scope is not allowed.");
-
   // The arguments variable is special, in that it's declared in every local
   // scope, but not explicitly declared.
   private static final String ARGUMENTS = "arguments";
@@ -121,7 +116,7 @@ class VarCheck extends AbstractPostOrderCallback implements
   private ScopeCreator createScopeCreator() {
     if (compiler.getLanguageMode().isEs6OrHigher()) {
       // Redeclaration check is handled in VariableReferenceCheck for ES6
-      return new Es6SyntacticScopeCreator(compiler, new RedeclarationCheckHandler());
+      return new Es6SyntacticScopeCreator(compiler);
     } else if (sanityCheck) {
       return SyntacticScopeCreator.makeUntyped(compiler);
     } else {
@@ -282,7 +277,6 @@ class VarCheck extends AbstractPostOrderCallback implements
         switch (parent.getType()) {
           case Token.VAR:
           case Token.FUNCTION:
-          case Token.CLASS:
           case Token.PARAM_LIST:
             // These are okay.
             break;
@@ -330,12 +324,18 @@ class VarCheck extends AbstractPostOrderCallback implements
     Node parent = n.getParent();
     Node origParent = origVar.getParentNode();
 
-    JSDocInfo info = parent.getJSDocInfo();
+    JSDocInfo info = n.getJSDocInfo();
+    if (info == null) {
+      info = parent.getJSDocInfo();
+    }
     if (info != null && info.getSuppressions().contains("duplicate")) {
       return true;
     }
 
-    info = origParent.getJSDocInfo();
+    info = origVar.nameNode.getJSDocInfo();
+    if (info == null) {
+      info = origParent.getJSDocInfo();
+    }
     return (info != null && info.getSuppressions().contains("duplicate"));
   }
 
@@ -358,13 +358,6 @@ class VarCheck extends AbstractPostOrderCallback implements
           return;
         }
 
-        if (parent.isLet() || parent.isConst() ||
-            origParent.isLet() || origParent.isConst()) {
-          compiler.report(
-              JSError.make(n, LET_CONST_MULTIPLY_DECLARED_ERROR));
-          return;
-        }
-
         boolean allowDupe = hasDuplicateDeclarationSuppression(n, origVar);
 
         if (!allowDupe) {
diff --git a/src/com/google/javascript/jscomp/VariableReferenceCheck.java b/src/com/google/javascript/jscomp/VariableReferenceCheck.java
index 840eab1ea..dd69e0da8 100644
--- a/src/com/google/javascript/jscomp/VariableReferenceCheck.java
+++ b/src/com/google/javascript/jscomp/VariableReferenceCheck.java
@@ -73,13 +73,16 @@ class VariableReferenceCheck implements HotSwapCompilerPass {
       "Block-scoped declaration not directly within block: {0}");
 
   private final AbstractCompiler compiler;
+  private final CheckLevel checkLevel;
 
   // NOTE(nicksantos): It's a lot faster to use a shared Set that
   // we clear after each method call, because the Set never gets too big.
   private final Set<BasicBlock> blocksWithDeclarations = new HashSet<>();
 
-  public VariableReferenceCheck(AbstractCompiler compiler) {
+  public VariableReferenceCheck(AbstractCompiler compiler,
+      CheckLevel checkLevel) {
     this.compiler = compiler;
+    this.checkLevel = checkLevel;
   }
 
   @Override
@@ -115,10 +118,10 @@ class VariableReferenceCheck implements HotSwapCompilerPass {
         ReferenceCollection referenceCollection = referenceMap.getReferences(v);
         // TODO(moz): Figure out why this could be null
         if (referenceCollection != null) {
-          if (scope.getRootNode().isFunction() && v.isDefaultParam()) {
+          if (scope.getRootNode().isFunction() && v.getParentNode().isDefaultValue()
+              && v.getParentNode().getFirstChild() == v.getNode()) {
             checkDefaultParam(v, scope);
-          }
-          if (scope.getRootNode().isFunction()) {
+          } else if (scope.isFunctionBlockScope()) {
             checkShadowParam(v, scope, referenceCollection.references);
           }
           checkVar(v, referenceCollection.references);
@@ -151,27 +154,29 @@ class VariableReferenceCheck implements HotSwapCompilerPass {
       for (Node ref : check.currParamReferences) {
         String refName = ref.getString();
         if (!scope.isDeclared(refName, true)) {
-          compiler.report(JSError.make(ref, EARLY_REFERENCE_ERROR, v.name));
+          compiler.report(JSError.make(ref, checkLevel, EARLY_REFERENCE_ERROR, v.name));
         }
       }
     }
 
-    private void checkShadowParam(Var v, Scope functionScope, List<Reference> references) {
+    private void checkShadowParam(Var v, Scope scope, List<Reference> references) {
+      Scope functionScope = scope.getParent();
       Var maybeParam = functionScope.getVar(v.getName());
       if (maybeParam != null && maybeParam.isParam()
           && maybeParam.getScope() == functionScope) {
         for (Reference r : references) {
-          if (r.isDeclaration() && !r.getNode().equals(v.getNameNode())) {
-            if (!compiler.getLanguageMode().isEs6OrHigher() && r.getParent().isCatch()) {
-              continue;
-            }
-            compiler.report(
-                JSError.make(
-                    r.getNode(),
-                    (r.isVarDeclaration() || r.isHoistedFunction())
-                    ? REDECLARED_VARIABLE
-                    : PARAMETER_SHADOWED_ERROR, v.name));
+          if (!r.isDeclaration() || r.getScope() != scope) {
+            continue;
           }
+          compiler.report(
+              JSError.make(
+                  r.getNode(),
+                  checkLevel,
+                  (r.isVarDeclaration() || r.isHoistedFunction())
+                      && !(maybeParam.getNode().getParent().isDefaultValue()
+                          || maybeParam.getNode().isRest())
+                  ? REDECLARED_VARIABLE
+                  : PARAMETER_SHADOWED_ERROR, v.name));
         }
       }
     }
@@ -230,17 +235,16 @@ class VariableReferenceCheck implements HotSwapCompilerPass {
               // better yet, make sure the generated code never violates
               // the requirement to pass aggressive var check!
               DiagnosticType diagnosticType;
-              if (v.isLet() || v.isConst() || v.isClass()
+              if (v.isLet() || v.isConst()
                   || letConstShadowsVar || shadowCatchVar) {
                 diagnosticType = REDECLARED_VARIABLE_ERROR;
-              } else if (reference.getNode().getParent().isCatch()) {
-                return;
               } else {
                 diagnosticType = REDECLARED_VARIABLE;
               }
               compiler.report(
                   JSError.make(
                       referenceNode,
+                      checkLevel,
                       diagnosticType, v.name));
               break;
             }
@@ -250,7 +254,7 @@ class VariableReferenceCheck implements HotSwapCompilerPass {
         if (!shadowDetected && isDeclaration && (letConstShadowsVar || shadowCatchVar)
             && v.getScope() == reference.getScope()) {
           compiler.report(
-              JSError.make(referenceNode, REDECLARED_VARIABLE_ERROR, v.name));
+              JSError.make(referenceNode, checkLevel, REDECLARED_VARIABLE_ERROR, v.name));
         }
 
         if (isUnhoistedNamedFunction && !isDeclaration && isDeclaredInScope) {
@@ -287,7 +291,8 @@ class VariableReferenceCheck implements HotSwapCompilerPass {
               isUndeclaredReference = true;
               compiler.report(
                   JSError.make(reference.getNode(),
-                               (v.isLet() || v.isConst() || v.isClass() || v.isParam())
+                               checkLevel,
+                               (v.isLet() || v.isConst() || v.isParam())
                                    ? EARLY_REFERENCE_ERROR
                                    : EARLY_REFERENCE, v.name));
             }
@@ -296,12 +301,18 @@ class VariableReferenceCheck implements HotSwapCompilerPass {
 
         if (!isDeclaration && !isUndeclaredReference
             && v.isConst() && reference.isLvalue()) {
-          compiler.report(JSError.make(referenceNode, REASSIGNED_CONSTANT, v.name));
+          compiler.report(
+              JSError.make(referenceNode,
+                           checkLevel,
+                           REASSIGNED_CONSTANT, v.name));
         }
 
-        if (isDeclaration && !reference.isVarDeclaration()
+        if (isDeclaration && !v.isVar()
             && reference.getGrandparent().isAddedBlock()) {
-          compiler.report(JSError.make(referenceNode, DECLARATION_NOT_DIRECTLY_IN_BLOCK, v.name));
+          compiler.report(
+              JSError.make(referenceNode,
+                           checkLevel,
+                           DECLARATION_NOT_DIRECTLY_IN_BLOCK, v.name));
         }
 
         if (isDeclaration) {
diff --git a/src/com/google/javascript/jscomp/WarningLevel.java b/src/com/google/javascript/jscomp/WarningLevel.java
index 2b0c6082a..9937cb794 100644
--- a/src/com/google/javascript/jscomp/WarningLevel.java
+++ b/src/com/google/javascript/jscomp/WarningLevel.java
@@ -107,6 +107,7 @@ public enum WarningLevel {
     // false positives.
     options.setCheckTypes(true);
     options.setCheckGlobalNamesLevel(CheckLevel.WARNING);
+    options.setAggressiveVarCheck(CheckLevel.WARNING);
     options.setWarningLevel(DiagnosticGroups.MISSING_PROPERTIES, CheckLevel.WARNING);
     options.setWarningLevel(
         DiagnosticGroups.DEPRECATED, CheckLevel.WARNING);
diff --git a/src/com/google/javascript/jscomp/js/es6_runtime.js b/src/com/google/javascript/jscomp/js/es6_runtime.js
index 01e953e43..149b37d06 100644
--- a/src/com/google/javascript/jscomp/js/es6_runtime.js
+++ b/src/com/google/javascript/jscomp/js/es6_runtime.js
@@ -112,12 +112,11 @@ $jscomp.inherits = function(childCtor, parentCtor) {
   childCtor.prototype.constructor = childCtor;
 
   for (var p in parentCtor) {
-    if ($jscomp.global.Object.defineProperties) {
-      var descriptor = $jscomp.global.Object.getOwnPropertyDescriptor(
-          parentCtor, p);
+    if (Object.defineProperties) {
+      var descriptor = Object.getOwnPropertyDescriptor(parentCtor, p);
       // TODO(tbreisacher): Remove this check when Function.inherits is gone.
       if (descriptor !== undefined) {
-        $jscomp.global.Object.defineProperty(childCtor, p, descriptor);
+        Object.defineProperty(childCtor, p, descriptor);
       }
     } else {
       // Pre-ES5 browser. Just copy with an assignment.
diff --git a/src/com/google/javascript/jscomp/lint/CheckEnums.java b/src/com/google/javascript/jscomp/lint/CheckEnums.java
index 71c1ee521..498ec6654 100644
--- a/src/com/google/javascript/jscomp/lint/CheckEnums.java
+++ b/src/com/google/javascript/jscomp/lint/CheckEnums.java
@@ -34,12 +34,6 @@ public final class CheckEnums extends AbstractPostOrderCallback implements Compi
   public static final DiagnosticType DUPLICATE_ENUM_VALUE = DiagnosticType.warning(
       "JSC_DUPLICATE_ENUM_VALUE",
       "The value {0} is duplicated in this enum.");
-  public static final DiagnosticType COMPUTED_PROP_NAME_IN_ENUM = DiagnosticType.warning(
-      "JSC_COMPUTED_PROP_NAME_IN_ENUM",
-      "Computed property name used in enum.");
-  public static final DiagnosticType SHORTHAND_ASSIGNMENT_IN_ENUM = DiagnosticType.warning(
-      "JSC_SHORTHAND_ASSIGNMENT_IN_ENUM",
-      "Shorthand assignment used in enum.");
 
   private final AbstractCompiler compiler;
 
@@ -57,39 +51,17 @@ public final class CheckEnums extends AbstractPostOrderCallback implements Compi
     if (n.isObjectLit()) {
       JSDocInfo jsdoc = NodeUtil.getBestJSDocInfo(n);
       if (jsdoc != null && jsdoc.hasEnumParameterType()) {
-        checkSpecialNamingAndAssignmentUsage(t, n);
         checkDuplicateEnumValues(t, n);
       }
     }
   }
 
-  private void checkSpecialNamingAndAssignmentUsage(NodeTraversal t, Node n) {
-    for (Node child : n.children()) {
-      checkComputedPropName(t, child);
-      checkShorthandAssignment(t, child);
-    }
-  }
-
-  private void checkComputedPropName(NodeTraversal t, Node node) {
-    if (node.isComputedProp()) {
-      t.report(node, COMPUTED_PROP_NAME_IN_ENUM);
-    }
-  }
-
-  private void checkShorthandAssignment(NodeTraversal t, Node node) {
-    if (node.isStringKey() && !node.hasChildren()) {
-      t.report(node, SHORTHAND_ASSIGNMENT_IN_ENUM);
-    }
-  }
-
   private void checkDuplicateEnumValues(NodeTraversal t, Node n) {
     Set<String> values = new HashSet<>();
     for (Node child : n.children()) {
-      Node valueNode = child.getLastChild();
+      Node valueNode = child.getFirstChild();
       String value;
-      if (valueNode == null) {
-        return;
-      } else if (valueNode.isString()) {
+      if (valueNode.isString()) {
         value = valueNode.getString();
       } else if (valueNode.isNumber()) {
         value = Double.toString(valueNode.getDouble());
diff --git a/src/com/google/javascript/jscomp/lint/CheckRequiresAndProvidesSorted.java b/src/com/google/javascript/jscomp/lint/CheckRequiresAndProvidesSorted.java
index 34540112c..508c4c43b 100644
--- a/src/com/google/javascript/jscomp/lint/CheckRequiresAndProvidesSorted.java
+++ b/src/com/google/javascript/jscomp/lint/CheckRequiresAndProvidesSorted.java
@@ -76,18 +76,16 @@ public final class CheckRequiresAndProvidesSorted extends AbstractShallowCallbac
         providedNamespaces.clear();
         break;
       case Token.CALL:
-        if (parent.isExprResult() && parent.getParent().isScript()) {
-          String req = compiler.getCodingConvention().extractClassNameIfRequire(n, parent);
-          if (req != null) {
-            requiredNamespaces.add(req);
-          }
-          String prov = compiler.getCodingConvention().extractClassNameIfProvide(n, parent);
-          if (prov != null) {
-            if (!requiredNamespaces.isEmpty()) {
-              t.report(n, PROVIDES_AFTER_REQUIRES);
-            }
-            providedNamespaces.add(prov);
+        String req = compiler.getCodingConvention().extractClassNameIfRequire(n, parent);
+        if (req != null) {
+          requiredNamespaces.add(req);
+        }
+        String prov = compiler.getCodingConvention().extractClassNameIfProvide(n, parent);
+        if (prov != null) {
+          if (!requiredNamespaces.isEmpty()) {
+            t.report(n, PROVIDES_AFTER_REQUIRES);
           }
+          providedNamespaces.add(prov);
         }
         break;
     }
diff --git a/src/com/google/javascript/jscomp/newtypes/EnumType.java b/src/com/google/javascript/jscomp/newtypes/EnumType.java
index c21f4926c..87a03e0bf 100644
--- a/src/com/google/javascript/jscomp/newtypes/EnumType.java
+++ b/src/com/google/javascript/jscomp/newtypes/EnumType.java
@@ -21,8 +21,6 @@ import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
 import com.google.javascript.rhino.JSTypeExpression;
 
-import com.google.javascript.rhino.Node;
-
 import java.util.Collection;
 
 /**
@@ -45,10 +43,13 @@ public final class EnumType extends Namespace implements TypeWithProperties {
 
   private State state;
   private JSTypeExpression typeExpr;
+  private String name;
   // The type that accompanies the enum declaration
   private JSType declaredType;
   // The type of the enum's properties, a subtype of the previous field.
   private JSType enumPropType;
+  // The type of the object literal that defines the enum
+  private JSType enumObjType;
   // All properties have the same type, so we only need a set, not a map.
   private ImmutableSet<String> props;
 
@@ -68,53 +69,51 @@ public final class EnumType extends Namespace implements TypeWithProperties {
   }
 
   public boolean isResolved() {
-    return this.state == State.RESOLVED;
+    return state == State.RESOLVED;
   }
 
   public JSType getEnumeratedType() {
-    Preconditions.checkState(this.state == State.RESOLVED);
+    Preconditions.checkState(state == State.RESOLVED);
     return declaredType;
   }
 
   public JSType getPropType() {
-    Preconditions.checkState(this.state == State.RESOLVED);
+    Preconditions.checkState(state == State.RESOLVED);
     return enumPropType;
   }
 
   @Override
-  public void finalize(Node constDeclNode) {
-    if (this.isFinalized) {
-      return;
+  public JSType toJSType(JSTypes commonTypes) {
+    Preconditions.checkState(state == State.RESOLVED);
+    if (enumObjType == null) {
+      enumObjType = computeObjType(commonTypes);
     }
-    Preconditions.checkState(this.state == State.RESOLVED);
-    finalizeSubnamespaces(constDeclNode);
-    this.constDeclNode = constDeclNode;
-    this.isFinalized = true;
+    return enumObjType;
   }
 
   // Returns null iff there is a type cycle
   public JSTypeExpression getTypeExpr() {
-    Preconditions.checkState(this.state != State.RESOLVED);
-    if (this.state == State.DURING_RESOLUTION) {
+    Preconditions.checkState(state != State.RESOLVED);
+    if (state == State.DURING_RESOLUTION) {
       return null;
     }
-    this.state = State.DURING_RESOLUTION;
+    state = State.DURING_RESOLUTION;
     return typeExpr;
   }
 
   public JSTypeExpression getTypeExprForErrorReporting() {
-    Preconditions.checkState(this.state == State.DURING_RESOLUTION);
+    Preconditions.checkState(state == State.DURING_RESOLUTION);
     return typeExpr;
   }
 
   void resolveEnum(JSType t) {
     Preconditions.checkNotNull(t);
-    if (this.state == State.RESOLVED) {
+    if (state == State.RESOLVED) {
       return;
     }
-    Preconditions.checkState(this.state == State.DURING_RESOLUTION,
-        "Expected state DURING_RESOLUTION but found %s", this.state.toString());
-    this.state = State.RESOLVED;
+    Preconditions.checkState(state == State.DURING_RESOLUTION,
+        "Expected state DURING_RESOLUTION but found %s", state.toString());
+    state = State.RESOLVED;
     typeExpr = null;
     declaredType = t;
     enumPropType = JSType.fromEnum(this);
@@ -126,8 +125,7 @@ public final class EnumType extends Namespace implements TypeWithProperties {
    *   var X = { ONE: 1, TWO: 2 };
    * the properties of the object literal are constant.
    */
-  @Override
-  protected JSType computeJSType(JSTypes commonTypes) {
+  private JSType computeObjType(JSTypes commonTypes) {
     Preconditions.checkState(enumPropType != null);
     PersistentMap<String, Property> propMap = otherProps;
     for (String s : props) {
diff --git a/src/com/google/javascript/jscomp/newtypes/Namespace.java b/src/com/google/javascript/jscomp/newtypes/Namespace.java
index dbce38bc7..161c3e66d 100644
--- a/src/com/google/javascript/jscomp/newtypes/Namespace.java
+++ b/src/com/google/javascript/jscomp/newtypes/Namespace.java
@@ -42,46 +42,6 @@ public abstract class Namespace {
   // "Simple type" properties (i.e. represented as JSTypes rather than something more specific).
   protected PersistentMap<String, Property> otherProps = PersistentMap.create();
 
-  protected String name;
-  // If true, it is forbidden to add more properties to the namespace.
-  protected boolean isFinalized = false;
-  // If a namespace is finalized early b/c of a @const inference, we
-  // record the @const declaration (usually an assignment node).
-  protected Node constDeclNode;
-  // Represents the namespace as an object that includes all namespace properties.
-  // For NamespaceLit and EnumType, it is an object literal.
-  // For RawNominalType, it is the constructor.
-  protected JSType namespaceType;
-
-  public abstract void finalize(Node constDeclNode);
-
-  protected final void finalizeSubnamespaces(Node constDeclNode) {
-    for (RawNominalType rawType : nominals.values()) {
-      rawType.finalize(constDeclNode);
-    }
-    for (EnumType et : enums.values()) {
-      et.finalize(constDeclNode);
-    }
-    for (NamespaceLit ns : namespaces.values()) {
-      ns.finalize(constDeclNode);
-    }
-  }
-
-  protected abstract JSType computeJSType(JSTypes commonTypes);
-
-  public final String getName() {
-    return name;
-  }
-
-  // Overriden by RawNominalType
-  public Node getConstDeclNode() {
-    return this.constDeclNode;
-  }
-
-  public final boolean isFinalized() {
-    return this.isFinalized;
-  }
-
   private boolean isDefined(String name) {
     return nominals.containsKey(name)
         || enums.containsKey(name)
@@ -108,7 +68,6 @@ public abstract class Namespace {
   }
 
   public final void addSubnamespace(QualifiedName qname) {
-    Preconditions.checkState(!this.isFinalized);
     Declaration d = getDeclaration(qname);
     Preconditions.checkState(d == null
         || d.getNamespace() == null && d.getFunctionScope() != null);
@@ -117,11 +76,10 @@ public abstract class Namespace {
       ns.namespaces = new LinkedHashMap<>();
     }
     String name = qname.getRightmostName();
-    ns.namespaces.put(name, new NamespaceLit(this.name + qname.toString()));
+    ns.namespaces.put(name, new NamespaceLit());
   }
 
   public final void addScope(QualifiedName qname, DeclaredTypeRegistry scope) {
-    Preconditions.checkState(!this.isFinalized);
     Namespace ns = getReceiverNamespace(qname);
     if (ns.scopes.isEmpty()) {
       ns.scopes = new LinkedHashMap<>();
@@ -151,7 +109,6 @@ public abstract class Namespace {
   }
 
   public final void addNominalType(QualifiedName qname, RawNominalType rawNominalType) {
-    Preconditions.checkState(!this.isFinalized);
     Preconditions.checkState(!isDefined(qname));
     Namespace ns = getReceiverNamespace(qname);
     if (ns.nominals.isEmpty()) {
@@ -162,7 +119,6 @@ public abstract class Namespace {
   }
 
   public final void addTypedef(QualifiedName qname, Typedef td) {
-    Preconditions.checkState(!this.isFinalized);
     Preconditions.checkState(!isDefined(qname));
     Namespace ns = getReceiverNamespace(qname);
     if (ns.typedefs.isEmpty()) {
@@ -173,7 +129,6 @@ public abstract class Namespace {
   }
 
   public final void addEnum(QualifiedName qname, EnumType e) {
-    Preconditions.checkState(!this.isFinalized);
     Preconditions.checkState(!isDefined(qname));
     Namespace ns = getReceiverNamespace(qname);
     if (ns.enums.isEmpty()) {
@@ -230,7 +185,6 @@ public abstract class Namespace {
 
   /** Add a new non-optional declared property to this namespace */
   public final void addProperty(String pname, Node defSite, JSType type, boolean isConstant) {
-    Preconditions.checkState(!this.isFinalized);
     if (type == null && isConstant) {
       type = JSType.UNKNOWN;
     }
@@ -242,7 +196,6 @@ public abstract class Namespace {
   /** Add a new undeclared property to this namespace */
   public final void addUndeclaredProperty(
       String pname, Node defSite, JSType t, boolean isConstant) {
-    Preconditions.checkState(!this.isFinalized);
     if (otherProps.containsKey(pname)
         && !otherProps.get(pname).getType().isUnknown()) {
       return;
@@ -257,15 +210,7 @@ public abstract class Namespace {
     return p == null ? null : p.getDeclaredType();
   }
 
-  public final JSType toJSType(JSTypes commonTypes) {
-    if (!this.isFinalized) {
-      finalize(null);
-    }
-    if (this.namespaceType == null) {
-      this.namespaceType = computeJSType(commonTypes);
-    }
-    return this.namespaceType;
-  }
+  public abstract JSType toJSType(JSTypes commonTypes);
 
   protected final JSType withNamedTypes(JSTypes commonTypes, ObjectType obj) {
     if (nominals != null) {
diff --git a/src/com/google/javascript/jscomp/newtypes/NamespaceLit.java b/src/com/google/javascript/jscomp/newtypes/NamespaceLit.java
index df5778512..8b9a24dfe 100644
--- a/src/com/google/javascript/jscomp/newtypes/NamespaceLit.java
+++ b/src/com/google/javascript/jscomp/newtypes/NamespaceLit.java
@@ -16,30 +16,13 @@
 
 package com.google.javascript.jscomp.newtypes;
 
-import com.google.javascript.rhino.Node;
-
 /**
  *
  * @author blickly@google.com (Ben Lickly)
  * @author dimvar@google.com (Dimitris Vardoulakis)
  */
 public final class NamespaceLit extends Namespace {
-  public NamespaceLit(String name) {
-    this.name = name;
-  }
-
-  @Override
-  public void finalize(Node constDeclNode) {
-    if (this.isFinalized) {
-      return;
-    }
-    finalizeSubnamespaces(constDeclNode);
-    this.constDeclNode = constDeclNode;
-    this.isFinalized = true;
-  }
-
-  @Override
-  protected JSType computeJSType(JSTypes commonTypes) {
+  public JSType toJSType(JSTypes commonTypes) {
     ObjectType obj = ObjectType.makeObjectType(
         null, otherProps, null, false, ObjectKind.UNRESTRICTED);
     return withNamedTypes(commonTypes, obj);
diff --git a/src/com/google/javascript/jscomp/newtypes/NominalType.java b/src/com/google/javascript/jscomp/newtypes/NominalType.java
index 1d1e3b69c..a9e9e8d5f 100644
--- a/src/com/google/javascript/jscomp/newtypes/NominalType.java
+++ b/src/com/google/javascript/jscomp/newtypes/NominalType.java
@@ -424,6 +424,7 @@ public final class NominalType {
    * created from it by instantiation.
    */
   public static class RawNominalType extends Namespace {
+    private final String name;
     // The function node (if any) that defines the type
     private final Node defSite;
     // If a nominal type is finalized early b/c of a @const inference, we
@@ -438,6 +439,8 @@ public final class NominalType {
     // for @struct. We use this map to remember the names of props added outside
     // the constructor and the prototype methods.
     private PersistentMap<String, Property> randomProps = PersistentMap.create();
+    // The "static" properties of the constructor are stored in the namespace.
+    boolean isFinalized = false;
     // Consider a generic type A<T> which inherits from a generic type B<T>.
     // All instantiated A classes, such as A<number>, A<string>, etc,
     // have the same superclass and interfaces fields, because they have the
@@ -457,6 +460,7 @@ public final class NominalType {
     private final ImmutableList<String> typeParameters;
     private final ObjectKind objectKind;
     private FunctionType ctorFn;
+    private JSType ctorFnWrappedAsJSType;
     private JSTypes commonTypes;
 
     private RawNominalType(
@@ -515,11 +519,14 @@ public final class NominalType {
           defSite, name.toString(), typeParameters, true, ObjectKind.STRUCT);
     }
 
+    public String getName() {
+      return name;
+    }
+
     public Node getDefSite() {
       return this.defSite;
     }
 
-    @Override
     public Node getConstDeclNode() {
       if (this.constDeclNode != null) {
         return this.constDeclNode;
@@ -562,13 +569,17 @@ public final class NominalType {
       return objectKind.isDict();
     }
 
+    public boolean isFinalized() {
+      return this.isFinalized;
+    }
+
     ImmutableList<String> getTypeParameters() {
       return typeParameters;
     }
 
     public void setCtorFunction(
         FunctionType ctorFn, JSTypes commonTypes) {
-      Preconditions.checkState(!this.isFinalized);
+      Preconditions.checkState(!isFinalized);
       this.ctorFn = ctorFn;
       this.commonTypes = commonTypes;
     }
@@ -586,7 +597,7 @@ public final class NominalType {
 
     /** @return Whether the superclass can be added without creating a cycle. */
     public boolean addSuperClass(NominalType superClass) {
-      Preconditions.checkState(!this.isFinalized);
+      Preconditions.checkState(!isFinalized);
       Preconditions.checkState(this.superClass == null);
       if (superClass.rawType.hasAncestorClass(this)) {
         return false;
@@ -613,7 +624,7 @@ public final class NominalType {
 
     /** @return Whether the interface can be added without creating a cycle. */
     public boolean addInterfaces(ImmutableSet<NominalType> interfaces) {
-      Preconditions.checkState(!this.isFinalized);
+      Preconditions.checkState(!isFinalized);
       Preconditions.checkState(this.interfaces == null);
       Preconditions.checkNotNull(interfaces);
       if (this.isInterface) {
@@ -715,7 +726,7 @@ public final class NominalType {
 
     private ImmutableSet<String> getAllPropsOfInterface() {
       Preconditions.checkState(isInterface);
-      Preconditions.checkState(this.isFinalized);
+      Preconditions.checkState(isFinalized);
       if (allProps == null) {
         ImmutableSet.Builder<String> builder = ImmutableSet.builder();
         if (interfaces != null) {
@@ -730,7 +741,7 @@ public final class NominalType {
 
     private ImmutableSet<String> getAllPropsOfClass() {
       Preconditions.checkState(!isInterface);
-      Preconditions.checkState(this.isFinalized);
+      Preconditions.checkState(isFinalized);
       if (allProps == null) {
         ImmutableSet.Builder<String> builder = ImmutableSet.builder();
         if (superClass != null) {
@@ -742,7 +753,7 @@ public final class NominalType {
     }
 
     public void addPropertyWhichMayNotBeOnAllInstances(String pname, JSType type) {
-      Preconditions.checkState(!this.isFinalized);
+      Preconditions.checkState(!isFinalized);
       if (this.classProps.containsKey(pname) || this.protoProps.containsKey(pname)) {
         return;
       }
@@ -756,7 +767,7 @@ public final class NominalType {
 
     /** Add a new non-optional declared property to instances of this class */
     public void addClassProperty(String pname, Node defSite, JSType type, boolean isConstant) {
-      Preconditions.checkState(!this.isFinalized);
+      Preconditions.checkState(!isFinalized);
       if (type == null && isConstant) {
         type = JSType.UNKNOWN;
       }
@@ -774,7 +785,7 @@ public final class NominalType {
 
     /** Add a new undeclared property to instances of this class */
     public void addUndeclaredClassProperty(String pname, Node defSite) {
-      Preconditions.checkState(!this.isFinalized);
+      Preconditions.checkState(!isFinalized);
       // Only do so if there isn't a declared prop already.
       if (mayHaveProp(pname)) {
         return;
@@ -786,7 +797,7 @@ public final class NominalType {
 
     /** Add a new non-optional declared prototype property to this class */
     public void addProtoProperty(String pname, Node defSite, JSType type, boolean isConstant) {
-      Preconditions.checkState(!this.isFinalized);
+      Preconditions.checkState(!isFinalized);
       if (type == null && isConstant) {
         type = JSType.UNKNOWN;
       }
@@ -804,7 +815,7 @@ public final class NominalType {
 
     /** Add a new undeclared prototype property to this class */
     public void addUndeclaredProtoProperty(String pname, Node defSite) {
-      Preconditions.checkState(!this.isFinalized);
+      Preconditions.checkState(!isFinalized);
       if (!this.protoProps.containsKey(pname) ||
           this.protoProps.get(pname).getDeclaredType() == null) {
         this.protoProps = this.protoProps.with(pname,
@@ -830,13 +841,13 @@ public final class NominalType {
 
     /** Add a new non-optional declared property to this class's constructor */
     public void addCtorProperty(String pname, Node defSite, JSType type, boolean isConstant) {
-      Preconditions.checkState(!this.isFinalized);
+      Preconditions.checkState(!isFinalized);
       super.addProperty(pname, defSite, type, isConstant);
     }
 
     /** Add a new undeclared property to this class's constructor */
     public void addUndeclaredCtorProperty(String pname, Node defSite) {
-      Preconditions.checkState(!this.isFinalized);
+      Preconditions.checkState(!isFinalized);
       super.addUndeclaredProperty(pname, defSite, JSType.UNKNOWN, false);
     }
 
@@ -852,14 +863,18 @@ public final class NominalType {
     // For those, we should just be creating a basic function type, not be
     // adding all the static properties.
     private JSType getConstructorObject(FunctionType ctorFn) {
-      Preconditions.checkState(this.isFinalized);
-      if (this.ctorFn != ctorFn || this.namespaceType == null) {
+      Preconditions.checkState(isFinalized);
+      if (this.ctorFn != ctorFn || this.ctorFnWrappedAsJSType == null) {
         ObjectType ctorFnAsObj = ObjectType.makeObjectType(
             this.commonTypes.getFunctionType(), this.otherProps, ctorFn,
             ctorFn.isLoose(), ObjectKind.UNRESTRICTED);
-        return withNamedTypes(this.commonTypes, ctorFnAsObj);
+        JSType result = withNamedTypes(this.commonTypes, ctorFnAsObj);
+        if (this.ctorFn == ctorFn) {
+          this.ctorFnWrappedAsJSType = result;
+        }
+        return result;
       }
-      return this.namespaceType;
+      return this.ctorFnWrappedAsJSType;
     }
 
     private StringBuilder appendGenericSuffixTo(
@@ -889,13 +904,9 @@ public final class NominalType {
       return builder;
     }
 
-    @Override
-    public void finalize(Node constDeclNode) {
-      if (this.isFinalized) {
-        return;
-      }
+    // If we try to mutate the class after the AST-preparation phase, error.
+    public void finalizeNominalType(Node constDeclNode) {
       Preconditions.checkState(this.ctorFn != null);
-      finalizeSubnamespaces(constDeclNode);
       // System.out.println("Class " + name +
       //     " created with class properties: " + classProps +
       //     " and prototype properties: " + protoProps);
@@ -915,7 +926,8 @@ public final class NominalType {
     }
 
     @Override
-    protected JSType computeJSType(JSTypes commonTypes) {
+    public JSType toJSType(JSTypes commonTypes) {
+      Preconditions.checkState(this.isFinalized);
       return getConstructorObject(this.ctorFn);
     }
 
diff --git a/src/com/google/javascript/jscomp/newtypes/ObjectType.java b/src/com/google/javascript/jscomp/newtypes/ObjectType.java
index 51ca33b6a..09c5c4a95 100644
--- a/src/com/google/javascript/jscomp/newtypes/ObjectType.java
+++ b/src/com/google/javascript/jscomp/newtypes/ObjectType.java
@@ -21,7 +21,6 @@ import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Sets;
 
-import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -683,7 +682,7 @@ final class ObjectType implements TypeWithProperties {
       return objs1;
     }
     ObjectType[] objs1Arr = objs1.toArray(new ObjectType[0]);
-    ObjectType[] keptFrom1 = Arrays.copyOf(objs1Arr, objs1Arr.length);
+    ObjectType[] keptFrom1 = objs1Arr.clone();
     ImmutableSet.Builder<ObjectType> newObjs = ImmutableSet.builder();
     for (ObjectType obj2 : objs2) {
       boolean addedObj2 = false;
diff --git a/src/com/google/javascript/jscomp/parsing/Config.java b/src/com/google/javascript/jscomp/parsing/Config.java
index 6faac83da..fc0c767df 100644
--- a/src/com/google/javascript/jscomp/parsing/Config.java
+++ b/src/com/google/javascript/jscomp/parsing/Config.java
@@ -65,18 +65,27 @@ public final class Config {
    */
   final LanguageMode languageMode;
 
+  /**
+   * Accept `const' keyword.
+   */
+  final boolean acceptConstKeyword;
+
   Config(Set<String> annotationWhitelist, Set<String> suppressionNames,
-      boolean isIdeMode, LanguageMode languageMode) {
-    this(annotationWhitelist, suppressionNames, isIdeMode, isIdeMode, languageMode);
+      boolean isIdeMode, LanguageMode languageMode,
+      boolean acceptConstKeyword) {
+    this(annotationWhitelist, suppressionNames, isIdeMode, isIdeMode,
+        languageMode, acceptConstKeyword);
   }
 
   Config(Set<String> annotationWhitelist, Set<String> suppressionNames,
-      boolean isIdeMode, boolean parseJsDocDocumentation, LanguageMode languageMode) {
+      boolean isIdeMode, boolean parseJsDocDocumentation, LanguageMode languageMode,
+      boolean acceptConstKeyword) {
     this.annotationNames = buildAnnotationNames(annotationWhitelist);
     this.parseJsDocDocumentation = parseJsDocDocumentation;
     this.suppressionNames = suppressionNames;
     this.isIdeMode = isIdeMode;
     this.languageMode = languageMode;
+    this.acceptConstKeyword = acceptConstKeyword;
   }
 
   /**
diff --git a/src/com/google/javascript/jscomp/parsing/IRFactory.java b/src/com/google/javascript/jscomp/parsing/IRFactory.java
index 0c620b8fe..56daad907 100644
--- a/src/com/google/javascript/jscomp/parsing/IRFactory.java
+++ b/src/com/google/javascript/jscomp/parsing/IRFactory.java
@@ -135,7 +135,6 @@ import com.google.javascript.jscomp.parsing.parser.util.SourceRange;
 import com.google.javascript.rhino.ErrorReporter;
 import com.google.javascript.rhino.IR;
 import com.google.javascript.rhino.JSDocInfo;
-import com.google.javascript.rhino.JSDocInfo.Visibility;
 import com.google.javascript.rhino.JSDocInfoBuilder;
 import com.google.javascript.rhino.Node;
 import com.google.javascript.rhino.Node.TypeDeclarationNode;
@@ -1222,7 +1221,6 @@ class IRFactory {
         Node member = newStringNode(Token.MEMBER_FUNCTION_DEF, name.value);
         member.addChildToBack(node);
         member.setStaticMember(functionTree.isStatic);
-        maybeProcessAccessibilityModifier(member, functionTree, functionTree.access);
         node.setDeclaredTypeExpression(node.getDeclaredTypeExpression());
         result = member;
       } else {
@@ -1448,9 +1446,7 @@ class IRFactory {
       Node n = newNode(Token.COMPUTED_PROP, transform(tree.property));
       maybeProcessType(n, tree.declaredType);
       n.putBooleanProp(Node.COMPUTED_PROP_VARIABLE, true);
-      n.putProp(Node.ACCESS_MODIFIER, tree.access);
       n.setStaticMember(tree.isStatic);
-      maybeProcessAccessibilityModifier(n, tree, tree.access);
       return n;
     }
 
@@ -1463,7 +1459,6 @@ class IRFactory {
       if (tree.method.asFunctionDeclaration().isStatic) {
         n.setStaticMember(true);
       }
-      maybeProcessAccessibilityModifier(n, tree, tree.access);
       return n;
     }
 
@@ -1781,8 +1776,19 @@ class IRFactory {
       int declType;
       switch (decl.declarationType) {
         case CONST:
-          maybeWarnEs6Feature(decl, "const declarations");
-          declType = Token.CONST;
+          if (!config.acceptConstKeyword) {
+            maybeWarnEs6Feature(decl, "const declarations");
+          }
+
+          if (isEs6Mode()) {
+            declType = Token.CONST;
+          } else {
+            // Code uses the 'const' keyword which is non-standard in ES5 and
+            // below. Just treat it as though it was a 'var'.
+            // TODO(tbreisacher): Treat this node as though it had an @const
+            // annotation.
+            declType = Token.VAR;
+          }
           break;
         case LET:
           maybeWarnEs6Feature(decl, "let declarations");
@@ -1808,7 +1814,6 @@ class IRFactory {
       if (decl.initializer != null) {
         Node initializer = transform(decl.initializer);
         node.addChildToBack(initializer);
-        maybeSetLength(node, decl.location.start, decl.location.end);
       }
       maybeProcessType(node, decl.declaredType);
       return node;
@@ -1963,7 +1968,6 @@ class IRFactory {
       maybeProcessType(member, tree.declaredType);
       member.setStaticMember(tree.isStatic);
       member.putBooleanProp(Node.OPT_ES6_TYPED, tree.isOptional);
-      maybeProcessAccessibilityModifier(member, tree, tree.access);
       return member;
     }
 
@@ -2319,26 +2323,6 @@ class IRFactory {
       }
     }
 
-    void maybeProcessAccessibilityModifier(Node n, ParseTree tree, TokenType type) {
-      if (type != null) {
-        Visibility access;
-        switch (type) {
-          case PUBLIC:
-            access = Visibility.PUBLIC;
-            break;
-          case PROTECTED:
-            access = Visibility.PROTECTED;
-            break;
-          case PRIVATE:
-            access = Visibility.PRIVATE;
-            break;
-          default:
-            throw new IllegalStateException("Unexpected access modifier type");
-        }
-        n.putProp(Node.ACCESS_MODIFIER, access);
-      }
-    }
-
     void maybeWarnTypeSyntax(ParseTree node, String feature) {
       if (config.languageMode != LanguageMode.ECMASCRIPT6_TYPED) {
         errorReporter.warning(
diff --git a/src/com/google/javascript/jscomp/parsing/JsDocInfoParser.java b/src/com/google/javascript/jscomp/parsing/JsDocInfoParser.java
index 6068da05b..4e98f55b4 100644
--- a/src/com/google/javascript/jscomp/parsing/JsDocInfoParser.java
+++ b/src/com/google/javascript/jscomp/parsing/JsDocInfoParser.java
@@ -190,9 +190,10 @@ public final class JsDocInfoParser {
   public static Node parseTypeString(String typeString) {
     Config config = new Config(
         new HashSet<String>(),
-        new HashSet<String>(),
+         new HashSet<String>(),
         false,
-        LanguageMode.ECMASCRIPT3);
+        LanguageMode.ECMASCRIPT3,
+        false);
     JsDocInfoParser parser = new JsDocInfoParser(
         new JsDocTokenStream(typeString),
         typeString,
@@ -472,7 +473,7 @@ public final class JsDocInfoParser {
 
         case FILE_OVERVIEW:
           String fileOverview = "";
-          if (jsdocBuilder.shouldParseDocumentation() && !lookAheadForAnnotation()) {
+          if (jsdocBuilder.shouldParseDocumentation()) {
             ExtractionInfo fileOverviewInfo =
                 extractMultilineTextualBlock(token,
                     WhitespaceOption.TRIM);
@@ -481,7 +482,7 @@ public final class JsDocInfoParser {
 
             token = fileOverviewInfo.token;
           } else {
-            token = eatUntilEOLIfNotAnnotation();
+            token = eatTokensUntilEOL(token);
           }
 
           if (!jsdocBuilder.recordFileOverview(fileOverview)) {
diff --git a/src/com/google/javascript/jscomp/parsing/ParserRunner.java b/src/com/google/javascript/jscomp/parsing/ParserRunner.java
index 6df6b4570..55ef1e065 100644
--- a/src/com/google/javascript/jscomp/parsing/ParserRunner.java
+++ b/src/com/google/javascript/jscomp/parsing/ParserRunner.java
@@ -51,14 +51,16 @@ public final class ParserRunner {
 
   public static Config createConfig(boolean isIdeMode,
                                     LanguageMode languageMode,
+                                    boolean acceptConstKeyword,
                                     Set<String> extraAnnotationNames) {
     return createConfig(
-        isIdeMode, isIdeMode, languageMode, extraAnnotationNames);
+        isIdeMode, isIdeMode, languageMode, acceptConstKeyword, extraAnnotationNames);
   }
 
   public static Config createConfig(boolean isIdeMode,
                                     boolean parseJsDocDocumentation,
                                     LanguageMode languageMode,
+                                    boolean acceptConstKeyword,
                                     Set<String> extraAnnotationNames) {
     initResourceConfig();
     Set<String> effectiveAnnotationNames;
@@ -69,7 +71,7 @@ public final class ParserRunner {
       effectiveAnnotationNames.addAll(extraAnnotationNames);
     }
     return new Config(effectiveAnnotationNames, suppressionNames,
-        isIdeMode, parseJsDocDocumentation, languageMode);
+        isIdeMode, parseJsDocDocumentation, languageMode, acceptConstKeyword);
   }
 
   public static Set<String> getReservedVars() {
diff --git a/src/com/google/javascript/jscomp/parsing/TypeTransformationParser.java b/src/com/google/javascript/jscomp/parsing/TypeTransformationParser.java
index b6d6bf492..caf3a7440 100644
--- a/src/com/google/javascript/jscomp/parsing/TypeTransformationParser.java
+++ b/src/com/google/javascript/jscomp/parsing/TypeTransformationParser.java
@@ -250,7 +250,7 @@ public final class TypeTransformationParser {
    */
   public boolean parseTypeTransformation() {
     Config config = new Config(new HashSet<String>(),
-        new HashSet<String>(), true, LanguageMode.ECMASCRIPT6);
+        new HashSet<String>(), true, LanguageMode.ECMASCRIPT6, false);
     // TODO(lpino): ParserRunner reports errors if the expression is not
     // ES6 valid. We need to abort the validation of the type transformation
     // whenever an error is reported.
diff --git a/src/com/google/javascript/jscomp/parsing/parser/Parser.java b/src/com/google/javascript/jscomp/parsing/parser/Parser.java
index 615ecd4eb..80ae28197 100644
--- a/src/com/google/javascript/jscomp/parsing/parser/Parser.java
+++ b/src/com/google/javascript/jscomp/parsing/parser/Parser.java
@@ -200,7 +200,6 @@ public class Parser {
       ES6_TYPED,
     }
 
-    public final boolean is6Typed;
     public final boolean atLeast6;
     public final boolean atLeast5;
     public final boolean isStrictMode;
@@ -209,7 +208,6 @@ public class Parser {
     public final boolean warnES6NumberLiteral;
 
     public Config(Mode mode) {
-      is6Typed = mode == Mode.ES6_TYPED;
       atLeast6 = mode == Mode.ES6 || mode == Mode.ES6_STRICT
           || mode == Mode.ES6_TYPED;
       atLeast5 = atLeast6 || mode == Mode.ES5 || mode == Mode.ES5_STRICT;
@@ -603,14 +601,13 @@ public class Parser {
 
     if (peek(TokenType.OPEN_PAREN) || peek(TokenType.OPEN_ANGLE)) {
       // Method signature.
-      ParseTree function = parseMethodSignature(
-          start, name, false, isGenerator, isOptional, null);
+      ParseTree function = parseMethodSignature(start, name, false, isGenerator, isOptional);
       return function;
     } else {
       // Property signature.
       ParseTree declaredType = maybeParseColonType();
-      return new MemberVariableTree(
-          getTreeLocation(start), name, false, isOptional, null, declaredType);
+      return new MemberVariableTree(getTreeLocation(start), name, false,
+          isOptional, declaredType);
     }
   }
 
@@ -703,22 +700,19 @@ public class Parser {
   }
 
   private ParseTree parseClassElement(boolean isAmbient) {
-    TokenType access = maybeParseAccessibilityModifier();
-
     if (peek(TokenType.SEMI_COLON)) {
       return parseEmptyStatement();
     }
     if (peekGetAccessor(true)) {
-      return parseGetAccessor(access);
+      return parseGetAccessor();
     }
     if (peekSetAccessor(true)) {
-      return parseSetAccessor(access);
+      return parseSetAccessor();
     }
-    return parseClassMemberDeclaration(true, isAmbient, access);
+    return parseClassMemberDeclaration(true, isAmbient);
   }
 
-  private ParseTree parseClassMemberDeclaration(
-      boolean allowStatic, boolean isAmbient, TokenType access) {
+  private ParseTree parseClassMemberDeclaration(boolean allowStatic, boolean isAmbient) {
     SourcePosition start = getTreeStartLocation();
     boolean isStatic = false;
     if (allowStatic && peek(TokenType.STATIC) && peekType(1) != TokenType.OPEN_PAREN) {
@@ -745,30 +739,20 @@ public class Parser {
 
     if (peek(TokenType.OPEN_PAREN) || peek(TokenType.OPEN_ANGLE)) {
       // Member function.
-      FunctionDeclarationTree.Kind kind;
-      TokenType accessOnFunction;
-      if (nameExpr == null) {
-        kind = FunctionDeclarationTree.Kind.MEMBER;
-        accessOnFunction = access;
-      } else {
-        kind = FunctionDeclarationTree.Kind.EXPRESSION;
-        accessOnFunction = null; // Accessibility modifier goes on the ComputedPropertyMethodTree
-      }
-
+      FunctionDeclarationTree.Kind kind =
+          nameExpr == null ? FunctionDeclarationTree.Kind.MEMBER
+              : FunctionDeclarationTree.Kind.EXPRESSION;
       ParseTree function;
       if (isAmbient) {
-        function = parseMethodSignature(
-            start, name, isStatic, isGenerator, false, accessOnFunction);
+        function = parseMethodSignature(start, name, isStatic, isGenerator, false);
         eatPossibleImplicitSemiColon();
       } else {
-        function = parseFunctionTail(
-            start, name, isStatic, isGenerator, accessOnFunction, kind);
+        function = parseFunctionTail(start, name, isStatic, isGenerator, kind);
       }
       if (kind == FunctionDeclarationTree.Kind.MEMBER) {
         return function;
       } else {
-        return new ComputedPropertyMethodTree(
-            getTreeLocation(start), access, nameExpr, function);
+        return new ComputedPropertyMethodTree(getTreeLocation(start), nameExpr, function);
       }
     } else {
       // Member variable.
@@ -781,26 +765,23 @@ public class Parser {
       }
       eatPossibleImplicitSemiColon();
       if (nameExpr == null) {
-        return new MemberVariableTree(
-            getTreeLocation(start), name, isStatic, false, access, declaredType);
+        return new MemberVariableTree(getTreeLocation(start), name, isStatic, false, declaredType);
       } else {
-        return new ComputedPropertyMemberVariableTree(getTreeLocation(start),
-            nameExpr, isStatic, access, declaredType);
+        return new ComputedPropertyMemberVariableTree(getTreeLocation(start), nameExpr, isStatic,
+            declaredType);
       }
     }
   }
 
   private FunctionDeclarationTree parseMethodSignature(SourcePosition start,
-      IdentifierToken name, boolean isStatic, boolean isGenerator,
-      boolean isOptional, TokenType access) {
+      IdentifierToken name, boolean isStatic, boolean isGenerator, boolean isOptional) {
     GenericTypeListTree generics = maybeParseGenericTypes();
     FormalParameterListTree formalParameterList = parseFormalParameterList(ParamContext.SIGNATURE);
     ParseTree returnType = maybeParseColonType();
     ParseTree functionBody = new EmptyStatementTree(getTreeLocation(start));
     FunctionDeclarationTree declaration = new FunctionDeclarationTree(
         getTreeLocation(start), name, generics, isStatic, isGenerator, isOptional,
-        access, FunctionDeclarationTree.Kind.MEMBER, formalParameterList, returnType,
-        functionBody);
+        FunctionDeclarationTree.Kind.MEMBER, formalParameterList, returnType, functionBody);
     return declaration;
   }
 
@@ -811,14 +792,14 @@ public class Parser {
     ParseTree returnType = maybeParseColonType();
     ParseTree functionBody = new EmptyStatementTree(getTreeLocation(start));
     FunctionDeclarationTree declaration = new FunctionDeclarationTree(
-        getTreeLocation(start), name, generics, false, isGenerator, false, null,
+        getTreeLocation(start), name, generics, false, isGenerator, false,
         FunctionDeclarationTree.Kind.DECLARATION, formalParameterList, returnType, functionBody);
     return declaration;
   }
 
   private FunctionDeclarationTree parseFunctionTail(
       SourcePosition start, IdentifierToken name,
-      boolean isStatic, boolean isGenerator, TokenType access,
+      boolean isStatic, boolean isGenerator,
       FunctionDeclarationTree.Kind kind) {
 
     inGeneratorContext.addLast(isGenerator);
@@ -829,7 +810,7 @@ public class Parser {
     ParseTree returnType = maybeParseColonType();
     BlockTree functionBody = parseFunctionBody();
     FunctionDeclarationTree declaration = new FunctionDeclarationTree(
-        getTreeLocation(start), name, generics, isStatic, isGenerator, false, access,
+        getTreeLocation(start), name, generics, isStatic, isGenerator, false,
         kind, formalParameterList, returnType, functionBody);
 
     inGeneratorContext.removeLast();
@@ -889,7 +870,7 @@ public class Parser {
     eat(TokenType.COLON);
     ParseTree declaredType = parseType();
     ParseTree nameTree = new MemberVariableTree(getTreeLocation(start), name, false,
-        false, null, indexType);
+        false, indexType);
     return new IndexSignatureTree(getTreeLocation(start), nameTree, declaredType);
   }
 
@@ -951,7 +932,7 @@ public class Parser {
     }
 
     FunctionDeclarationTree declaration =  new FunctionDeclarationTree(
-        getTreeLocation(start), null, generics, false, false, false, null,
+        getTreeLocation(start), null, generics, false, false, false,
         FunctionDeclarationTree.Kind.ARROW,
         formalParameterList, returnType, functionBody);
 
@@ -995,7 +976,7 @@ public class Parser {
     IdentifierToken name = eatId();
 
     return parseFunctionTail(
-        start, name, false, isGenerator, null,
+        start, name, false, isGenerator,
         FunctionDeclarationTree.Kind.DECLARATION);
   }
 
@@ -1006,7 +987,7 @@ public class Parser {
     IdentifierToken name = eatIdOpt();
 
     return parseFunctionTail(
-        start, name, false, isGenerator, null,
+        start, name, false, isGenerator,
         FunctionDeclarationTree.Kind.EXPRESSION);
   }
 
@@ -2124,8 +2105,7 @@ public class Parser {
 
     eat(TokenType.OPEN_CURLY);
     Token commaToken = null;
-    while (peekPropertyNameOrComputedProp(0) || peek(TokenType.STAR)
-        || peekAccessibilityModifier()) {
+    while (peekPropertyNameOrComputedProp(0) || peek(TokenType.STAR)) {
       commaToken = null;
       result.add(parsePropertyAssignment());
       commaToken = eatOpt(TokenType.COMMA);
@@ -2175,11 +2155,11 @@ public class Parser {
         || type == TokenType.IDENTIFIER
         || Keywords.isKeyword(type)) {
       if (peekGetAccessor(false)) {
-        return parseGetAccessor(null);
+        return parseGetAccessor();
       } else if (peekSetAccessor(false)) {
-        return parseSetAccessor(null);
+        return parseSetAccessor();
       } else if (peekType(1) == TokenType.OPEN_PAREN) {
-        return parseClassMemberDeclaration(false, false, null);
+        return parseClassMemberDeclaration(false, false);
       } else {
         return parsePropertyNameAssignment();
       }
@@ -2193,9 +2173,8 @@ public class Parser {
         return new ComputedPropertyDefinitionTree(getTreeLocation(start), name, value);
       } else {
         ParseTree value = parseFunctionTail(
-            start, null, false, false, null, FunctionDeclarationTree.Kind.EXPRESSION);
-        return new ComputedPropertyMethodTree(
-            getTreeLocation(start), null, name, value);
+            start, null, false, false, FunctionDeclarationTree.Kind.EXPRESSION);
+        return new ComputedPropertyMethodTree(getTreeLocation(start), name, value);
       }
     } else {
       throw new RuntimeException("unreachable");
@@ -2209,15 +2188,15 @@ public class Parser {
         || type == TokenType.IDENTIFIER
         || Keywords.isKeyword(type)) {
       // parseMethodDeclaration will consume the '*'.
-      return parseClassMemberDeclaration(false, false, null);
+      return parseClassMemberDeclaration(false, false);
     } else {
       SourcePosition start = getTreeStartLocation();
       eat(TokenType.STAR);
       ParseTree name = parseComputedPropertyName();
 
       ParseTree value = parseFunctionTail(
-          start, null, false, true, null, FunctionDeclarationTree.Kind.EXPRESSION);
-      return new ComputedPropertyMethodTree(getTreeLocation(start), null, name, value);
+          start, null, false, true, FunctionDeclarationTree.Kind.EXPRESSION);
+      return new ComputedPropertyMethodTree(getTreeLocation(start), name, value);
     }
   }
 
@@ -2253,7 +2232,7 @@ public class Parser {
         && ((IdentifierToken) peekToken(index)).value.equals(string);
   }
 
-  private ParseTree parseGetAccessor(TokenType access) {
+  private ParseTree parseGetAccessor() {
     SourcePosition start = getTreeStartLocation();
     boolean isStatic = eatOpt(TokenType.STATIC) != null;
     eatPredefinedString(PredefinedName.GET);
@@ -2270,7 +2249,7 @@ public class Parser {
       eat(TokenType.CLOSE_PAREN);
       BlockTree body = parseFunctionBody();
       return new ComputedPropertyGetterTree(
-          getTreeLocation(start), property, isStatic, access, body);
+          getTreeLocation(start), property, isStatic, body);
     }
   }
 
@@ -2280,7 +2259,7 @@ public class Parser {
         && peekPropertyNameOrComputedProp(index + 1);
   }
 
-  private ParseTree parseSetAccessor(TokenType access) {
+  private ParseTree parseSetAccessor() {
     SourcePosition start = getTreeStartLocation();
     boolean isStatic = eatOpt(TokenType.STATIC) != null;
     eatPredefinedString(PredefinedName.SET);
@@ -2299,7 +2278,7 @@ public class Parser {
       eat(TokenType.CLOSE_PAREN);
       BlockTree body = parseFunctionBody();
       return new ComputedPropertySetterTree(
-          getTreeLocation(start), property, isStatic, access, parameter, body);
+          getTreeLocation(start), property, isStatic, parameter, body);
     }
   }
 
@@ -3282,22 +3261,6 @@ public class Parser {
         || (!inStrictContext() && Keywords.isStrictKeyword(type));
   }
 
-  private boolean peekAccessibilityModifier() {
-    return EnumSet.of(TokenType.PUBLIC, TokenType.PROTECTED, TokenType.PRIVATE)
-        .contains(peekType());
-  }
-
-  private TokenType maybeParseAccessibilityModifier() {
-    if (peekAccessibilityModifier()) {
-      if (!config.is6Typed) {
-        reportError("Accessibility modifier is only supported in ES6 typed mode");
-      }
-      return nextToken().type;
-    } else {
-      return null;
-    }
-  }
-
   /**
    * Shorthand for eatOpt(TokenType.IDENTIFIER)
    */
diff --git a/src/com/google/javascript/jscomp/parsing/parser/trees/ComputedPropertyGetterTree.java b/src/com/google/javascript/jscomp/parsing/parser/trees/ComputedPropertyGetterTree.java
index 23550756a..5c9f593e4 100644
--- a/src/com/google/javascript/jscomp/parsing/parser/trees/ComputedPropertyGetterTree.java
+++ b/src/com/google/javascript/jscomp/parsing/parser/trees/ComputedPropertyGetterTree.java
@@ -16,25 +16,19 @@
 
 package com.google.javascript.jscomp.parsing.parser.trees;
 
-import com.google.javascript.jscomp.parsing.parser.TokenType;
 import com.google.javascript.jscomp.parsing.parser.util.SourceRange;
 
-import javax.annotation.Nullable;
-
 public class ComputedPropertyGetterTree extends ParseTree {
   public final ParseTree property;
   public final boolean isStatic;
-  @Nullable public final TokenType access;
   public final BlockTree body;
 
   public ComputedPropertyGetterTree(
-      SourceRange location, ParseTree property, boolean isStatic,
-      @Nullable TokenType access, BlockTree body) {
+      SourceRange location, ParseTree property, boolean isStatic, BlockTree body) {
     super(ParseTreeType.COMPUTED_PROPERTY_GETTER, location);
 
     this.property = property;
     this.isStatic = isStatic;
-    this.access = access;
     this.body = body;
   }
 }
diff --git a/src/com/google/javascript/jscomp/parsing/parser/trees/ComputedPropertyMemberVariableTree.java b/src/com/google/javascript/jscomp/parsing/parser/trees/ComputedPropertyMemberVariableTree.java
index c2ad8e382..2c3945314 100644
--- a/src/com/google/javascript/jscomp/parsing/parser/trees/ComputedPropertyMemberVariableTree.java
+++ b/src/com/google/javascript/jscomp/parsing/parser/trees/ComputedPropertyMemberVariableTree.java
@@ -15,7 +15,6 @@
  */
 package com.google.javascript.jscomp.parsing.parser.trees;
 
-import com.google.javascript.jscomp.parsing.parser.TokenType;
 import com.google.javascript.jscomp.parsing.parser.util.SourceRange;
 
 import javax.annotation.Nullable;
@@ -26,16 +25,13 @@ import javax.annotation.Nullable;
 public class ComputedPropertyMemberVariableTree extends ParseTree {
   public final ParseTree property;
   public final boolean isStatic;
-  @Nullable public final TokenType access;
   @Nullable public final ParseTree declaredType;
 
   public ComputedPropertyMemberVariableTree(SourceRange location, ParseTree property,
-      boolean isStatic,  @Nullable TokenType access, @Nullable ParseTree declaredType) {
+      boolean isStatic, @Nullable ParseTree declaredType) {
     super(ParseTreeType.COMPUTED_PROPERTY_MEMBER_VARIABLE, location);
-
     this.property = property;
     this.isStatic = isStatic;
-    this.access = access;
     this.declaredType = declaredType;
   }
 }
diff --git a/src/com/google/javascript/jscomp/parsing/parser/trees/ComputedPropertyMethodTree.java b/src/com/google/javascript/jscomp/parsing/parser/trees/ComputedPropertyMethodTree.java
index 1c7475fb8..271067cea 100644
--- a/src/com/google/javascript/jscomp/parsing/parser/trees/ComputedPropertyMethodTree.java
+++ b/src/com/google/javascript/jscomp/parsing/parser/trees/ComputedPropertyMethodTree.java
@@ -15,21 +15,14 @@
  */
 package com.google.javascript.jscomp.parsing.parser.trees;
 
-import com.google.javascript.jscomp.parsing.parser.TokenType;
 import com.google.javascript.jscomp.parsing.parser.util.SourceRange;
 
-import javax.annotation.Nullable;
-
 public class ComputedPropertyMethodTree extends ParseTree {
-  @Nullable public final TokenType access;
   public final ParseTree property;
   public final ParseTree method;
 
-  public ComputedPropertyMethodTree(SourceRange location, @Nullable TokenType access,
-      ParseTree property, ParseTree method) {
+  public ComputedPropertyMethodTree(SourceRange location, ParseTree property, ParseTree method) {
     super(ParseTreeType.COMPUTED_PROPERTY_METHOD, location);
-
-    this.access = access;
     this.property = property;
     this.method = method;
   }
diff --git a/src/com/google/javascript/jscomp/parsing/parser/trees/ComputedPropertySetterTree.java b/src/com/google/javascript/jscomp/parsing/parser/trees/ComputedPropertySetterTree.java
index 0255fbad8..81d946e7d 100644
--- a/src/com/google/javascript/jscomp/parsing/parser/trees/ComputedPropertySetterTree.java
+++ b/src/com/google/javascript/jscomp/parsing/parser/trees/ComputedPropertySetterTree.java
@@ -17,30 +17,24 @@
 package com.google.javascript.jscomp.parsing.parser.trees;
 
 import com.google.javascript.jscomp.parsing.parser.IdentifierToken;
-import com.google.javascript.jscomp.parsing.parser.TokenType;
 import com.google.javascript.jscomp.parsing.parser.util.SourceRange;
 
-import javax.annotation.Nullable;
-
 public class ComputedPropertySetterTree extends ParseTree {
   public final ParseTree property;
   public final IdentifierToken parameter;
   public final boolean isStatic;
-  @Nullable public final TokenType access;
   public final BlockTree body;
 
   public ComputedPropertySetterTree(
       SourceRange location,
       ParseTree property,
       boolean isStatic,
-      @Nullable TokenType access,
       IdentifierToken parameter,
       BlockTree body) {
     super(ParseTreeType.COMPUTED_PROPERTY_SETTER, location);
 
     this.property = property;
     this.isStatic = isStatic;
-    this.access = access;
     this.parameter = parameter;
     this.body = body;
   }
diff --git a/src/com/google/javascript/jscomp/parsing/parser/trees/FunctionDeclarationTree.java b/src/com/google/javascript/jscomp/parsing/parser/trees/FunctionDeclarationTree.java
index 7c3d19e7a..bf8b8ed3a 100644
--- a/src/com/google/javascript/jscomp/parsing/parser/trees/FunctionDeclarationTree.java
+++ b/src/com/google/javascript/jscomp/parsing/parser/trees/FunctionDeclarationTree.java
@@ -17,7 +17,6 @@
 package com.google.javascript.jscomp.parsing.parser.trees;
 
 import com.google.javascript.jscomp.parsing.parser.IdentifierToken;
-import com.google.javascript.jscomp.parsing.parser.TokenType;
 import com.google.javascript.jscomp.parsing.parser.util.SourceRange;
 
 import javax.annotation.Nullable;
@@ -39,13 +38,11 @@ public class FunctionDeclarationTree extends ParseTree {
   public final boolean isStatic;
   public final boolean isGenerator;
   public final boolean isOptional;
-  @Nullable public final TokenType access;
   public final Kind kind;
 
   public FunctionDeclarationTree(SourceRange location, IdentifierToken name,
-      GenericTypeListTree generics, boolean isStatic,
-      boolean isGenerator, boolean isOptional, @Nullable TokenType access, Kind kind,
-      FormalParameterListTree formalParameterList, @Nullable ParseTree returnType,
+      GenericTypeListTree generics, boolean isStatic, boolean isGenerator, boolean isOptional,
+      Kind kind, FormalParameterListTree formalParameterList, @Nullable ParseTree returnType,
       ParseTree functionBody) {
     super(ParseTreeType.FUNCTION_DECLARATION, location);
 
@@ -54,7 +51,6 @@ public class FunctionDeclarationTree extends ParseTree {
     this.isStatic = isStatic;
     this.isGenerator = isGenerator;
     this.isOptional = isOptional;
-    this.access = access;
     this.kind = kind;
     this.formalParameterList = formalParameterList;
     this.returnType = returnType;
diff --git a/src/com/google/javascript/jscomp/parsing/parser/trees/MemberVariableTree.java b/src/com/google/javascript/jscomp/parsing/parser/trees/MemberVariableTree.java
index 34839824d..dd8122c45 100644
--- a/src/com/google/javascript/jscomp/parsing/parser/trees/MemberVariableTree.java
+++ b/src/com/google/javascript/jscomp/parsing/parser/trees/MemberVariableTree.java
@@ -16,7 +16,6 @@
 package com.google.javascript.jscomp.parsing.parser.trees;
 
 import com.google.javascript.jscomp.parsing.parser.IdentifierToken;
-import com.google.javascript.jscomp.parsing.parser.TokenType;
 import com.google.javascript.jscomp.parsing.parser.util.SourceRange;
 
 import javax.annotation.Nullable;
@@ -28,17 +27,14 @@ public class MemberVariableTree extends ParseTree {
   public final IdentifierToken name;
   public final boolean isStatic;
   public final boolean isOptional;
-  @Nullable public final TokenType access;
   @Nullable public final ParseTree declaredType;
 
   public MemberVariableTree(SourceRange location, IdentifierToken name, boolean isStatic,
-      boolean isOptional, @Nullable TokenType access, @Nullable ParseTree declaredType) {
+      boolean isOptional, @Nullable ParseTree declaredType) {
     super(ParseTreeType.MEMBER_VARIABLE, location);
-
     this.name = name;
     this.isStatic = isStatic;
     this.isOptional = isOptional;
-    this.access = access;
     this.declaredType = declaredType;
   }
 }
diff --git a/src/com/google/javascript/jscomp/regex/CharRanges.java b/src/com/google/javascript/jscomp/regex/CharRanges.java
index e7592953d..13c57ec82 100644
--- a/src/com/google/javascript/jscomp/regex/CharRanges.java
+++ b/src/com/google/javascript/jscomp/regex/CharRanges.java
@@ -50,7 +50,7 @@ final class CharRanges {
    * Returns an instance containing all and only the given members.
    */
   public static CharRanges withMembers(int... members) {
-    return new CharRanges(intArrayToRanges(Arrays.copyOf(members, members.length)));
+    return new CharRanges(intArrayToRanges(members.clone()));
   }
 
   /**
@@ -59,7 +59,7 @@ final class CharRanges {
    *     non-contiguous, [inclusive start, exclusive end) ranges.
    */
   public static CharRanges withRanges(int... ranges) {
-    ranges = Arrays.copyOf(ranges, ranges.length);
+    ranges = ranges.clone();
     if ((ranges.length & 1) != 0) { throw new IllegalArgumentException(); }
     for (int i = 1; i < ranges.length; ++i) {
       if (ranges[i] <= ranges[i - 1]) {
diff --git a/src/com/google/javascript/refactoring/RefactoringDriver.java b/src/com/google/javascript/refactoring/RefactoringDriver.java
index 83a3fd408..7bd4aa3b0 100644
--- a/src/com/google/javascript/refactoring/RefactoringDriver.java
+++ b/src/com/google/javascript/refactoring/RefactoringDriver.java
@@ -94,6 +94,8 @@ public final class RefactoringDriver {
 
     options.setWarningLevel(DiagnosticGroups.MISSING_REQUIRE, CheckLevel.ERROR);
 
+    options.setAcceptConstKeyword(true);
+
     return options;
   }
 
diff --git a/src/com/google/javascript/rhino/JSDocInfo.java b/src/com/google/javascript/rhino/JSDocInfo.java
index 742e1d09b..4f29ceacf 100644
--- a/src/com/google/javascript/rhino/JSDocInfo.java
+++ b/src/com/google/javascript/rhino/JSDocInfo.java
@@ -152,6 +152,7 @@ public class JSDocInfo implements Serializable {
           .toString();
     }
 
+    @Override
     protected LazilyInitializedInfo clone() {
       LazilyInitializedInfo other = new LazilyInitializedInfo();
       other.baseType = baseType;
@@ -446,6 +447,7 @@ public class JSDocInfo implements Serializable {
   // Visible for testing.
   JSDocInfo() {}
 
+  @Override
   public JSDocInfo clone() {
     JSDocInfo other = new JSDocInfo();
     other.info = this.info == null ? null : this.info.clone();
diff --git a/src/com/google/javascript/rhino/JSTypeExpression.java b/src/com/google/javascript/rhino/JSTypeExpression.java
index aa609523f..ae0de3a71 100644
--- a/src/com/google/javascript/rhino/JSTypeExpression.java
+++ b/src/com/google/javascript/rhino/JSTypeExpression.java
@@ -128,6 +128,7 @@ public final class JSTypeExpression implements Serializable {
     return "type: " + root.toString();
   }
 
+  @Override
   public JSTypeExpression clone() {
     return new JSTypeExpression(root.cloneTree(), sourceName);
   }
diff --git a/src/com/google/javascript/rhino/Node.java b/src/com/google/javascript/rhino/Node.java
index d91e91453..a575baad5 100644
--- a/src/com/google/javascript/rhino/Node.java
+++ b/src/com/google/javascript/rhino/Node.java
@@ -136,8 +136,7 @@ public class Node implements Serializable {
                                   // in ES6 Typed syntax.
       GENERIC_TYPE_LIST = 81,     // Generic type list in ES6 typed syntax.
       IMPLEMENTS = 82,            // "implements" clause in ES6 typed syntax.
-      CONSTRUCT_SIGNATURE = 83,   // This node is a TypeScript ConstructSignature
-      ACCESS_MODIFIER = 84;       // TypeScript accessibility modifiers (public, protected, private)
+      CONSTRUCT_SIGNATURE = 83;   // This node is a TypeScript ConstructSignature
 
   public static final int   // flags for INCRDECR_PROP
       DECR_FLAG = 0x1,
@@ -193,7 +192,6 @@ public class Node implements Serializable {
         case GENERIC_TYPE_LIST:       return "generic_type";
         case IMPLEMENTS:       return "implements";
         case CONSTRUCT_SIGNATURE: return "construct_signature";
-        case ACCESS_MODIFIER: return "access_modifier";
         default:
           throw new IllegalStateException("unexpected prop id " + propType);
       }


Test patch:
diff --git a/src/com/google/javascript/jscomp/ExportTestFunctions.java b/src/com/google/javascript/jscomp/ExportTestFunctions.java
index c5a670ce3..1065eba26 100644
--- a/src/com/google/javascript/jscomp/ExportTestFunctions.java
+++ b/src/com/google/javascript/jscomp/ExportTestFunctions.java
@@ -90,25 +90,15 @@ class ExportTestFunctions implements CompilerPass {
         }
       } else if (n.isObjectLit()
           && isCallTargetQName(n.getParent(), "goog.testing.testSuite")) {
-        for (Node c : n.children()) {
+        for (Node c = n.getFirstChild(); c != null; c = c.getNext()) {
           if (c.isStringKey() && !c.isQuotedString()) {
             c.setQuotedString();
             compiler.reportCodeChange();
-          } else if (c.isMemberFunctionDef()) {
-            rewriteMemberDefInObjLit(c, n);
           }
         }
       }
     }
 
-    private void rewriteMemberDefInObjLit(Node memberDef, Node objLit) {
-      String name = memberDef.getString();
-      Node stringKey = IR.stringKey(name, memberDef.getFirstChild().detachFromParent());
-      objLit.replaceChild(memberDef, stringKey);
-      stringKey.setQuotedString();
-      compiler.reportCodeChange();
-    }
-
     // TODO(johnlenz): move test suite declaration into the
     // coding convention class.
     private boolean isCallTargetQName(Node n, String qname) {
diff --git a/src/com/google/javascript/jscomp/testing/NodeSubject.java b/src/com/google/javascript/jscomp/testing/NodeSubject.java
index c990ff05e..2232bf171 100644
--- a/src/com/google/javascript/jscomp/testing/NodeSubject.java
+++ b/src/com/google/javascript/jscomp/testing/NodeSubject.java
@@ -53,12 +53,4 @@ public final class NodeSubject extends Subject<NodeSubject, Node> {
         + " not of type " + Token.name(type);
     assertEquals(message, type, getSubject().getType());
   }
-
-  public void hasCharno(int charno) {
-    assertEquals(charno, getSubject().getCharno());
-  }
-
-  public void hasLength(int length) {
-    assertEquals(length, getSubject().getLength());
-  }
 }
diff --git a/test/com/google/javascript/jscomp/CheckMissingReturnTest.java b/test/com/google/javascript/jscomp/CheckMissingReturnTest.java
index dbe61ca64..f277c76e1 100644
--- a/test/com/google/javascript/jscomp/CheckMissingReturnTest.java
+++ b/test/com/google/javascript/jscomp/CheckMissingReturnTest.java
@@ -16,7 +16,7 @@
 
 package com.google.javascript.jscomp;
 
-import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
+import com.google.javascript.jscomp.CheckLevel;
 
 /**
  * Tests for {@link CheckMissingReturn}.
@@ -71,8 +71,6 @@ public final class CheckMissingReturnTest extends CompilerTestCase {
 
     // Test try catch finally.
     testNotMissing("try { return foo() } catch (e) { } finally { }");
-    testNotMissing("try {throw e;} catch (e) { return foo() } finally { }");
-    testNotMissing("try {} catch (e) {} finally {return foo()};");
 
     // Nested function.
     testNotMissing(
@@ -230,43 +228,13 @@ public final class CheckMissingReturnTest extends CompilerTestCase {
     return "/** @return {" + returnType + "} */ function foo() {" + body + "}";
   }
 
-  private static String createShorthandFunctionInObjLit(
-      String returnType, String body) {
-    return LINE_JOINER.join(
-        "var obj = {",
-        "  /** @return {" + returnType + "} */",
-        "  foo() {", body, "}",
-        "}");
-  }
-
-  private void testMissingInTraditionalFunction(String returnType, String body) {
+  private void testMissing(String returnType, String body) {
     String js = createFunction(returnType, body);
     testError(js, CheckMissingReturn.MISSING_RETURN_STATEMENT);
   }
 
-  private void testNotMissingInTraditionalFunction(String returnType, String body) {
-    testSame(createFunction(returnType, body));
-  }
-
-  private void testMissingInShorthandFunction(String returnType, String body) {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    String js = createShorthandFunctionInObjLit(returnType, body);
-    testError(js, CheckMissingReturn.MISSING_RETURN_STATEMENT);
-  }
-
-  private void testNotMissingInShorthandFunction(String returnType, String body) {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testSame(createShorthandFunctionInObjLit(returnType, body));
-  }
-
-  private void testMissing(String returnType, String body) {
-    testMissingInTraditionalFunction(returnType, body);
-    testMissingInShorthandFunction(returnType, body);
-  }
-
   private void testNotMissing(String returnType, String body) {
-    testNotMissingInTraditionalFunction(returnType, body);
-    testNotMissingInShorthandFunction(returnType, body);
+    testSame(createFunction(returnType, body));
   }
 
   /** Creates function with return type {number} */
diff --git a/test/com/google/javascript/jscomp/CheckProvidesTest.java b/test/com/google/javascript/jscomp/CheckProvidesTest.java
index cead101c5..4c19d7729 100644
--- a/test/com/google/javascript/jscomp/CheckProvidesTest.java
+++ b/test/com/google/javascript/jscomp/CheckProvidesTest.java
@@ -18,7 +18,6 @@ package com.google.javascript.jscomp;
 import static com.google.javascript.jscomp.CheckProvides.MISSING_PROVIDE_WARNING;
 
 import com.google.javascript.jscomp.CheckLevel;
-import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
 
 /**
  * Tests for {@link CheckProvides}.
@@ -43,27 +42,6 @@ public final class CheckProvidesTest extends CompilerTestCase {
     testSame(js);
   }
 
-  public void testHarmlessEs6Class() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testSame("goog.provide('X'); var X = class {};");
-    testSame("goog.provide('X'); class X {};");
-    testSame("goog.provide('foo.bar.X'); foo.bar.X = class {};");
-  }
-
-  public void testMissingProvideEs6Class() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    String js = "class X {};";
-    String warning = "missing goog.provide('X')";
-    test(js, js, null, MISSING_PROVIDE_WARNING, warning);
-
-    js = "var X = class {};";
-    test(js, js, null, MISSING_PROVIDE_WARNING, warning);
-
-    js = "foo.bar.X = class {};";
-    warning = "missing goog.provide('foo.bar.X')";
-    test(js, js, null, MISSING_PROVIDE_WARNING, warning);
-  }
-
   public void testNoProvideInnerClass() {
     testSame(
         "goog.provide('X');\n" +
diff --git a/test/com/google/javascript/jscomp/CheckRegExpTest.java b/test/com/google/javascript/jscomp/CheckRegExpTest.java
index a33b05a19..63f136cc7 100644
--- a/test/com/google/javascript/jscomp/CheckRegExpTest.java
+++ b/test/com/google/javascript/jscomp/CheckRegExpTest.java
@@ -16,8 +16,6 @@
 
 package com.google.javascript.jscomp;
 
-import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
-
 /**
  * @author johnlenz@google.com (John Lenz)
  */
@@ -82,31 +80,15 @@ public final class CheckRegExpTest extends CompilerTestCase {
     testReference("f(RegExp);", true);
     testReference("new f(RegExp);", true);
     testReference("var x = RegExp; x.test()", true);
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testReference("let x = RegExp;", true);
-    testReference("const x = RegExp;", true);
 
     // No RegExp reference is OK.
     testReference("var x;", false);
 
     // Local RegExp is OK.
     testReference("function f() {var RegExp; RegExp.test();}", false);
-    testReference("function f() {let RegExp; RegExp.test();}", false);
-    testReference("function *gen() {var RegExp; yield RegExp.test();}", false);
 
     // Property named 'RegExp' is OK.
     testReference("var x = {RegExp: {}}; x.RegExp.$1;", false);
-
-    // Class property is also OK.
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testReference(LINE_JOINER.join(
-        "class x {",
-        "  constructor() {this.RegExp = {};}",
-        "  method() {",
-        "    this.RegExp.$1;",
-        "    this.RegExp.test();",
-        "  }",
-        "}"), false);
   }
 
   public void testInvalidRange() {
diff --git a/test/com/google/javascript/jscomp/CheckUnreachableCodeTest.java b/test/com/google/javascript/jscomp/CheckUnreachableCodeTest.java
index 14db981e6..97755f81e 100644
--- a/test/com/google/javascript/jscomp/CheckUnreachableCodeTest.java
+++ b/test/com/google/javascript/jscomp/CheckUnreachableCodeTest.java
@@ -16,8 +16,6 @@
 
 package com.google.javascript.jscomp;
 
-import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
-
 /**
  * Tests for {@link CheckUnreachableCode}.
  *
@@ -211,90 +209,6 @@ public final class CheckUnreachableCodeTest extends CompilerTestCase {
         "}\n");
   }
 
-  public void testES6FeaturesInIfExpression() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    // class X{} always eval to true by toBoolean();
-    assertUnreachable("if(!class {}) x = 1;");
-    assertUnreachable("if(!class A{}) x = 1;");
-
-    // Template string with substitution and tagged template will be evaluated
-    // to UNKNOWN. Template string with definite length (without substitution)
-    // will be evaled like a normal string.
-    assertUnreachable("if(!`tempLit`) {x = 1;}");
-    assertUnreachable("if(``) {x = 1;}");
-    testSame("if(`temp${sub}Lit`) {x = 1;} else {x = 2;}");
-    testSame("if(`${sub}`) {x = 1;} else {x = 2;}");
-    testSame("if(tagged`tempLit`) {x = 1;} else {x = 2;}");
-
-    // Functions were deemed UNKNOWN, so they remain UNKNOWN.
-    // TODO(tbreisacher): Treat functions as truthy.
-    testSame("if(()=>true) {x = 1;} else {x = 2;}");
-  }
-
-  public void testES6FeaturesInTryCatch() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    assertUnreachable("try { let x = 1; } catch(e) {}");
-    assertUnreachable("try { const x = 1; } catch(e) {}");
-    assertUnreachable("try {()=>42;} catch(e) {}");
-    assertUnreachable("try {function *gen(){};} catch(e) {}");
-    // Assumed tagged template may throw exception.
-    testSame("try {tagged`temp`;} catch(e) {}");
-
-    assertUnreachable("try { var obj = {a(){}};} catch(e) {}");
-    testSame("try { var obj = {a(){}}; obj.a();} catch(e) {}");
-  }
-
-  public void testCorrectForOfBreakAndContinues() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testSame("for(x of [1, 2, 3]) {foo();}");
-    testSame("for(x of [1, 2, 3]) {foo(); break;}");
-    testSame("for(x of [1, 2, 3]) {foo(); continue;}");
-  }
-
-  public void testInCorrectForOfBreakAndContinues() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    assertUnreachable("for(x of [1, 2, 3]) {foo(); break; bar();}");
-    assertUnreachable("for(x of [1, 2, 3]) {foo(); continue; bar();}");
-
-    assertUnreachable("for(x of [1, 2, 3]) {if(x) {break; bar();}}");
-    //TODO(user): ES6 scope creator could not correctly handle its scope yet.
-    //                Enable the test after functional scope creator is in place.
-    //assertUnreachable("for(x of [1, 2, 3]) {if(x) {continue; bar();}}");
-  }
-
-  public void testReturnsInShorthandFunctionOfObjLit() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testSame(LINE_JOINER.join(
-        "var obj = {",
-        "  f() { ",
-        "    switch(x) { ",
-        "      default: return; ",
-        "      case 1: x++; ",
-        "    }",
-        "  }",
-        "}"));
-    assertUnreachable(LINE_JOINER.join(
-        "var obj = {f() {",
-        "  switch(x) { ",
-        "    default: return; ",
-        "    case 1: return; ",
-        "  }",
-        "  return; ",
-        "}}"));
-    testSame("var obj = {f() { if(x) {return;} else {return; }}}");
-    assertUnreachable(LINE_JOINER.join(
-        "var obj = {f() { ",
-        "  if(x) {",
-        "    return;",
-        "  } else {",
-        "    return;",
-        "  }",
-        "  return; ",
-        "}}"));
-  }
-
-
-
   private void assertUnreachable(String js) {
     test(js, js, null, CheckUnreachableCode.UNREACHABLE_CODE);
   }
diff --git a/test/com/google/javascript/jscomp/CollapsePropertiesTest.java b/test/com/google/javascript/jscomp/CollapsePropertiesTest.java
index 2cb76f6be..2a4ede6c7 100644
--- a/test/com/google/javascript/jscomp/CollapsePropertiesTest.java
+++ b/test/com/google/javascript/jscomp/CollapsePropertiesTest.java
@@ -438,15 +438,13 @@ public final class CollapsePropertiesTest extends CompilerTestCase {
     // People don't typically iterate through static members of a class or
     // refer to them using an alias for the class name.
     test("/** @constructor */ var a = function(){}; a.b = 1; "
-         + "var c = a; c.b = 2; a.b == c.b;",
-         "var a = function(){}; var a$b = 1; var c = null; a$b = 2; a$b == a$b;");
+         + "var c = a; c.b = 2; a.b != c.b;",
+         "var a = function(){}; var a$b = 1; var c = a; c.b = 2; a$b != c.b;");
 
     // Sometimes we want to prevent static members of a constructor from
     // being collapsed.
-    test("/** @constructor */ var a = function(){};"
-        + "/** @nocollapse */ a.b = 1; var c = a; c.b = 2; a.b == c.b;",
-        "/** @constructor */ var a = function(){};"
-        + "/** @nocollapse */ a.b = 1; var c = null; a.b = 2; a.b == a.b;");
+    testSame("/** @constructor */ var a = function(){};"
+        + "/** @nocollapse */ a.b = 1; var c = a; c.b = 2; a.b == c.b;");
   }
 
   public void testAliasCreatedForFunctionDepth1_2() {
@@ -489,15 +487,15 @@ public final class CollapsePropertiesTest extends CompilerTestCase {
   public void testAliasCreatedForCtorDepth2() {
     test("var a = {}; /** @constructor */ a.b = function() {}; "
          + "a.b.c = 1; var d = a.b;"
-         + "a.b.c == d.c;",
-         "var a$b = function() {}; var a$b$c = 1; var d = null;"
-         + "a$b$c == a$b$c;");
+         + "a.b.c != d.c;",
+         "var a$b = function() {}; var a$b$c = 1; var d = a$b;"
+         + "a$b$c != d.c;");
 
     test("var a = {}; /** @constructor */ a.b = function() {}; "
         + "/** @nocollapse */ a.b.c = 1; var d = a.b;"
         + "a.b.c == d.c;",
-        "var a$b = function() {}; a$b.c = 1; var d = null;"
-        + "a$b.c == a$b.c;");
+        "var a$b = function() {}; a$b.c = 1; var d = a$b;"
+        + "a$b.c == d.c;");
   }
 
   public void testAliasCreatedForClassDepth1_1() {
@@ -865,18 +863,16 @@ public final class CollapsePropertiesTest extends CompilerTestCase {
   }
 
   public void testAddPropertyToUncollapsibleNamedCtorInLocalScopeDepth1() {
-    test(
-        "/** @constructor */ function a() {} var a$b; var c = a; "
-        + "(function() {a$b = 0;})(); a$b;",
-        "/** @constructor */ function a() {} var a$b; var c = null; "
-        + "(function() {a$b = 0;})(); a$b;");
+    testSame(
+          "/** @constructor */ function a() {} var a$b; var c = a; "
+          + "(function() {a$b = 0;})(); a$b;");
   }
 
   public void testAddPropertyToUncollapsibleCtorInLocalScopeDepth1() {
     test("/** @constructor */ var a = function() {}; var c = a; "
          + "(function() {a.b = 0;})(); a.b;",
          "var a = function() {}; var a$b; "
-         + "var c = null; (function() {a$b = 0;})(); a$b;");
+         + "var c = a; (function() {a$b = 0;})(); a$b;");
   }
 
   public void testAddPropertyToUncollapsibleObjectInLocalScopeDepth2() {
@@ -896,7 +892,7 @@ public final class CollapsePropertiesTest extends CompilerTestCase {
   public void testAddPropertyToUncollapsibleCtorInLocalScopeDepth2() {
     test("var a = {}; /** @constructor */ a.b = function (){}; var d = a.b;"
          + "(function() {a.b.c = 0;})(); a.b.c;",
-         "var a$b = function (){}; var a$b$c; var d = null;"
+         "var a$b = function (){}; var a$b$c; var d = a$b;"
          + "(function() {a$b$c = 0;})(); a$b$c;");
   }
 
@@ -933,7 +929,7 @@ public final class CollapsePropertiesTest extends CompilerTestCase {
   public void testAddPropertyToChildOfUncollapsibleCtorInLocalScope() {
     test("/** @constructor */ var a = function() {}; a.b = {x: 0}; var c = a;"
          + "(function() {a.b.y = 0;})(); a.b.y;",
-         "var a = function() {}; var a$b$x = 0; var a$b$y; var c = null;"
+         "var a = function() {}; var a$b$x = 0; var a$b$y; var c = a;"
          + "(function() {a$b$y = 0;})(); a$b$y;");
   }
 
@@ -2109,77 +2105,4 @@ public final class CollapsePropertiesTest extends CompilerTestCase {
         + "/** @nocollapse */ e.foo = { bar: true };",
         "var e$A=1; var e$B=2; var e = {}; e.foo = { bar: true };");
   }
-
-  public void testCodeGeneratedByGoogModule() {
-    // The static property is added to the exports object
-    test(
-        "var $jscomp = {};\n" +
-        "$jscomp.scope = {};\n" +
-        "/** @constructor */\n" +
-        "$jscomp.scope.Foo = function() {};\n" +
-        "var exports = $jscomp.scope.Foo;\n" +
-        "exports.staticprop = {A:1};\n" +
-        "var y = exports.staticprop.A;",
-
-        "var $jscomp$scope$Foo = function() {}\n" +
-        "var exports = null;\n" +
-        "var $jscomp$scope$Foo$staticprop$A = 1;\n" +
-        "var y = $jscomp$scope$Foo$staticprop$A;");
-
-    // The static property is added to the constructor
-    test(
-        "var $jscomp = {};\n" +
-        "$jscomp.scope = {};\n" +
-        "/** @constructor */\n" +
-        "$jscomp.scope.Foo = function() {};\n" +
-        "$jscomp.scope.Foo.staticprop = {A:1};\n" +
-        "var exports = $jscomp.scope.Foo;\n" +
-        "var y = exports.staticprop.A;",
-
-        "var $jscomp$scope$Foo = function() {}\n" +
-        "var $jscomp$scope$Foo$staticprop$A = 1;\n" +
-        "var exports = null;\n" +
-        "var y = $jscomp$scope$Foo$staticprop$A;");
-  }
-
-  public void testDontCrashAtComma() {
-    test(
-        "var ns = {};\n"
-        + "ns.Foo = {};\n"
-        + "var Baz = {};\n"
-        + "Baz.Foo = ns.Foo;\n"
-        + "(Baz.Foo.bar = 10, 123);",
-
-        "var Baz$Foo=null;\n"
-        + "(ns$Foo$bar = 10, 123);");
-  }
-
-  public void testInlineCtorInObjLit() {
-    test(
-        "/** @constructor */\n"
-        + "function Foo() {}\n"
-        + "/** @constructor */\n"
-        + "var Bar = Foo;\n"
-        + "var objlit = {\n"
-        + "  'prop' : Bar\n"
-        + "};",
-
-        "function Foo() {}\n"
-        + "var Bar = null;\n"
-        + "var objlit$prop = Foo;");
-  }
-
-  public void testDontCrashCtorAliasWithEnum() {
-    test(
-        "var ns = {};\n"
-        + "/** @constructor */\n"
-        + "ns.Foo = function () {};\n"
-        + "var Bar = ns.Foo;\n"
-        + "/** @const @enum */\n"
-        + "Bar.prop = { A: 1 };",
-
-        "var ns$Foo = function(){};\n"
-        + "var Bar = null;\n"
-        + "var ns$Foo$prop$A = 1");
-  }
 }
diff --git a/test/com/google/javascript/jscomp/CommandLineRunnerTest.java b/test/com/google/javascript/jscomp/CommandLineRunnerTest.java
index 6793e0596..fa104e4ae 100644
--- a/test/com/google/javascript/jscomp/CommandLineRunnerTest.java
+++ b/test/com/google/javascript/jscomp/CommandLineRunnerTest.java
@@ -165,17 +165,6 @@ public final class CommandLineRunnerTest extends TestCase {
     test("function f() { this.a = 3; }", CheckGlobalThis.GLOBAL_THIS);
   }
 
-  public void testWarningGuardWildcard1() {
-    args.add("--jscomp_warning=*");
-    test("function f() { this.a = 3; }", CheckGlobalThis.GLOBAL_THIS);
-  }
-
-  public void testWarningGuardWildcardOrdering() {
-    args.add("--jscomp_warning=*");
-    args.add("--jscomp_off=globalThis");
-    testSame("function f() { this.a = 3; }");
-  }
-
   public void testSimpleModeLeavesUnusedParams() {
     args.add("--compilation_level=SIMPLE_OPTIMIZATIONS");
     testSame("window.f = function(a) {};");
diff --git a/test/com/google/javascript/jscomp/Es6SyntacticScopeCreatorTest.java b/test/com/google/javascript/jscomp/Es6SyntacticScopeCreatorTest.java
index 9b45320c9..ce47f936f 100644
--- a/test/com/google/javascript/jscomp/Es6SyntacticScopeCreatorTest.java
+++ b/test/com/google/javascript/jscomp/Es6SyntacticScopeCreatorTest.java
@@ -201,7 +201,12 @@ public final class Es6SyntacticScopeCreatorTest extends TestCase {
 
     Node functionNode = root.getFirstChild();
     Scope functionScope = scopeCreator.createScope(functionNode, globalScope);
+
+    Node functionBlock = functionNode.getLastChild();
+    Scope functionBlockScope = scopeCreator.createScope(functionBlock, functionScope);
+
     assertTrue(functionScope.isDeclared("a", false));
+    assertFalse(functionBlockScope.isDeclared("a", false));
   }
 
   public void testObjectDestructuringNested() {
@@ -371,7 +376,7 @@ public final class Es6SyntacticScopeCreatorTest extends TestCase {
 
     Node ifBlock = functionBlock.getLastChild().getLastChild().getLastChild();
     Scope blockScope = scopeCreator.createScope(ifBlock, functionScope);
-    assertTrue(blockScope.isDeclared("x", false));
+    assertFalse(blockScope.isDeclared("x", false));
     assertTrue(blockScope.isDeclared("y", false));
   }
 
@@ -449,52 +454,4 @@ public final class Es6SyntacticScopeCreatorTest extends TestCase {
     assertTrue(ifBlockScope.isDeclared("x", false));
     assertFalse(ifBlockScope.isDeclared("y", false));
   }
-
-  public void testSimpleFunctionParam() {
-    String js = "function f(x) {}";
-    Node root = getRoot(js);
-    Node fNode = root.getFirstChild();
-
-    Scope globalScope = scopeCreator.createScope(root, null);
-    Scope fScope = scopeCreator.createScope(fNode, globalScope);
-    assertTrue(fScope.isDeclared("x", false));
-
-    Node fBlock = fNode.getLastChild();
-    Scope fBlockScope = scopeCreator.createScope(fBlock, null);
-    assertFalse(fBlockScope.isDeclared("x", false));
-  }
-
-  public void testOnlyOneDeclaration() {
-    String js = "function f(x) { if (!x) var x = 6; }";
-    Node root = getRoot(js);
-    Node fNode = root.getFirstChild();
-    Scope globalScope = scopeCreator.createScope(root, null);
-    Scope fScope = scopeCreator.createScope(fNode, globalScope);
-    assertTrue(fScope.isDeclared("x", false));
-
-    Node fBlock = fNode.getLastChild();
-    Scope fBlockScope = scopeCreator.createScope(fBlock, fScope);
-    assertTrue(fBlockScope.isDeclared("x", false));
-
-    Node ifBlock = fBlock.getFirstChild().getLastChild();
-    Scope ifBlockScope = scopeCreator.createScope(ifBlock, fBlockScope);
-    assertFalse(ifBlockScope.isDeclared("x", false));
-  }
-
-  public void testCatchInFunction() {
-    String js = "function f(e) { try {} catch (e) {} }";
-    Node root = getRoot(js);
-    Node fNode = root.getFirstChild();
-    Scope globalScope = scopeCreator.createScope(root, null);
-    Scope fScope = scopeCreator.createScope(fNode, globalScope);
-    assertTrue(fScope.isDeclared("e", false));
-
-    Node fBlock = fNode.getLastChild();
-    Scope fBlockScope = scopeCreator.createScope(fBlock, fScope);
-    Node tryBlock = fBlock.getFirstChild().getFirstChild();
-    Scope tryScope = scopeCreator.createScope(tryBlock, fBlockScope);
-    Node catchBlock = tryBlock.getNext();
-    Scope catchScope = scopeCreator.createScope(catchBlock, tryScope);
-    assertTrue(catchScope.isDeclared("e", false));
-  }
 }
diff --git a/test/com/google/javascript/jscomp/Es6TypedToEs6ConverterTest.java b/test/com/google/javascript/jscomp/Es6TypedToEs6ConverterTest.java
index a0336c4d2..a97137e77 100644
--- a/test/com/google/javascript/jscomp/Es6TypedToEs6ConverterTest.java
+++ b/test/com/google/javascript/jscomp/Es6TypedToEs6ConverterTest.java
@@ -23,7 +23,6 @@ public final class Es6TypedToEs6ConverterTest extends CompilerTestCase {
   protected void setUp() throws Exception {
     super.setUp();
     setAcceptedLanguage(LanguageMode.ECMASCRIPT6_TYPED);
-    enableCompareAsTree(true);
   }
 
   @Override
@@ -253,17 +252,13 @@ public final class Es6TypedToEs6ConverterTest extends CompilerTestCase {
   }
 
   public void testAmbientDeclaration() {
-    enableCompareAsTree(false);
-    testExternChanges(
-        "declare var x: number;",
-        "/** @suppress {duplicate} */ var /** number */ x;");
-    testExternChanges("declare let x;", "var x;");
-    testExternChanges("declare const x;", "/** @const */ var x;");
-    testExternChanges("declare function f(): number;", "/** @return {number} */ function f() {}");
-    testExternChanges(
-        "declare enum Foo {}",
-        "/** @suppress {duplicate} @enum {number} */ var Foo = {}");
-    testExternChanges("declare class C { constructor(); };", "class C { constructor() {} }");
+    test("declare var x;", "/** @suppress {duplicate} */ var x;");
+    test("declare let x;", "/** @suppress {duplicate} */ var x;");
+    test("declare const x;", "/** @suppress {duplicate} @const */ var x;");
+    test("declare function f();", "/** @suppress {duplicate} */ function f() {}");
+    test("declare enum Foo {}", "/** @suppress {duplicate} @enum {number} */ var Foo = {}");
+    test("declare class C { constructor(); };",
+         "/** @suppress {duplicate} */ class C { constructor() {} }");
   }
 
   public void testIndexSignature() {
@@ -277,18 +272,4 @@ public final class Es6TypedToEs6ConverterTest extends CompilerTestCase {
     testError("var x: { [foo: string]: number; };",
         Es6TypedToEs6Converter.UNSUPPORTED_RECORD_TYPE);
   }
-
-  public void testAccessibilityModifier() {
-    test("class Foo { private constructor() {} }",
-         "class Foo { /** @private */ constructor() {} }");
-    test("class Foo { protected bar() {} }", "class Foo { /** @protected */ bar() {} }");
-    test("class Foo { protected static bar: number; }",
-         "class Foo {} /** @protected @type {number} */ Foo.bar;");
-    test("class Foo { private get() {} }", "class Foo { /** @private */ get() {} }");
-    test("class Foo { public set() {} }", "class Foo { /** @public */ set() {} }");
-    testError("class Foo { private ['foo']() {} }",
-        Es6TypedToEs6Converter.COMPUTED_PROP_ACCESS_MODIFIER);
-    testError("class Foo { private ['foo']; }",
-        Es6TypedToEs6Converter.COMPUTED_PROP_ACCESS_MODIFIER);
-  }
 }
diff --git a/test/com/google/javascript/jscomp/Es6VariableReferenceCheckTest.java b/test/com/google/javascript/jscomp/Es6VariableReferenceCheckTest.java
index 14cd22ce2..eead81ed0 100644
--- a/test/com/google/javascript/jscomp/Es6VariableReferenceCheckTest.java
+++ b/test/com/google/javascript/jscomp/Es6VariableReferenceCheckTest.java
@@ -18,6 +18,8 @@ package com.google.javascript.jscomp;
 
 import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
 
+
+
 /**
  * Test that errors and warnings are generated in appropriate cases and
  * appropriate cases only by VariableReferenceCheck when checking ES6 input
@@ -25,23 +27,45 @@ import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
  */
 public final class Es6VariableReferenceCheckTest extends CompilerTestCase {
 
+  private static final String VARIABLE_RUN =
+      "var a = 1; var b = 2; var c = a + b, d = c;";
+
   private static final String LET_RUN =
       "let a = 1; let b = 2; let c = a + b, d = c;";
 
+  private boolean enableAmbiguousFunctionCheck = false;
+
+  @Override
+  public CompilerOptions getOptions() {
+    CompilerOptions options = super.getOptions();
+    if (enableAmbiguousFunctionCheck) {
+      options.setWarningLevel(
+          DiagnosticGroups.AMBIGUOUS_FUNCTION_DECL, CheckLevel.WARNING);
+    }
+    return options;
+  }
+
   @Override
   public CompilerPass getProcessor(Compiler compiler) {
-    return new VariableReferenceCheck(compiler);
+    // Treats bad reads as errors, and reports bad write warnings.
+    return new VariableReferenceCheck(compiler, CheckLevel.WARNING);
   }
 
   @Override
   public void setUp() throws Exception {
-    super.setUp();
     setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
+    enableAmbiguousFunctionCheck = false;
   }
 
   public void testCorrectCode() {
+    assertNoWarning("function foo(d) { (function() { d.foo(); }); d.bar(); } ");
+    assertNoWarning("function foo() { bar(); } function bar() { foo(); } ");
+    assertNoWarning("function f(d) { d = 3; }");
+    assertNoWarning(VARIABLE_RUN);
     assertNoWarning(LET_RUN);
+    assertNoWarning("function f() { " + VARIABLE_RUN + "}");
     assertNoWarning("function f() { " + LET_RUN + "}");
+    assertNoWarning("if (a) { var x; }");
     assertNoWarning("try { let e; } catch (e) { let x; }");
   }
 
@@ -96,7 +120,7 @@ public final class Es6VariableReferenceCheckTest extends CompilerTestCase {
     assertRedeclareError("const x = 0, x = 0;");
   }
 
-  public void testIllegalBlockScopedEarlyReference() {
+  public void testIllegalLetConstEarlyReference() {
     assertEarlyReferenceError("let x = x");
     assertEarlyReferenceError("const x = x");
     assertEarlyReferenceError("let x = x || 0");
@@ -104,7 +128,6 @@ public final class Es6VariableReferenceCheckTest extends CompilerTestCase {
     // In the following cases, "x" might not be reachable but we warn anyways
     assertEarlyReferenceError("let x = expr || x");
     assertEarlyReferenceError("const x = expr || x");
-    assertEarlyReferenceError("X; class X {};");
   }
 
   public void testCorrectEarlyReference() {
@@ -149,27 +172,20 @@ public final class Es6VariableReferenceCheckTest extends CompilerTestCase {
   public void testParameterShadowing() {
     assertParameterShadowed("function f(x) { let x; }");
     assertParameterShadowed("function f(x) { const x = 3; }");
-    assertParameterShadowed("function f(X) { class X {} }");
-
     assertRedeclare("function f(x) { function x() {} }");
+    assertParameterShadowed("function f(X) { class X {} }");
     assertRedeclare("function f(x) { var x; }");
-    assertRedeclare("function f(x=3) { var x; }");
-    assertRedeclare("function f(...x) { var x; }");
-    assertRedeclare("function f(...x) { function x() {} }");
-    assertRedeclare("function f(x=3) { function x() {} }");
+    assertParameterShadowed("function f(x=3) { var x; }");
+    assertParameterShadowed("function f(...x) { var x; }");
+    assertParameterShadowed("function f(x=3) { function x() {} }");
+    assertParameterShadowed("function f(...x) { function x() {} }");
     assertNoWarning("function f(x) { if (true) { let x; } }");
-    assertNoWarning(LINE_JOINER.join(
-        "function outer(x) {",
-        "  function inner() {",
-        "    let x = 1;",
-        "  }",
-        "}"));
-    assertNoWarning(LINE_JOINER.join(
-        "function outer(x) {",
-        "  function inner() {",
-        "    var x = 1;",
-        "  }",
-        "}"));
+    assertNoWarning(
+        LINE_JOINER.join(
+            "function outer(x) {", "  function inner() {", "    let x = 1;", "  }", "}"));
+    assertNoWarning(
+        LINE_JOINER.join(
+            "function outer(x) {", "  function inner() {", "    var x = 1;", "  }", "}"));
   }
 
   public void testReassignedConst() {
@@ -178,12 +194,10 @@ public final class Es6VariableReferenceCheckTest extends CompilerTestCase {
   }
 
   public void testLetConstNotDirectlyInBlock() {
-    testSame("if (true) var x = 3;");
-    testError("if (true) let x = 3;", VariableReferenceCheck.DECLARATION_NOT_DIRECTLY_IN_BLOCK);
-    testError("if (true) const x = 3;", VariableReferenceCheck.DECLARATION_NOT_DIRECTLY_IN_BLOCK);
-    testError("if (true) class C {}", VariableReferenceCheck.DECLARATION_NOT_DIRECTLY_IN_BLOCK);
-    testError("if (true) function f() {}",
-        VariableReferenceCheck.DECLARATION_NOT_DIRECTLY_IN_BLOCK);
+    testSame("if (true) let x = 3;", VariableReferenceCheck.DECLARATION_NOT_DIRECTLY_IN_BLOCK);
+    testSame("if (true) const x = 3;", VariableReferenceCheck.DECLARATION_NOT_DIRECTLY_IN_BLOCK);
+    testSame("if (true) function f() {}", VariableReferenceCheck.DECLARATION_NOT_DIRECTLY_IN_BLOCK);
+    testSame("if (true) class C {}", VariableReferenceCheck.DECLARATION_NOT_DIRECTLY_IN_BLOCK);
   }
 
   public void testFunctionHoisting() {
@@ -310,28 +324,28 @@ public final class Es6VariableReferenceCheckTest extends CompilerTestCase {
    * Expects the JS to generate one bad-read error.
    */
   private void assertReassign(String js) {
-    testError(js, VariableReferenceCheck.REASSIGNED_CONSTANT);
+    testSame(js, VariableReferenceCheck.REASSIGNED_CONSTANT);
   }
 
   /**
    * Expects the JS to generate one bad-read warning.
    */
   private void assertRedeclare(String js) {
-    testWarning(js, VariableReferenceCheck.REDECLARED_VARIABLE);
+    testSame(js, VariableReferenceCheck.REDECLARED_VARIABLE);
   }
 
   /**
    * Expects the JS to generate one bad-read error.
    */
   private void assertRedeclareError(String js) {
-    testError(js, VariableReferenceCheck.REDECLARED_VARIABLE_ERROR);
+    testSame(js, VariableReferenceCheck.REDECLARED_VARIABLE_ERROR);
   }
 
   /**
    * Expects the JS to generate one bad-read error.
    */
   private void assertParameterShadowed(String js) {
-    testError(js, VariableReferenceCheck.PARAMETER_SHADOWED_ERROR);
+    testSame(js, VariableReferenceCheck.PARAMETER_SHADOWED_ERROR);
   }
 
   /**
@@ -345,7 +359,7 @@ public final class Es6VariableReferenceCheckTest extends CompilerTestCase {
    * Expects the JS to generate one bad-write error.
    */
   private void assertEarlyReferenceError(String js) {
-    testError(js, VariableReferenceCheck.EARLY_REFERENCE_ERROR);
+    testSame(js, VariableReferenceCheck.EARLY_REFERENCE_ERROR);
   }
 
   /**
diff --git a/test/com/google/javascript/jscomp/ExportTestFunctionsTest.java b/test/com/google/javascript/jscomp/ExportTestFunctionsTest.java
index a7d801e2b..7777f6469 100644
--- a/test/com/google/javascript/jscomp/ExportTestFunctionsTest.java
+++ b/test/com/google/javascript/jscomp/ExportTestFunctionsTest.java
@@ -15,8 +15,6 @@
  */
 package com.google.javascript.jscomp;
 
-import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
-
 /**
  * Tests for ExportTestFunctions.
  *
@@ -162,11 +160,4 @@ public final class ExportTestFunctionsTest extends CompilerTestCase {
         "goog.testing.testSuite({a: function() {}, b: function() {}});",
         "goog.testing.testSuite({'a': function() {}, 'b': function() {}});");
   }
-
-  public void testMemberDefInObjLit() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    test(
-        "goog.testing.testSuite({a() {}, b() {}});",
-        "goog.testing.testSuite({'a': function() {}, 'b': function() {}});");
-  }
 }
diff --git a/test/com/google/javascript/jscomp/ExternExportsPassTest.java b/test/com/google/javascript/jscomp/ExternExportsPassTest.java
index 71c08e921..d55c5d1b9 100644
--- a/test/com/google/javascript/jscomp/ExternExportsPassTest.java
+++ b/test/com/google/javascript/jscomp/ExternExportsPassTest.java
@@ -532,32 +532,6 @@ public final class ExternExportsPassTest extends TestCase {
         + "F.prototype.x;\n");
   }
 
-  public void testExportLocalPropertyInConstructor3() throws Exception {
-    compileAndCheck(
-        "/** @constructor */function F() { /** @export */ this.x;}"
-        + "goog.exportSymbol('F', F);",
-        "/**\n"
-        + " * @constructor\n"
-        + " */\n"
-        + "var F = function() {\n};\n"
-        + "F.prototype.x;\n");
-  }
-
-  public void testExportLocalPropertyInConstructor4() throws Exception {
-    compileAndCheck(
-        "/** @constructor */function F() { /** @export */ this.x = function(/** string */ x){};}"
-        + "goog.exportSymbol('F', F);",
-        "/**\n"
-        + " * @constructor\n"
-        + " */\n"
-        + "var F = function() {\n};\n"
-        + "/**\n"
-        + " * @param {string} x\n"
-        + " * @return {undefined}\n"
-        + " */\n"
-        + "F.prototype.x = function(x) {\n};\n");
-  }
-
   public void testExportLocalPropertyNotInConstructor() throws Exception {
     compileAndCheck(
         "function f() { /** @export */ this.x = 5;}"
diff --git a/test/com/google/javascript/jscomp/GenerateExportsTest.java b/test/com/google/javascript/jscomp/GenerateExportsTest.java
index 7f4fada52..37b1f1d34 100644
--- a/test/com/google/javascript/jscomp/GenerateExportsTest.java
+++ b/test/com/google/javascript/jscomp/GenerateExportsTest.java
@@ -16,7 +16,6 @@
 
 package com.google.javascript.jscomp;
 
-import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
 
 /**
  * Generate exports unit test.
@@ -149,63 +148,6 @@ public final class GenerateExportsTest extends CompilerTestCase {
          "function G() {} google_exportSymbol('G', G); foo();");
   }
 
-  public void testExportClassMember() {
-    test(LINE_JOINER.join(
-          "/** @export */ function F() {}",
-          "/** @export */ F.prototype.method = function() {};"),
-         LINE_JOINER.join(
-          "function F() {}",
-          "google_exportSymbol('F', F);",
-          "F.prototype.method = function() {};",
-          "goog.exportProperty(F.prototype, 'method', F.prototype.method);"));
-  }
-
-  public void testExportEs6ClassSymbol() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    test("/** @export */ class G {} foo();",
-         "class G {} google_exportSymbol('G', G); foo();");
-
-    test("/** @export */ G = class {}; foo();",
-         "G = class {}; google_exportSymbol('G', G); foo();");
-  }
-
-  public void testExportEs6ClassProperty() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    test(LINE_JOINER.join(
-          "/** @export */ G = class {};",
-          "/** @export */ G.foo = class {};"),
-        LINE_JOINER.join(
-          "G = class {}; google_exportSymbol('G', G);",
-          "G.foo = class {};",
-          "goog.exportProperty(G, 'foo', G.foo)"));
-
-    test(LINE_JOINER.join(
-           "G = class {};",
-           "/** @export */ G.prototype.foo = class {};"),
-         LINE_JOINER.join(
-           "G = class {}; G.prototype.foo = class {};",
-           "goog.exportProperty(G.prototype, 'foo', G.prototype.foo)"));
-  }
-
-  public void testExportEs6ClassMembers() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    test(LINE_JOINER.join(
-          "/** @export */ class G {",
-          "  /** @export */ method() {} }"),
-         LINE_JOINER.join(
-          "class G { method() {} }",
-          "google_exportSymbol('G', G);",
-          "goog.exportProperty(G.prototype, 'method', G.prototype.method);"));
-
-    test(LINE_JOINER.join(
-          "/** @export */ class G {",
-          "/** @export */ static method() {} }"),
-         LINE_JOINER.join(
-          "class G { static method() {} }",
-          "google_exportSymbol('G', G);",
-          "goog.exportProperty(G, 'method', G.method);"));
-  }
-
   public void testExportSubclass() {
     test("var goog = {}; function F() {}" +
          "/** @export */ function G() {} goog.inherits(G, F);",
diff --git a/test/com/google/javascript/jscomp/GroupVariableDeclarationsTest.java b/test/com/google/javascript/jscomp/GroupVariableDeclarationsTest.java
new file mode 100644
index 000000000..09a6c7cf5
--- /dev/null
+++ b/test/com/google/javascript/jscomp/GroupVariableDeclarationsTest.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2010 The Closure Compiler Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.javascript.jscomp;
+
+public final class GroupVariableDeclarationsTest extends CompilerTestCase {
+
+  @Override
+  protected void setUp() {
+    super.enableLineNumberCheck(false);
+  }
+
+  public void testGroupingUninitializedVarsInScope() {
+    // basic with just one fn call in between
+    test("var a = 1; f1(); var b;", "var a = 1, b; f1();");
+    // > 1 line of code in between
+    test("var a = \"mangoes\"; f1(); alert(a); var b;",
+         "var a = \"mangoes\", b; f1(); alert(a);");
+    // nested block in between that also contains a declaration + initialization
+    // of the variable that needs to be collapsed
+    test("var a = 1; {var c; alert(c);} var b;",
+         "var a = 1, c, b; {alert(c);}");
+    // multiple variables
+    test("var a = 1; var b = 1; f1(); f2(); var c; var d;",
+         "var a = 1, b, c, d; b = 1; f1(); f2();");
+    test("var a = 1; var b = 2; var c; f1(); f2(); var d, e;",
+         "var a = 1, b, c, d, e; b = 2; f1(); f2();");
+    test("var a = 1, b = 2, c; f1(); f2(); var d; var e; " +
+         "f3(); f4(); var f = 10; var g; var h = a + b;",
+         "var a = 1, b = 2, c, d, e, f, g, h; f1(); f2(); f3(); f4(); " +
+         "f = 10; h = a + b;");
+  }
+
+  public void testGroupingInitializedVarsInScope() {
+    // basic with just one fn call in between
+    test("var a = 1; f1(); var b = 2;", "var a = 1, b; f1(); b = 2;");
+    // > 1 line of code in between
+    test("var a = \"mangoes\"; f1(); alert(a); var b = 2;",
+         "var a = \"mangoes\", b; f1(); alert(a); b = 2;");
+    // nested block in between that also contains a declaration + initialization
+    // of the variable that needs to be collapsed
+    test("var a = 1; {var c = 34; alert(c);} var b = 2;",
+         "var a = 1, c, b; {c = 34; alert(c);} b = 2;");
+    // multiple variables
+    test("var a = 1; var b = 1; f1(); f2(); var c = 3; var d = 4;",
+         "var a = 1, b, c, d; b = 1; f1(); f2(); c = 3; d = 4;");
+    test("var a = 1; var b = 2; var c; f1(); f2(); var d = 4, e;",
+         "var a = 1, b, c, d, e; b = 2; f1(); f2(); d = 4;");
+    test("var a = 1, b = 2, c; f1(); f2(); var d; var e = 6; " +
+         "f3(); f4(); var f; var g; var h = a + b;",
+         "var a = 1, b = 2, c, d, e, f, g, h; f1(); f2(); e = 6; " +
+         "f3(); f4(); h = a + b;");
+  }
+
+  public void testGroupingVarsInForAndForInLoops() {
+    // test for loop
+    test("var a = 1; for (var x = 0; x < 10; ++x) {a++;} var y;",
+         "var a = 1, x, y; for (x = 0; x < 10; ++x) {a++;}");
+    test("var a = 1, x; for (x = 0; x < 10; ++x) {a++;} var y;",
+         "var a = 1, x, y; for (x = 0; x < 10; ++x) {a++;}");
+    test("var a = 1, x; for (x; x < 10; ++x) {a++;} var y;",
+         "var a = 1, x, y; for (x; x < 10; ++x) {a++;}");
+    test("var a = 1; for (; a < 10; ++a) {alert(a);} var y;",
+         "var a = 1, y; for (; a < 10; ++a) {alert(a);}");
+    test("var a = 1; for (var x; x < 10; ++x) {a += 2;} var y = 5;",
+         "var a = 1, x, y; for (; x < 10; ++x) {a += 2;} y = 5;");
+    // multiple loop-control variables in for loop
+    test("var a = 1; " +
+         "for (var a1 = 0, a2 = 10; a1 < 10 && a2 > 0; ++a1, --a2) {}" +
+         "var x = 5;",
+         "var a = 1, x;" +
+         "for (var a1 = 0, a2 = 10; a1 < 10 && a2 > 0; ++a1, --a2) {} " +
+         "x = 5;");
+    test("var a = 1; " +
+         "for (var a1 = 0, a2; a1 < 10 && a2 > 0; ++a1, --a2) {}" +
+         "var x = 5;",
+         "var a = 1, a1, a2, x;" +
+         "for (a1 = 0; a1 < 10 && a2 > 0; ++a1, --a2) {}" +
+         "x = 5;");
+    test("var a = 1; " +
+         "for (var a1, a2; a1 < 10 && a2 > 0; ++a1, --a2) {}" +
+         "var x = 5;",
+         "var a = 1, a1, a2, x;" +
+         "for (; a1 < 10 && a2 > 0; ++a1, --a2) {}" +
+         "x = 5;");
+
+    // test for-in loop
+    test("var a = [1, 2, 3, 4]; for (var z in a) {alert(z);} var y;",
+         "var a = [1, 2, 3, 4], z, y; for (z in a) {alert(z);}");
+    test("var a = [1, 2, 3, 4]; for (var z in a) {alert(z);} var y = 5;",
+         "var a = [1, 2, 3, 4], z, y; for (z in a) {alert(z);} y = 5;");
+    test("var a; for (var z in a = [1, 2, 3, 4]) {alert(z);} var y, x = 5;",
+         "var a, z, y, x; for (z in a = [1, 2, 3, 4]) {alert(z);} x = 5;");
+    test("var a, z; for (z in a = [1, 2, 3, 4]) {alert(z);} var y, x = 5;",
+         "var a, z, y, x; for (z in a = [1, 2, 3, 4]) {alert(z);} x = 5;");
+  }
+
+  public void testGroupingVarsInForAndForInLoops_initializer() {
+    setExpectParseWarningsThisTest();
+    test("var a; for (var z = 1 in a = [1, 2, 3, 4]) {alert(z);} var y, x = 5;",
+         "var a, y, x; for (var z = 1 in a = [1, 2, 3, 4]) {alert(z);} x = 5;");
+  }
+
+  public void testGroupingVarsNestedFunction() {
+    test("function f(b) {var x; function g() {var x; a = x; var y;} var a;}",
+         "function f(b) {var x, a; function g() {var x, y; a = x;}}");
+  }
+
+  public void testGroupingVarsInnerFunction() {
+    test("function f(b) {var x; h = x * x; var myfn = function() " +
+         "{var x; a = x; var y;}; var a;}",
+         "function f(b) {var x, myfn, a; h = x * x; myfn = function() " +
+         "{var x, y; a = x;};}");
+  }
+
+  public void testGroupingVarsFirstStatementNotVar() {
+    test("f(); var a; g(); var b;", "f(); var a, b; g();");
+  }
+
+  public void testGroupingVarsInScopeRegtest() {
+    // regtest with lots of different scopes
+    test("var x = 0, y = 1, z;" +
+         "function f1(aa, bb) {" +
+         "  if (y) {" +
+         "    if (x === 0) {" +
+         "      var h, r = 999;" +
+         "    }" +
+         "  } else {" +
+         "    r = 1000;" +
+         "  }" +
+         "  var mylist = [1, 2, 3, 4];" +
+         "  var k1 = 200, k2 = 400;" +
+         "  for (var i1 = 0; i1 < 10; ++i1) {" +
+         "    for (var i2 in mylist) {" +
+         "      alert(i1);" +
+         "    }" +
+         "  }" +
+         "  var jam, q = 100;" +
+         "  var myfn = function() {" +
+         "    var x = 1;" +
+         "    f5();" +
+         "    var z = 5;" +
+         "  };" +
+         "  function f5() {" +
+         "    var aa = 5;" +
+         "    if (y === 1) {" +
+         "      var x = 100;" +
+         "    }" +
+         "  }" +
+         "}" +
+         "var h = x + y;" +
+         "function g() {" +
+         "  y = 0;" +
+         "  { var x = 200;}" +
+         "  var h = y + x;" +
+         "}" +
+         "var ggg = 0;",  // End of input
+         "var x = 0, y = 1, z, h, ggg;" +
+         "function f1(aa, bb) {" +
+         "  if (y) {" +
+         "    if (x === 0) {" +
+         "      var h, r = 999, mylist, i1, i2, jam, q, myfn;" +
+         "    }" +
+         "  } else {" +
+         "    r = 1000;" +
+         "  }" +
+         "  mylist = [1, 2, 3, 4];" +
+         "  var k1 = 200, k2 = 400;" +
+         "  for (i1 = 0; i1 < 10; ++i1) {" +
+         "    for (i2 in mylist) {" +
+         "      alert(i1);" +
+         "    }" +
+         "  }" +
+         "  q = 100; " +
+         "  myfn = function() {" +
+         "    var x = 1, z;" +
+         "    f5();" +
+         "    z = 5;" +
+         "  };" +
+         "  function f5() {" +
+         "    var aa = 5, x;" +
+         "    if (y === 1) {" +
+         "      x = 100;" +
+         "    }" +
+         "  }" +
+         "}" +
+         "h = x + y;" +
+         "function g() {" +
+         "  y = 0;" +
+         "  { var x = 200, h;}" +
+         "  h = y + x;" +
+         "}" +
+         "ggg = 0;");
+  }
+
+  @Override
+  protected CompilerPass getProcessor(Compiler compiler) {
+    return new GroupVariableDeclarations(compiler);
+  }
+}
diff --git a/test/com/google/javascript/jscomp/InferConstsTest.java b/test/com/google/javascript/jscomp/InferConstsTest.java
index ded2b843a..22054be06 100644
--- a/test/com/google/javascript/jscomp/InferConstsTest.java
+++ b/test/com/google/javascript/jscomp/InferConstsTest.java
@@ -16,7 +16,6 @@
 package com.google.javascript.jscomp;
 
 import com.google.common.collect.ImmutableList;
-import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
 import com.google.javascript.rhino.Node;
 
 import junit.framework.TestCase;
@@ -30,55 +29,21 @@ import java.util.Map;
  */
 public final class InferConstsTest extends TestCase {
   public void testSimple() {
-    testConsts("var x = 3;", "x");
-    testConsts("/** @const */ var x;", "x");
-    testConsts("var x = 3, y = 4;", "x", "y");
-    testConsts("var x = 3, y;", "x");
-    testConsts("var x = 3;  function f(){x;}", "x");
-  }
-
-  public void testSimpleLetConst() {
-    testConsts("let x = 3, y", "x");
-    testConsts("let x = 3; let y = 4;", "x", "y");
-    testConsts("let x = 3, y = 4; x++;", "y");
-    testConsts("let x = 3;  function f(){let x = 4;}", "x");
-    testConsts("/** @const */ let x;", "x");
-    testConsts("const x = 1;", "x");
-  }
-
-  public void testUnfound() {
-    testNotConsts("var x = 2; x++;", "x");
-    testNotConsts("var x = 2; x = 3;", "x");
-    testNotConsts("var x = 3;  function f(){x++;}", "x");
-    testNotConsts("let x = 3; x++;", "x");
-    testNotConsts("let x = 3; x = 2;", "x", "y");
-    testNotConsts("/** @const */let x; let y;", "y");
-    testNotConsts("let x = 3;  function f() {let x = 4; x++;} x++;", "x");
+    testInferConsts("var x = 3;", "x");
+    testInferConsts("var x = 3, y = 4;", "x", "y");
   }
 
   public void testArguments() {
-    testConsts("var arguments = 3;");
-  }
-
-  private void testConsts(String js, String... constants) {
-    testInferConstsHelper(true, js, constants);
+    testInferConsts("var arguments = 3;");
   }
 
-  private void testNotConsts(String js, String... constants) {
-    testInferConstsHelper(false, js, constants);
-  }
-
-  private void testInferConstsHelper(boolean constExpected,
-      String js, String... constants) {
+  public void testInferConsts(String js, String... constants) {
     Compiler compiler = new Compiler();
 
     SourceFile extern = SourceFile.fromCode("extern", "");
     SourceFile input = SourceFile.fromCode("js", js);
     compiler.init(ImmutableList.<SourceFile>of(), ImmutableList.of(input),
         new CompilerOptions());
-
-    compiler.options.setLanguageIn(LanguageMode.ECMASCRIPT6);
-    compiler.setLanguageMode(LanguageMode.ECMASCRIPT6);
     compiler.parseInputs();
 
     CompilerPass inferConsts = new InferConsts(compiler);
@@ -90,15 +55,9 @@ public final class InferConstsTest extends TestCase {
 
     FindConstants constFinder = new FindConstants(constants);
     NodeTraversal.traverse(compiler, n, constFinder);
-
     for (String name : constants) {
-      if (constExpected) {
-        assertTrue("Expect constant: " + name,
-            constFinder.foundNodes.containsKey(name));
-      } else {
-        assertTrue("Unexpected constant: " + name,
-            !constFinder.foundNodes.containsKey(name));
-      }
+      assertTrue("Did not find a const node for " + name,
+          constFinder.foundNodes.containsKey(name));
     }
   }
 
diff --git a/test/com/google/javascript/jscomp/IntegrationTest.java b/test/com/google/javascript/jscomp/IntegrationTest.java
index 8dba7b94e..56eb31d5e 100644
--- a/test/com/google/javascript/jscomp/IntegrationTest.java
+++ b/test/com/google/javascript/jscomp/IntegrationTest.java
@@ -442,6 +442,7 @@ public final class IntegrationTest extends IntegrationTestCase {
   public void testCheckReferencesOn() {
     CompilerOptions options = createCompilerOptions();
     options.setCheckSymbols(true);
+    options.setAggressiveVarCheck(CheckLevel.ERROR);
     test(options, "x = 3; var x = 5;", VariableReferenceCheck.EARLY_REFERENCE);
   }
 
@@ -849,6 +850,7 @@ public final class IntegrationTest extends IntegrationTestCase {
     options.syntheticBlockStartMarker = "synStart";
     options.syntheticBlockEndMarker = "synEnd";
     options.setCheckSymbols(true);
+    options.setAggressiveVarCheck(CheckLevel.ERROR);
     options.processObjectPropertyString = true;
     options.setCollapseProperties(true);
     test(options, CLOSURE_BOILERPLATE, CLOSURE_COMPILED);
diff --git a/test/com/google/javascript/jscomp/NewTypeInferenceES5OrLowerTest.java b/test/com/google/javascript/jscomp/NewTypeInferenceES5OrLowerTest.java
index e2d83eb6b..f926a03d0 100644
--- a/test/com/google/javascript/jscomp/NewTypeInferenceES5OrLowerTest.java
+++ b/test/com/google/javascript/jscomp/NewTypeInferenceES5OrLowerTest.java
@@ -4631,17 +4631,13 @@ public final class NewTypeInferenceES5OrLowerTest extends NewTypeInferenceTestBa
   public void testSimpleInferNamespaces() {
     typeCheck(Joiner.on('\n').join(
         "/** @const */ var ns = {};",
-        "/** @const */ ns.numprop = 123;",
-        "/** @const */ var x = ns;",
-        "function f() { var /** string */ s = x.numprop; }"),
-        NewTypeInference.MISTYPED_ASSIGN_RHS);
+        "/** @const */ var x = ns;"),
+        GlobalTypeInfo.COULD_NOT_INFER_CONST_TYPE);
 
     typeCheck(Joiner.on('\n').join(
         "/** @enum {number} */ var e = { FOO : 5 };",
-        "/** @const */ e.numprop = 123;",
-        "/** @const */ var x = e;",
-        "function f() { var /** string */ s = x.numprop; }"),
-        NewTypeInference.MISTYPED_ASSIGN_RHS);
+        "/** @const */ var x = e;"),
+        GlobalTypeInfo.COULD_NOT_INFER_CONST_TYPE);
 
     typeCheck(Joiner.on('\n').join(
         "/** @const */ var ns = {};",
@@ -11425,6 +11421,7 @@ public final class NewTypeInferenceES5OrLowerTest extends NewTypeInferenceTestBa
         "goog.forwardDeclare = function(name){};");
 
   public void testForwardDeclarations() {
+
     typeCheck(Joiner.on('\n').join(FORWARD_DECLARATION_DEFINITIONS,
         "goog.addDependency('', ['Foo'], []);",
         "goog.forwardDeclare('Bar');",
@@ -11508,32 +11505,6 @@ public final class NewTypeInferenceES5OrLowerTest extends NewTypeInferenceTestBa
         "function f(/** !ns.Foo */ x) {}",
         "/** @constructor */ function Bar(){}",
         "f(new Bar);"));
-
-    typeCheck(Joiner.on('\n').join(FORWARD_DECLARATION_DEFINITIONS,
-        "goog.forwardDeclare('ns.Foo');",
-        "/** @const */",
-        "var ns = {};",
-        "/** @const */",
-        "var c = ns;"),
-        GlobalTypeInfo.COULD_NOT_INFER_CONST_TYPE);
-
-    typeCheck(Joiner.on('\n').join(FORWARD_DECLARATION_DEFINITIONS,
-            "goog.forwardDeclare('ns.ns2.Foo');",
-            "/** @const */",
-            "var ns = {};",
-            "/** @const */",
-            "ns.ns2 = {};",
-            "/** @const */",
-            "var c = ns;",
-            "var x = new ns.ns2.Foo();"),
-        GlobalTypeInfo.COULD_NOT_INFER_CONST_TYPE,
-        TypeCheck.INEXISTENT_PROPERTY);
-
-    typeCheck(Joiner.on('\n').join(FORWARD_DECLARATION_DEFINITIONS,
-            "goog.forwardDeclare('Foo.Bar');",
-            "/** @constructor */",
-            "function Foo() {}",
-            "var x = new Foo.Bar()"));
   }
 
   public void testDontLookupInParentScopeForNamesWithoutDeclaredType() {
@@ -13077,14 +13048,14 @@ public final class NewTypeInferenceES5OrLowerTest extends NewTypeInferenceTestBa
         "var x = new f();"));
   }
 
-  public void testDontAddPropsToNamespacesAfterEarlyFinalization() {
+  public void testDontAddPropsToNomTypesAfterEarlyFinalization() {
     typeCheck(Joiner.on('\n').join(
         "/** @constructor */",
         "function Foo() {}",
         "/** @const */",
         "var Bar = Foo;",
         "Foo.prop = 123;"),
-        GlobalTypeInfo.NAMESPACE_MODIFIED_AFTER_FINALIZATION);
+        GlobalTypeInfo.NOMINAL_TYPE_MODIFIED_AFTER_FINALIZATION);
 
     typeCheck(Joiner.on('\n').join(
         "/** @constructor */",
@@ -13094,7 +13065,7 @@ public final class NewTypeInferenceES5OrLowerTest extends NewTypeInferenceTestBa
         "/** @const */",
         "var Baz = Bar;",
         "Foo.prop = 123;"),
-        GlobalTypeInfo.NAMESPACE_MODIFIED_AFTER_FINALIZATION);
+        GlobalTypeInfo.NOMINAL_TYPE_MODIFIED_AFTER_FINALIZATION);
 
     typeCheck(Joiner.on('\n').join(
         "/** @interface */",
@@ -13104,7 +13075,7 @@ public final class NewTypeInferenceES5OrLowerTest extends NewTypeInferenceTestBa
         "/** @const */",
         "var Baz = Bar;",
         "Foo.prototype.prop = 123;"),
-        GlobalTypeInfo.NAMESPACE_MODIFIED_AFTER_FINALIZATION);
+        GlobalTypeInfo.NOMINAL_TYPE_MODIFIED_AFTER_FINALIZATION);
 
     typeCheck(Joiner.on('\n').join(
         "/** @constructor */",
@@ -13112,7 +13083,7 @@ public final class NewTypeInferenceES5OrLowerTest extends NewTypeInferenceTestBa
         "/** @const */",
         "var Bar = Foo;",
         "Foo.prototype.prop = 123;"),
-        GlobalTypeInfo.NAMESPACE_MODIFIED_AFTER_FINALIZATION);
+        GlobalTypeInfo.NOMINAL_TYPE_MODIFIED_AFTER_FINALIZATION);
 
     typeCheck(Joiner.on('\n').join(
         "/** @interface */",
@@ -13122,55 +13093,6 @@ public final class NewTypeInferenceES5OrLowerTest extends NewTypeInferenceTestBa
         "/** @const */",
         "var Baz = Bar;",
         "Foo.prop = 123;"),
-        GlobalTypeInfo.NAMESPACE_MODIFIED_AFTER_FINALIZATION);
-
-    typeCheck(Joiner.on('\n').join(
-        "/** @const */",
-        "var ns = {}",
-        "/** @const */",
-        "var x = ns;",
-        "ns.prop = 123;"),
-        GlobalTypeInfo.NAMESPACE_MODIFIED_AFTER_FINALIZATION);
-
-    typeCheck(Joiner.on('\n').join(
-        "/** @enum */",
-        "var e = { A: 1 }",
-        "/** @const */",
-        "var x = e;",
-        "e.prop = 123;"),
-        GlobalTypeInfo.NAMESPACE_MODIFIED_AFTER_FINALIZATION);
-
-    typeCheck(Joiner.on('\n').join(
-        "/** @const */",
-        "var ns = {};",
-        "/** @constructor */",
-        "ns.Foo = function() {};",
-        "/** @const */",
-        "var x = ns;",
-        "/** @type {number} */",
-        "ns.Foo.prop = 123;"),
-        GlobalTypeInfo.NAMESPACE_MODIFIED_AFTER_FINALIZATION);
-
-    typeCheck(Joiner.on('\n').join(
-        "/** @constructor */",
-        "function Bar() {}",
-        "/** @constructor */",
-        "Bar.Foo = function() {};",
-        "/** @const */",
-        "var x = Bar;",
-        "/** @type {number} */",
-        "Bar.Foo.prop = 123;"),
-        GlobalTypeInfo.NAMESPACE_MODIFIED_AFTER_FINALIZATION);
-
-    typeCheck(Joiner.on('\n').join(
-        "/** @enum */",
-        "var e = {A:1};",
-        "/** @constructor */",
-        "e.Foo = function() {};",
-        "/** @const */",
-        "var x = e;",
-        "/** @type {number} */",
-        "e.Foo.prop = 123;"),
-        GlobalTypeInfo.NAMESPACE_MODIFIED_AFTER_FINALIZATION);
+        GlobalTypeInfo.NOMINAL_TYPE_MODIFIED_AFTER_FINALIZATION);
   }
 }
diff --git a/test/com/google/javascript/jscomp/NewTypeInferenceES6TypedTest.java b/test/com/google/javascript/jscomp/NewTypeInferenceES6TypedTest.java
index 85b3ab7c5..c66372cfc 100644
--- a/test/com/google/javascript/jscomp/NewTypeInferenceES6TypedTest.java
+++ b/test/com/google/javascript/jscomp/NewTypeInferenceES6TypedTest.java
@@ -206,11 +206,4 @@ public final class NewTypeInferenceES6TypedTest extends NewTypeInferenceTestBase
         "interface Baz extends Foo, Bar {}"),
         TypeCheck.INCOMPATIBLE_EXTENDED_PROPERTY_TYPE);
   }
-
-  public void testAmbientDeclaration() {
-    typeCheck("declare var x: number;");
-    typeCheck("declare function f(): number;");
-    typeCheck("declare class C { constructor(); }");
-    typeCheck("declare enum Foo { BAR }");
-  }
 }
diff --git a/test/com/google/javascript/jscomp/NodeUtilTest.java b/test/com/google/javascript/jscomp/NodeUtilTest.java
index 0c27a4797..eda4316e4 100644
--- a/test/com/google/javascript/jscomp/NodeUtilTest.java
+++ b/test/com/google/javascript/jscomp/NodeUtilTest.java
@@ -113,13 +113,6 @@ public final class NodeUtilTest extends TestCase {
     // Known but getBooleanValue return false for expressions with side-effects
     assertPureBooleanUnknown("{a:foo()}");
     assertPureBooleanUnknown("[foo()]");
-
-    assertPureBooleanTrue("`definiteLength`");
-    assertPureBooleanFalse("``");
-    assertPureBooleanUnknown("`${indefinite}Length`");
-
-    assertPureBooleanTrue("class Klass{}");
-
   }
 
   private void assertPureBooleanTrue(String val) {
@@ -319,28 +312,6 @@ public final class NodeUtilTest extends TestCase {
     testGetFunctionName(parent.getLastChild(), "qualified.name2");
   }
 
-  public void testGetBestFunctionName1() throws Exception {
-    Compiler compiler = new Compiler();
-    Node parent = compiler.parseTestCode("function func(){}");
-
-    assertEquals("func",
-        NodeUtil.getNearestFunctionName(parent.getFirstChild()));
-  }
-
-  public void testGetBestFunctionName2() throws Exception {
-    Compiler compiler = new Compiler();
-    CompilerOptions options = new CompilerOptions();
-    options.setLanguageIn(LanguageMode.ECMASCRIPT6);
-    compiler.initOptions(options);
-
-    Node parent = compiler.parseTestCode("var obj = {memFunc(){}}")
-        .getFirstChild().getFirstChild().getFirstChild().getFirstChild();
-
-    assertEquals("memFunc",
-        NodeUtil.getNearestFunctionName(parent.getLastChild()));
-  }
-
-
   private void testGetFunctionName(Node function, String name) {
     assertEquals(Token.FUNCTION, function.getType());
     assertEquals(name, NodeUtil.getFunctionName(function));
@@ -1773,14 +1744,6 @@ public final class NodeUtilTest extends TestCase {
     assertNodeTreesEqual(expected, actual);
   }
 
-  public void testGetBestJsDocInfoForClasses() {
-    Node classNode = getClassNode("/** @export */ class Foo {}");
-    assertTrue(NodeUtil.getBestJSDocInfo(classNode).isExport());
-
-    classNode = getClassNode("/** @export */ var Foo = class {}");
-    assertTrue(NodeUtil.getBestJSDocInfo(classNode).isExport());
-  }
-
   private boolean executedOnceTestCase(String code) {
     Node ast = parse(code);
     Node nameNode = getNameNode(ast, "x");
@@ -1804,24 +1767,6 @@ public final class NodeUtilTest extends TestCase {
         NodeUtil.getNearestFunctionName(getFunctionNode(js)));
   }
 
-  static Node getClassNode(String js) {
-   Node root = parse(js);
-    return getClassNode(root);
-  }
-
-  static Node getClassNode(Node n) {
-    if (n.isClass()) {
-      return n;
-    }
-    for (Node c : n.children()) {
-      Node result = getClassNode(c);
-      if (result != null) {
-        return result;
-      }
-    }
-    return null;
-  }
-
   static Node getFunctionNode(String js) {
     Node root = parse(js);
     return getFunctionNode(root);
diff --git a/test/com/google/javascript/jscomp/ObjectPropertyStringPreprocessTest.java b/test/com/google/javascript/jscomp/ObjectPropertyStringPreprocessTest.java
index ad6b3d981..ca5e65065 100644
--- a/test/com/google/javascript/jscomp/ObjectPropertyStringPreprocessTest.java
+++ b/test/com/google/javascript/jscomp/ObjectPropertyStringPreprocessTest.java
@@ -16,7 +16,6 @@
 
 package com.google.javascript.jscomp;
 
-import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
 
 /**
  * Tests for {@link ObjectPropertyStringPreprocess}
@@ -68,22 +67,4 @@ public final class ObjectPropertyStringPreprocessTest extends CompilerTestCase {
     testError("new goog.testing.ObjectPropertyString(foo, bar)",
         ObjectPropertyStringPreprocess.STRING_LITERAL_EXPECTED_ERROR);
   }
-
-  public void testTemplateStringError() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testError("new goog.testing.ObjectPropertyString(foo, `bar`)",
-        ObjectPropertyStringPreprocess.STRING_LITERAL_EXPECTED_ERROR);
-    testError("new goog.testing.ObjectPropertyString(foo, `${A}bar`)",
-        ObjectPropertyStringPreprocess.STRING_LITERAL_EXPECTED_ERROR);
-    testError("new goog.testing.ObjectPropertyString(foo, `bar${A}`)",
-        ObjectPropertyStringPreprocess.STRING_LITERAL_EXPECTED_ERROR);
-  }
-
-  public void testTaggedTemplateError() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testError("new goog.testing.ObjectPropertyString(foo, tagged`bar`)",
-        ObjectPropertyStringPreprocess.STRING_LITERAL_EXPECTED_ERROR);
-    testError("new goog.testing.ObjectPropertyString(foo, tagged`${Foo}bar`)",
-        ObjectPropertyStringPreprocess.STRING_LITERAL_EXPECTED_ERROR);
-  }
 }
diff --git a/test/com/google/javascript/jscomp/ProcessCommonJSModulesTest.java b/test/com/google/javascript/jscomp/ProcessCommonJSModulesTest.java
index 58a4db162..12b3860a9 100644
--- a/test/com/google/javascript/jscomp/ProcessCommonJSModulesTest.java
+++ b/test/com/google/javascript/jscomp/ProcessCommonJSModulesTest.java
@@ -157,6 +157,30 @@ public final class ProcessCommonJSModulesTest extends CompilerTestCase {
         "var name$$module$foo$bar = module$foo$name;");
   }
 
+  public void testModuleExportsScope() {
+    setFilename("test");
+    test(
+        "var foo = function (module) {module.exports = {};};" +
+        "module.exports = foo;",
+        "goog.provide('module$test');" +
+        "var foo$$module$test=function(module){module.exports={}};" +
+        "var module$test=foo$$module$test");
+    test(
+        "var foo = function () {var module = {};module.exports = {};};" +
+        "module.exports = foo;",
+        "goog.provide('module$test');" +
+        "var foo$$module$test=function(){var module={};module.exports={}};" +
+        "var module$test=foo$$module$test");
+    test(
+        "var foo = function () {if (true) var module = {};" +
+        "module.exports = {};};" +
+        "module.exports = foo;",
+        "goog.provide('module$test');" +
+        "var foo$$module$test=function(){if(true)var module={};" +
+        "module.exports={}};" +
+        "var module$test=foo$$module$test");
+  }
+
   public void testSortInputs() throws Exception {
     SourceFile a = SourceFile.fromCode("a.js",
             "require('b');require('c')");
diff --git a/test/com/google/javascript/jscomp/ScopedAliasesTest.java b/test/com/google/javascript/jscomp/ScopedAliasesTest.java
index 23a3fca8b..4c4edd35c 100644
--- a/test/com/google/javascript/jscomp/ScopedAliasesTest.java
+++ b/test/com/google/javascript/jscomp/ScopedAliasesTest.java
@@ -43,7 +43,7 @@ public final class ScopedAliasesTest extends CompilerTestCase {
   private static final String GOOG_SCOPE_END_BLOCK = "});";
 
   private static final String SCOPE_NAMESPACE =
-      "/** @const */ var $jscomp = {}; /** @const */ $jscomp.scope = {};";
+      "var $jscomp = {}; $jscomp.scope = {};";
 
   private static final String EXTERNS = "var window;";
 
@@ -52,6 +52,7 @@ public final class ScopedAliasesTest extends CompilerTestCase {
 
   public ScopedAliasesTest() {
     super(EXTERNS);
+    compareJsDoc = false;
   }
 
   @Override
@@ -369,33 +370,25 @@ public final class ScopedAliasesTest extends CompilerTestCase {
             "  /** @param {Foo} foo */",
             "  y: function(foo) { }",
             "};"),
-        LINE_JOINER.join(
-            "goog.x = {",
-            "  /** @param {goog.Foo} foo */",
-            "  y: function(foo) {}",
-            "};"));
+        "goog.x = {y: function(foo) { }};");
 
     testScoped(
         LINE_JOINER.join(
             "var Foo = goog.Foo;",
             "goog.x = {",
-            "  y: /** @param {Foo} foo */ function(foo) {}",
+            "  y:",
+            "  /** @param {Foo} foo */ function(foo) {}",
             "};"),
-        LINE_JOINER.join(
-            "goog.x = {",
-            "  y: /** @param {goog.Foo} foo */ function(foo) {}",
-            "};"));
+        "goog.x = {y: function(foo) {}};");
 
     testScoped(
         LINE_JOINER.join(
             "var Foo = goog.Foo;",
             "goog.x = {",
-            "  y: /** @type {function(Foo)} */ (function(foo) {})",
+            "  y:",
+            "  /** @type {function(Foo)} */ (function(foo) {})",
             "};"),
-        LINE_JOINER.join(
-            "goog.x = {",
-            "  y: /** @type {function(goog.Foo)} */ (function(foo) {})",
-            "};"));
+        "goog.x = {y: /** @type {function(Foo)} */ (function(foo) {})};");
   }
 
   public void testObjectLiteralShorthand() {
@@ -499,82 +492,81 @@ public final class ScopedAliasesTest extends CompilerTestCase {
   public void testJsDocType() {
     testTypes(
         "var x = goog.Timer;",
-        LINE_JOINER.join(
-            "/** @type {goog.Timer} */ types.actual;",
-            "/** @type {goog.Timer} */ types.expected;"));
+        ""
+        + "/** @type {x} */ types.actual;"
+        + "/** @type {goog.Timer} */ types.expected;");
   }
 
   public void testJsDocParameter() {
     testTypes(
         "var x = goog.Timer;",
-        LINE_JOINER.join(
-            "/** @param {goog.Timer} a */ types.actual;",
-            "/** @param {goog.Timer} a */ types.expected;"));
+        ""
+        + "/** @param {x} a */ types.actual;"
+        + "/** @param {goog.Timer} a */ types.expected;");
   }
 
   public void testJsDocExtends() {
     testTypes(
         "var x = goog.Timer;",
-        LINE_JOINER.join(
-            "/** @extends {goog.Timer} */ types.actual;",
-            "/** @extends {goog.Timer} */ types.expected;"));
+        ""
+        + "/** @extends {x} */ types.actual;"
+        + "/** @extends {goog.Timer} */ types.expected;");
   }
 
   public void testJsDocImplements() {
     testTypes(
         "var x = goog.Timer;",
-        LINE_JOINER.join(
-            "/** @implements {goog.Timer} */ types.actual;",
-            "/** @implements {goog.Timer} */ types.expected;"));
+        ""
+        + "/** @implements {x} */ types.actual;"
+        + "/** @implements {goog.Timer} */ types.expected;");
   }
 
   public void testJsDocEnum() {
     testTypes(
         "var x = goog.Timer;",
-        LINE_JOINER.join(
-            "",
-            "/** @enum {goog.Timer} */ types.actual;",
-            "/** @enum {goog.Timer} */ types.expected;"));
+        ""
+        + "/** @enum {x} */ types.actual;"
+        + "/** @enum {goog.Timer} */ types.expected;");
   }
 
   public void testJsDocReturn() {
     testTypes(
         "var x = goog.Timer;",
-        LINE_JOINER.join(
-            "/** @return {goog.Timer} */ types.actual;",
-            "/** @return {goog.Timer} */ types.expected;"));
+        ""
+        + "/** @return {x} */ types.actual;"
+        + "/** @return {goog.Timer} */ types.expected;");
   }
 
   public void testJsDocThis() {
     testTypes(
         "var x = goog.Timer;",
-        LINE_JOINER.join(
-            "/** @this {goog.Timer} */ types.actual;",
-            "/** @this {goog.Timer} */ types.expected;"));
+        ""
+        + "/** @this {x} */ types.actual;"
+        + "/** @this {goog.Timer} */ types.expected;");
   }
 
   public void testJsDocThrows() {
     testTypes(
         "var x = goog.Timer;",
-        LINE_JOINER.join(
-            "/** @throws {goog.Timer} */ types.actual;",
-            "/** @throws {goog.Timer} */ types.expected;"));
+        ""
+        + "/** @throws {x} */ types.actual;"
+        + "/** @throws {goog.Timer} */ types.expected;");
   }
 
   public void testJsDocSubType() {
     testTypes(
         "var x = goog.Timer;",
-        LINE_JOINER.join(
-            "/** @type {goog.Timer.Enum} */ types.actual;",
-            "/** @type {goog.Timer.Enum} */ types.expected;"));
+        ""
+        + "/** @type {x.Enum} */ types.actual;"
+        + "/** @type {goog.Timer.Enum} */ types.expected;");
   }
 
   public void testJsDocTypedef() {
     testTypes(
         "var x = goog.Timer;",
-        LINE_JOINER.join(
-            "/** @typedef {goog.Timer} */ types.actual;",
-            "/** @typedef {goog.Timer} */ types.expected;"));
+        ""
+        + "/** @typedef {x} */ types.actual;"
+        + "/** @typedef {goog.Timer} */ types.expected;");
 
     testScoped(
         LINE_JOINER.join(
@@ -599,54 +591,50 @@ public final class ScopedAliasesTest extends CompilerTestCase {
   public void testJsDocRecord() {
     enableTypeCheck(CheckLevel.WARNING);
     runTypeCheckAfterProcessing = true;
-    test(
-        LINE_JOINER.join(
-            "/** @const */ var ns = {};",
-            "goog.scope(function () {",
-            "  var x = goog.Timer;",
-            "  /** @type {{x: string}} */ ns.y = {'goog.Timer': 'x'};",
-            "});"),
-        LINE_JOINER.join(
-            "/** @const */ var ns = {};",
-            "/** @type {{x: string}} */ ns.y = {'goog.Timer': 'x'};"),
-        null,
-        TypeValidator.TYPE_MISMATCH_WARNING);
+    test("/** @const */ var ns = {};" +
+         "goog.scope(function () {" +
+         "  var x = goog.Timer;" +
+         "  /** @type {{x: string}} */ ns.y = {'goog.Timer': 'x'};" +
+         "});",
+         " var ns = {}; ns.y = {'goog.Timer': 'x'};",
+         null,
+         TypeValidator.TYPE_MISMATCH_WARNING);
   }
 
   public void testArrayJsDoc() {
     testTypes(
         "var x = goog.Timer;",
-        LINE_JOINER.join(
-            "/** @type {Array.<goog.Timer>} */ types.actual;",
-            "/** @type {Array.<goog.Timer>} */ types.expected;"));
+        ""
+        + "/** @type {Array.<x>} */ types.actual;"
+        + "/** @type {Array.<goog.Timer>} */ types.expected;");
   }
 
   public void testObjectJsDoc() {
     testTypes(
         "var x = goog.Timer;",
-        LINE_JOINER.join(
-            "/** @type {{someKey: goog.Timer}} */ types.actual;",
-            "/** @type {{someKey: goog.Timer}} */ types.expected;"));
+        ""
+        + "/** @type {{someKey: x}} */ types.actual;"
+        + "/** @type {{someKey: goog.Timer}} */ types.expected;");
     testTypes(
         "var x = goog.Timer;",
-        LINE_JOINER.join(
-            "/** @type {{x: number}} */ types.actual;",
-            "/** @type {{x: number}} */ types.expected;"));
+        ""
+        + "/** @type {{x: number}} */ types.actual;"
+        + "/** @type {{x: number}} */ types.expected;");
   }
 
   public void testObjectJsDoc2() {
     testTypes(
         "var x = goog$Timer;",
-        LINE_JOINER.join(
-            "/** @type {{someKey: goog$Timer}} */ types.actual;",
-            "/** @type {{someKey: goog$Timer}} */ types.expected;"));
+        ""
+        + "/** @type {{someKey: x}} */ types.actual;"
+        + "/** @type {{someKey: goog$Timer}} */ types.expected;");
   }
 
   public void testUnionJsDoc() {
     testTypes(
         "var x = goog.Timer;",
         ""
-        + "/** @type {goog.Timer|Object} */ types.actual;"
+        + "/** @type {x|Object} */ types.actual;"
         + "/** @type {goog.Timer|Object} */ types.expected;");
   }
 
@@ -654,12 +642,12 @@ public final class ScopedAliasesTest extends CompilerTestCase {
     testTypes(
         "var x = goog.Timer;",
         ""
-        + "/** @type {function(goog.Timer) : void} */ types.actual;"
+        + "/** @type {function(x) : void} */ types.actual;"
         + "/** @type {function(goog.Timer) : void} */ types.expected;");
     testTypes(
         "var x = goog.Timer;",
         ""
-        + "/** @type {function() : goog.Timer} */ types.actual;"
+        + "/** @type {function() : x} */ types.actual;"
         + "/** @type {function() : goog.Timer} */ types.expected;");
   }
 
@@ -707,7 +695,7 @@ public final class ScopedAliasesTest extends CompilerTestCase {
     testTypes(
         "var b = a.b;" +
         "var c = b.c;",
-        "/** @param {a.b.c.MyType} x */ types.actual;" +
+        "/** @param {c.MyType} x */ types.actual;" +
         "/** @param {a.b.c.MyType} x */ types.expected;");
   }
 
@@ -871,7 +859,6 @@ public final class ScopedAliasesTest extends CompilerTestCase {
          "var ns = {};" +
          "ns.sub = {};" +
          "/** @constructor */ ns.sub.C = function () {};" +
-         "/** @type {ns.sub.C} */" +
          "$jscomp.scope.x = null;");
   }
 
@@ -879,19 +866,19 @@ public final class ScopedAliasesTest extends CompilerTestCase {
     enableTypeCheck(CheckLevel.WARNING);
     runTypeCheckAfterProcessing = true;
 
-    test(
+    String js =
         LINE_JOINER.join(
             "goog.scope(function () {",
             "  /** @constructor */ function F() {}",
             "  /** @return {F} */ function createFoo() { return 1; }",
-            "});"),
-        LINE_JOINER.join(
-            SCOPE_NAMESPACE,
-            "/** @return {$jscomp.scope.F} */",
-            "$jscomp.scope.createFoo = /** @return {$jscomp.scope.F} */ function() { return 1; };",
-            "/** @constructor */ $jscomp.scope.F = /** @constructor */ function() { };"),
-            null,
-            TypeValidator.TYPE_MISMATCH_WARNING);
+            "});");
+
+    test(js,
+         SCOPE_NAMESPACE +
+         "$jscomp.scope.createFoo = function() { return 1; };" +
+         "$jscomp.scope.F = function() { };",
+         null,
+         TypeValidator.TYPE_MISMATCH_WARNING);
   }
 
   // Alias Recording Tests
diff --git a/test/com/google/javascript/jscomp/SyntacticScopeCreatorTest.java b/test/com/google/javascript/jscomp/SyntacticScopeCreatorTest.java
index 84aa22d4c..9e89ac284 100644
--- a/test/com/google/javascript/jscomp/SyntacticScopeCreatorTest.java
+++ b/test/com/google/javascript/jscomp/SyntacticScopeCreatorTest.java
@@ -27,36 +27,23 @@ import junit.framework.TestCase;
  */
 public final class SyntacticScopeCreatorTest extends TestCase {
 
-  private Compiler compiler;
-  private SyntacticScopeCreator scopeCreator;
-
-  @Override
-  protected void setUp() {
-    compiler = new Compiler();
-    CompilerOptions options = new CompilerOptions();
-    compiler.initOptions(options);
-    scopeCreator = SyntacticScopeCreator.makeUntyped(compiler);
-  }
-
   /**
    * Helper to create a top-level scope from a JavaScript string
    */
-  private Scope getScope(String js) {
-    return scopeCreator.createScope(getRoot(js), null);
-  }
-
-  private Node getRoot(String js) {
+  private static Scope getScope(String js) {
+    Compiler compiler = new Compiler();
     Node root = compiler.parseTestCode(js);
     assertEquals(0, compiler.getErrorCount());
-    return root;
+    Scope scope = SyntacticScopeCreator.makeUntyped(compiler).createScope(root, null);
+    return scope;
   }
 
   public void testFunctionScope() {
     Scope scope = getScope("function foo() {}\n" +
-        "var x = function bar(a1) {};" +
-        "[function bar2() { var y; }];" +
-        "if (true) { function z() {} }");
-
+                           "var x = function bar(a1) {};" +
+                           "[function bar2() { var y; }];" +
+                           "if (true) { function z() {} }"
+                           );
     assertTrue(scope.isDeclared("foo", false));
     assertTrue(scope.isDeclared("x", false));
     assertTrue(scope.isDeclared("z", false));
@@ -69,29 +56,20 @@ public final class SyntacticScopeCreatorTest extends TestCase {
     assertFalse(scope.isDeclared("", false));
   }
 
-  public void testNestedFunctionScope() {
-    Node root = getRoot("function f(x) { function g(y) {} }");
-    Scope globalScope = scopeCreator.createScope(root, null);
-
-    Node fNode = root.getFirstChild();
-    Scope outerFScope = scopeCreator.createScope(fNode, globalScope);
-    assertTrue(outerFScope.isDeclared("x", false));
-
-    Node innerFNode = fNode.getLastChild().getFirstChild();
-    Scope innerFScope = scopeCreator.createScope(innerFNode, outerFScope);
-    assertFalse(innerFScope.isDeclared("x", false));
-    assertTrue(innerFScope.isDeclared("y", false));
-  }
-
   public void testScopeRootNode() {
-    Node root = getRoot("function foo() { var x = 10; }");
+    String js = "function foo() {\n" +
+        " var x = 10;" +
+        "}";
+    Compiler compiler = new Compiler();
+    Node root = compiler.parseTestCode(js);
+    assertEquals(0, compiler.getErrorCount());
 
-    Scope globalScope = scopeCreator.createScope(root, null);
+    Scope globalScope = SyntacticScopeCreator.makeUntyped(compiler).createScope(root, null);
     assertEquals(root, globalScope.getRootNode());
 
     Node fooNode = root.getFirstChild();
     assertEquals(Token.FUNCTION, fooNode.getType());
-    Scope fooScope = scopeCreator.createScope(fooNode, globalScope);
+    Scope fooScope = SyntacticScopeCreator.makeUntyped(compiler).createScope(fooNode, null);
     assertEquals(fooNode, fooScope.getRootNode());
     assertTrue(fooScope.isDeclared("x", false));
   }
diff --git a/test/com/google/javascript/jscomp/TypeCheckTest.java b/test/com/google/javascript/jscomp/TypeCheckTest.java
index c6e2e06b3..a53462887 100644
--- a/test/com/google/javascript/jscomp/TypeCheckTest.java
+++ b/test/com/google/javascript/jscomp/TypeCheckTest.java
@@ -13237,16 +13237,6 @@ public final class TypeCheckTest extends CompilerTypeTestCase {
         TypeCheck.NON_STRINGIFIABLE_OBJECT_KEY);
   }
 
-  public void testCheckObjectKeysBadKey9() throws Exception {
-    testTypes("/** @type {function(!Object<!Object, number>)} */ var k;",
-        TypeCheck.NON_STRINGIFIABLE_OBJECT_KEY);
-  }
-
-  public void testCheckObjectKeysBadKey10() throws Exception {
-    testTypes("/** @type {function(): !Object<!Object, number>} */ var k;",
-        TypeCheck.NON_STRINGIFIABLE_OBJECT_KEY);
-  }
-
   public void testCheckObjectKeysVariousTags1() throws Exception {
     testTypes("/** @type {!Object<!Object, number>} */ var k;",
         TypeCheck.NON_STRINGIFIABLE_OBJECT_KEY);
diff --git a/test/com/google/javascript/jscomp/VarCheckTest.java b/test/com/google/javascript/jscomp/VarCheckTest.java
index a54d3f649..511f5f8e3 100644
--- a/test/com/google/javascript/jscomp/VarCheckTest.java
+++ b/test/com/google/javascript/jscomp/VarCheckTest.java
@@ -100,21 +100,6 @@ public final class VarCheckTest extends CompilerTestCase {
     testError("{ let x = 1; } var y = x;", VarCheck.UNDEFINED_VAR_ERROR);
   }
 
-  public void testReferencedLetDefined1() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testSame("let x; x = 1;");
-  }
-
-  public void testReferencedLetDefined2() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testSame("let x; function y() {x = 1;}");
-  }
-
-  public void testReferencedConstDefined2() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testSame("const x = 1; var y = x + 1;");
-  }
-
   public void testReferencedVarDefined1() {
     testSame("var x, y; x=1;");
   }
@@ -146,34 +131,6 @@ public final class VarCheckTest extends CompilerTestCase {
         VarCheck.VAR_MULTIPLY_DECLARED_ERROR, true);
   }
 
-  public void testMultiplyDeclaredLets() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testError("let x = 1; let x = 2;", VarCheck.LET_CONST_MULTIPLY_DECLARED_ERROR);
-    testError("let x = 1; var x = 2;", VarCheck.LET_CONST_MULTIPLY_DECLARED_ERROR);
-    testError("var x = 1; let x = 2;", VarCheck.LET_CONST_MULTIPLY_DECLARED_ERROR);
-  }
-
-  public void testMultiplyDeclaredConsts() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testError("const x = 1; const x = 2;", VarCheck.LET_CONST_MULTIPLY_DECLARED_ERROR);
-    testError("const x = 1; var x = 2;", VarCheck.LET_CONST_MULTIPLY_DECLARED_ERROR);
-    testError("var x = 1; const x = 2;", VarCheck.LET_CONST_MULTIPLY_DECLARED_ERROR);
-  }
-
-  public void testMultiplyDeclareLetsInDifferentScope() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testSame("let x = 1; if (123) {let x = 2;}");
-    testSame("try {let x = 1;} catch(x){}");
-  }
-
-  public void testReferencedVarDefinedClass() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testError("var x; class x{ }", VarCheck.VAR_MULTIPLY_DECLARED_ERROR);
-    testError("let x; class x{ }", VarCheck.LET_CONST_MULTIPLY_DECLARED_ERROR);
-    testError("const x = 1; class x{ }", VarCheck.LET_CONST_MULTIPLY_DECLARED_ERROR);
-    testError("class x{ } let x;", VarCheck.LET_CONST_MULTIPLY_DECLARED_ERROR);
-  }
-
   public void testVarReferenceInExterns() {
     testSame("asdf;", "var asdf;",
         VarCheck.NAME_REFERENCE_IN_EXTERNS_ERROR);
@@ -184,13 +141,6 @@ public final class VarCheckTest extends CompilerTestCase {
         VarCheck.NAME_REFERENCE_IN_EXTERNS_ERROR);
   }
 
-  public void testNewInExterns() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    // Class is not hoisted.
-    testSame("x = new Klass();", "class Klass{}",
-        VarCheck.UNDEFINED_VAR_ERROR, true);
-  }
-
   public void testPropReferenceInExterns1() {
     testSame("asdf.foo;", "var asdf;",
         VarCheck.UNDEFINED_EXTERN_VAR_ERROR);
@@ -214,20 +164,6 @@ public final class VarCheckTest extends CompilerTestCase {
     test("asdf.foo;", "var asdf;", "var asdf;", null, null);
   }
 
-  public void testPropReferenceInExterns4() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    test("asdf.foo;", "let asdf;", null,
-        VarCheck.LET_CONST_MULTIPLY_DECLARED_ERROR,
-        VarCheck.UNDEFINED_EXTERN_VAR_ERROR);
-  }
-
-  public void testPropReferenceInExterns5() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    test("asdf.foo;", "class asdf{};", null,
-        VarCheck.VAR_MULTIPLY_DECLARED_ERROR,
-        VarCheck.UNDEFINED_EXTERN_VAR_ERROR);
-  }
-
   public void testVarInWithBlock() {
     testError("var a = {b:5}; with (a){b;}", VarCheck.UNDEFINED_VAR_ERROR);
   }
@@ -248,43 +184,16 @@ public final class VarCheckTest extends CompilerTestCase {
     testDependentModules("var x = 10;", "var y = x++;", null);
   }
 
-  public void testLegalLetReferenceBetweenModules() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testDependentModules("let x = 10;", "let y = x++;", null);
-  }
-
-  public void testLegalConstReferenceBetweenModules() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testDependentModules("const x = 10;", "const y = x + 1;", null);
-  }
-
   public void testMissingModuleDependencyDefault() {
     testIndependentModules("var x = 10;", "var y = x++;",
                            null, VarCheck.MISSING_MODULE_DEP_ERROR);
   }
 
-  public void testMissingModuleDependencyLetAndConst() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testIndependentModules("let x = 10;", "let y = x++;",
-        null, VarCheck.MISSING_MODULE_DEP_ERROR);
-    testIndependentModules("const x = 10;", "const y = x + 1;",
-        null, VarCheck.MISSING_MODULE_DEP_ERROR);
-  }
-
   public void testViolatedModuleDependencyDefault() {
     testDependentModules("var y = x++;", "var x = 10;",
                          VarCheck.VIOLATED_MODULE_DEP_ERROR);
   }
 
-  public void testViolatedModuleDependencyLetAndConst() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testDependentModules("let y = x++;", "let x = 10;",
-        VarCheck.VIOLATED_MODULE_DEP_ERROR);
-    testDependentModules("const y = x + 1;", "const x = 10;",
-        VarCheck.VIOLATED_MODULE_DEP_ERROR);
-  }
-
-
   public void testMissingModuleDependencySkipNonStrict() {
     sanityCheck = true;
     testIndependentModules("var x = 10;", "var y = x++;",
@@ -449,21 +358,11 @@ public final class VarCheckTest extends CompilerTestCase {
     testSame(js);
   }
 
-  public void testSuppressionWithInlineJsDoc() {
-    testSame("/** @suppress {duplicate} */ var /** number */ a; var a;");
-  }
-
   public void testDuplicateVar() {
     testError("/** @define {boolean} */ var DEF = false; var DEF = true;",
         VAR_MULTIPLY_DECLARED_ERROR);
   }
 
-  public void testDontAllowSuppressDupeOnLet() {
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    String js = "let a; /** @suppress {duplicate} */ let a; ";
-    testError(js, VarCheck.LET_CONST_MULTIPLY_DECLARED_ERROR);
-  }
-
   public void testFunctionScopeArguments() {
     // A var declaration doesn't mask arguments
     testSame("function f() {var arguments}");
diff --git a/test/com/google/javascript/jscomp/VariableReferenceCheckTest.java b/test/com/google/javascript/jscomp/VariableReferenceCheckTest.java
index f7a9b60b2..db927f26d 100644
--- a/test/com/google/javascript/jscomp/VariableReferenceCheckTest.java
+++ b/test/com/google/javascript/jscomp/VariableReferenceCheckTest.java
@@ -16,7 +16,7 @@
 
 package com.google.javascript.jscomp;
 
-import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
+
 
 /**
  * Test that warnings are generated in appropriate cases and appropriate
@@ -43,7 +43,7 @@ public final class VariableReferenceCheckTest extends CompilerTestCase {
   @Override
   public CompilerPass getProcessor(Compiler compiler) {
     // Treats bad reads as errors, and reports bad write warnings.
-    return new VariableReferenceCheck(compiler);
+    return new VariableReferenceCheck(compiler, CheckLevel.WARNING);
   }
 
   @Override
@@ -57,7 +57,6 @@ public final class VariableReferenceCheckTest extends CompilerTestCase {
     assertNoWarning("function foo() { bar(); } function bar() { foo(); } ");
     assertNoWarning("function f(d) { d = 3; }");
     assertNoWarning(VARIABLE_RUN);
-    assertNoWarning("if (a) { var x; }");
     assertNoWarning("function f() { " + VARIABLE_RUN + "}");
   }
 
@@ -76,14 +75,12 @@ public final class VariableReferenceCheckTest extends CompilerTestCase {
 
   public void testCorrectCatch() {
     assertNoWarning("function f() { try { var x = 2; } catch (x) {} }");
-    assertNoWarning("function f(e) { e = 3; try {} catch (e) {} }");
   }
 
   public void testRedeclare() {
     // Only test local scope since global scope is covered elsewhere
     assertRedeclare("function f() { var a = 2; var a = 3; }");
     assertRedeclare("function f(a) { var a = 2; }");
-    assertRedeclare("function f(a) { if (!a) var a = 6; }");
   }
 
   public void testEarlyReference() {
@@ -194,8 +191,6 @@ public final class VariableReferenceCheckTest extends CompilerTestCase {
    */
   private void assertRedeclare(String js) {
     testSame(js, VariableReferenceCheck.REDECLARED_VARIABLE);
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testSame(js, VariableReferenceCheck.REDECLARED_VARIABLE);
   }
 
   /**
@@ -203,8 +198,6 @@ public final class VariableReferenceCheckTest extends CompilerTestCase {
    */
   private void assertUndeclared(String js) {
     testSame(js, VariableReferenceCheck.EARLY_REFERENCE);
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testSame(js, VariableReferenceCheck.EARLY_REFERENCE);
   }
 
   /**
@@ -212,16 +205,13 @@ public final class VariableReferenceCheckTest extends CompilerTestCase {
    */
   private void assertAmbiguous(String js) {
     testSame(js, VariableReferenceCheck.AMBIGUOUS_FUNCTION_DECL);
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testSame(js); // In ES6, these are block scoped functions, so no ambiguity.
   }
 
+
   /**
    * Expects the JS to generate no errors or warnings.
    */
   private void assertNoWarning(String js) {
     testSame(js);
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testSame(js);
   }
 }
diff --git a/test/com/google/javascript/jscomp/lint/CheckEnumsTest.java b/test/com/google/javascript/jscomp/lint/CheckEnumsTest.java
index 9b18ceec4..e79946459 100644
--- a/test/com/google/javascript/jscomp/lint/CheckEnumsTest.java
+++ b/test/com/google/javascript/jscomp/lint/CheckEnumsTest.java
@@ -17,7 +17,6 @@
 package com.google.javascript.jscomp.lint;
 
 import com.google.javascript.jscomp.Compiler;
-import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
 import com.google.javascript.jscomp.CompilerPass;
 import com.google.javascript.jscomp.CompilerTestCase;
 import com.google.javascript.jscomp.DiagnosticType;
@@ -45,12 +44,6 @@ public final class CheckEnumsTest extends CompilerTestCase {
         CheckEnums.DUPLICATE_ENUM_VALUE);
     testSame("/** @enum {string} */ var Enum = {A: 'foo', B: 'foo'};",
         CheckEnums.DUPLICATE_ENUM_VALUE);
-
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testSame("/** @enum {number} */ var Enum = {A};",
-        CheckEnums.SHORTHAND_ASSIGNMENT_IN_ENUM);
-    testSame("/** @enum {string} */ var Enum = {['prop' + f()]: 'foo'};",
-        CheckEnums.COMPUTED_PROP_NAME_IN_ENUM);
   }
 
   private void testOk(String js) {
diff --git a/test/com/google/javascript/jscomp/lint/CheckNullableReturnTest.java b/test/com/google/javascript/jscomp/lint/CheckNullableReturnTest.java
index 488616e1e..6c488056f 100644
--- a/test/com/google/javascript/jscomp/lint/CheckNullableReturnTest.java
+++ b/test/com/google/javascript/jscomp/lint/CheckNullableReturnTest.java
@@ -19,7 +19,6 @@ package com.google.javascript.jscomp.lint;
 import com.google.javascript.jscomp.CheckLevel;
 import com.google.javascript.jscomp.Compiler;
 import com.google.javascript.jscomp.CompilerOptions;
-import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
 import com.google.javascript.jscomp.CompilerPass;
 import com.google.javascript.jscomp.CompilerTestCase;
 import com.google.javascript.jscomp.DiagnosticGroups;
@@ -125,65 +124,41 @@ public final class CheckNullableReturnTest extends CompilerTestCase {
   }
 
   public void testTwoBranches() {
-    testError(LINE_JOINER.join(
-        "/** @return {SomeType} */",
-        "function f() {",
-        "  if (foo) {",
-        "    return new SomeType();",
-        "  } else {",
-        "    return new SomeType();",
-        "  }",
-        "}"));
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testError(LINE_JOINER.join(
-        "var obj = {",
-        "  /** @return {SomeType} */",
-        "  f() {",
-        "    if (foo) {",
-        "      return new SomeType();",
-        "    } else {",
-        "      return new SomeType();",
-        "    }",
-        "  }",
-        "}"));
+    testError(""
+        + "/** @return {SomeType} */\n"
+        + "function f() {\n"
+        + "  if (foo) {\n"
+        + "    return new SomeType();\n"
+        + "  } else {\n"
+        + "    return new SomeType();\n"
+        + "  }\n"
+        + "}");
   }
 
   public void testTryCatch() {
-    testError(LINE_JOINER.join(
-        "/** @return {SomeType} */",
-        "function f() {",
-        "  try {",
-        "    return new SomeType();",
-        "  } catch (e) {",
-        "    return new SomeType();",
-        "  }",
-        "}"));
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testError(LINE_JOINER.join(
-        "var obj = {",
-        "  /** @return {SomeType} */",
-        "  f() {",
-        "    try {",
-        "      return new SomeType();",
-        "    } catch (e) {",
-        "      return new SomeType();",
-        "    }",
-        "  }",
-        "}"));
-
-    testBodyOk(LINE_JOINER.join(
-        "try {",
-        "  if (a) throw '';",
-        "} catch (e) {",
-        "  return null;",
-        "}",
-        "return {}"));
-
-    testBodyOk(LINE_JOINER.join(
-        "try {",
-        "  return bar();",
-        "} catch (e) {",
-        "} finally { }"));
+    testError(""
+        + "/** @return {SomeType} */\n"
+        + "function f() {\n"
+        + "  try {\n"
+        + "    return new SomeType();\n"
+        + "  } catch (e) {\n"
+        + "    return new SomeType();\n"
+        + "  }\n"
+        + "}");
+
+    testBodyOk(""
+        + "try {\n"
+        + "  if (a) throw '';\n"
+        + "} catch (e) {\n"
+        + "  return null;\n"
+        + "}\n"
+        + "return {}");
+
+    testBodyOk(""
+        + "try {\n"
+        + "  return bar();\n"
+        + "} catch (e) {\n"
+        + "} finally { }");
   }
 
   public void testNoExplicitReturn() {
@@ -209,37 +184,20 @@ public final class CheckNullableReturnTest extends CompilerTestCase {
   }
 
   public void testNoWarningOnEmptyFunction() {
-    testOk(LINE_JOINER.join(
-        "/** @return {SomeType} */",
-        "function f() {}"));
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testOk(LINE_JOINER.join(
-        "var obj = {",
-        "  /** @return {SomeType} */\n",
-        "  f() {}",
-        "}"));
+    testOk(""
+        + "/** @return {SomeType} */\n"
+        + "function f() {}");
   }
 
   public void testNoWarningOnXOrNull() {
-    testOk(LINE_JOINER.join(
-        "/**",
-        " * @param {!Array.<!Object>} arr",
-        " * @return {Object}",
-        " */",
-        "function f4(arr) {",
-        "  return arr[0] || null;",
-        "}"));
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testOk(LINE_JOINER.join(
-        "var obj = {",
-        "  /**",
-        "   * @param {!Array.<!Object>} arr",
-        "   * @return {Object}",
-        "   */",
-        "  f4(arr) {",
-        "    return arr[0] || null;",
-        "  }",
-        "}"));
+    testOk(""
+        + "/**\n"
+        + " * @param {!Array.<!Object>} arr\n"
+        + " * @return {Object}\n"
+        + " */\n"
+        + "function f4(arr) {\n"
+        + "  return arr[0] || null;\n"
+        + "}");
   }
 
   public void testNonfunctionTypeDoesntCrash() {
@@ -251,10 +209,6 @@ public final class CheckNullableReturnTest extends CompilerTestCase {
     return "/** @return {?Object} */ function foo() {" + body + "}";
   }
 
-  private static String createShorthandFunctionInObjLit(String body) {
-    return "var obj = {/** @return {?Object} */ foo() {" + body + "}}";
-  }
-
   private void testOk(String js) {
     testSame(externs, js, null);
   }
@@ -265,13 +219,9 @@ public final class CheckNullableReturnTest extends CompilerTestCase {
 
   private void testBodyOk(String body) {
     testOk(createFunction(body));
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testOk(createShorthandFunctionInObjLit(body));
   }
 
   private void testBodyError(String body) {
     testError(createFunction(body));
-    setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
-    testError(createShorthandFunctionInObjLit(body));
   }
 }
diff --git a/test/com/google/javascript/jscomp/lint/CheckRequiresAndProvidesSortedTest.java b/test/com/google/javascript/jscomp/lint/CheckRequiresAndProvidesSortedTest.java
index 10af478b7..1baee003f 100644
--- a/test/com/google/javascript/jscomp/lint/CheckRequiresAndProvidesSortedTest.java
+++ b/test/com/google/javascript/jscomp/lint/CheckRequiresAndProvidesSortedTest.java
@@ -66,13 +66,4 @@ public final class CheckRequiresAndProvidesSortedTest extends CompilerTestCase {
   public void testWarning_requiresFirst() {
     testWarning("goog.require('a');\ngoog.provide('b')", PROVIDES_AFTER_REQUIRES);
   }
-
-  public void testB3473189() {
-    testSame(
-        LINE_JOINER.join(
-            "goog.provide('abc');",
-            "if (typeof goog != 'undefined' && typeof goog.provide == 'function') {",
-            "  goog.provide('MyLib.Base');",
-            "}"));
-  }
 }
diff --git a/test/com/google/javascript/jscomp/parsing/AttachJsdocsTest.java b/test/com/google/javascript/jscomp/parsing/AttachJsdocsTest.java
index c0ea6688e..6f7a94dd6 100644
--- a/test/com/google/javascript/jscomp/parsing/AttachJsdocsTest.java
+++ b/test/com/google/javascript/jscomp/parsing/AttachJsdocsTest.java
@@ -785,7 +785,7 @@ public final class AttachJsdocsTest extends BaseJSTypeTestCase {
     Node script = ParserRunner.parse(
         new SimpleSourceFile("input", false),
         source,
-        ParserRunner.createConfig(true, mode, null),
+        ParserRunner.createConfig(true, mode, false, null),
         testErrorReporter).ast;
 
     // verifying that all warnings were seen
diff --git a/test/com/google/javascript/jscomp/parsing/JsDocInfoParserTest.java b/test/com/google/javascript/jscomp/parsing/JsDocInfoParserTest.java
index 97a2e8bb8..949b9dab2 100644
--- a/test/com/google/javascript/jscomp/parsing/JsDocInfoParserTest.java
+++ b/test/com/google/javascript/jscomp/parsing/JsDocInfoParserTest.java
@@ -57,10 +57,10 @@ public final class JsDocInfoParserTest extends BaseJSTypeTestCase {
     super.setUp();
     fileLevelJsDocBuilder = null;
     extraAnnotations = new HashSet<>(ParserRunner.createConfig(
-        true, LanguageMode.ECMASCRIPT3, null)
+        true, LanguageMode.ECMASCRIPT3, false, null)
             .annotationNames.keySet());
     extraSuppressions = new HashSet<>(ParserRunner.createConfig(
-        true, LanguageMode.ECMASCRIPT3, null).suppressionNames);
+        true, LanguageMode.ECMASCRIPT3, false, null).suppressionNames);
 
     extraSuppressions.add("x");
     extraSuppressions.add("y");
@@ -2297,7 +2297,8 @@ public final class JsDocInfoParserTest extends BaseJSTypeTestCase {
   }
 
   public void testBadModifies9() throws Exception {
-    parse("@nosideeffects @modifies {this} */", "conflicting @modifies tag");
+    parse("@nosideeffects\n"
+        + "@modifies {this} */", "conflicting @modifies tag");
   }
 
   //public void testNoParseFileOverview() throws Exception {
@@ -2337,15 +2338,11 @@ public final class JsDocInfoParserTest extends BaseJSTypeTestCase {
   public void testProtectedVisibilityNotAllowedInFileOverview() {
     parseFileOverview("@fileoverview \n * @protected */",
         "protected visibility not allowed in @fileoverview block");
-    parseFileOverview("@fileoverview @protected */",
-        "protected visibility not allowed in @fileoverview block");
   }
 
   public void testPrivateVisibilityNotAllowedInFileOverview() {
     parseFileOverview("@fileoverview \n @private */",
         "private visibility not allowed in @fileoverview block");
-    parseFileOverview("@fileoverview @private */",
-        "private visibility not allowed in @fileoverview block");
   }
 
   public void testReferences() throws Exception {
@@ -3868,11 +3865,6 @@ public final class JsDocInfoParserTest extends BaseJSTypeTestCase {
     assertTypeEquals(NUMBER_TYPE, info.getParameterType("index"));
   }
 
-  public void testJsDocAfterStatic() {
-    JSDocInfo info = parse("@static @type {number} */");
-    assertTypeEquals(NUMBER_TYPE, info.getType());
-  }
-
   public void testNonIdentifierAnnotation() {
     // Try to whitelist an annotation that is not a valid JS identifier.
     // It should not work.
@@ -4027,6 +4019,7 @@ public final class JsDocInfoParserTest extends BaseJSTypeTestCase {
     parse("@polymerBehavior \n@polymerBehavior*/", "extra @polymerBehavior tag");
   }
 
+
   public void testParseWizaction1() throws Exception {
     assertThat(parse("@wizaction*/").isWizaction()).isTrue();
   }
@@ -4237,7 +4230,8 @@ public final class JsDocInfoParserTest extends BaseJSTypeTestCase {
   private Node parseFull(String code, String... warnings) {
     TestErrorReporter testErrorReporter = new TestErrorReporter(null, warnings);
     Config config =
-        new Config(extraAnnotations, extraSuppressions, true, LanguageMode.ECMASCRIPT3);
+        new Config(extraAnnotations, extraSuppressions,
+            true, LanguageMode.ECMASCRIPT3, false);
 
     ParseResult result = ParserRunner.parse(
         new SimpleSourceFile("source", false), code, config, testErrorReporter);
@@ -4270,7 +4264,7 @@ public final class JsDocInfoParserTest extends BaseJSTypeTestCase {
     TestErrorReporter errorReporter = new TestErrorReporter(null, warnings);
 
     Config config = new Config(extraAnnotations, extraSuppressions,
-        parseDocumentation, LanguageMode.ECMASCRIPT3);
+        parseDocumentation, LanguageMode.ECMASCRIPT3, false);
     StaticSourceFile file = new SimpleSourceFile("testcode", false);
     Node associatedNode = new Node(Token.SCRIPT);
     associatedNode.setInputId(new InputId(file.getName()));
diff --git a/test/com/google/javascript/jscomp/parsing/NewParserTest.java b/test/com/google/javascript/jscomp/parsing/NewParserTest.java
index 98ea8d507..ff1878129 100644
--- a/test/com/google/javascript/jscomp/parsing/NewParserTest.java
+++ b/test/com/google/javascript/jscomp/parsing/NewParserTest.java
@@ -158,24 +158,6 @@ public final class NewParserTest extends BaseJSTypeTestCase {
         + "}");
   }
 
-  /** @bug 19100575 */
-  public void testVarSourceLocations() {
-    isIdeMode = true;
-
-    Node n = parse("var x, y = 1;");
-    Node var = n.getFirstChild();
-    assertNode(var).hasType(Token.VAR);
-
-    Node x = var.getFirstChild();
-    assertNode(x).hasType(Token.NAME);
-    assertNode(x).hasCharno("var ".length());
-
-    Node y = x.getNext();
-    assertNode(y).hasType(Token.NAME);
-    assertNode(y).hasCharno("var x, ".length());
-    assertNode(y).hasLength("y = 1".length());
-  }
-
   public void testReturn() {
     parse("function foo() { return 1; }");
     parseError("return;", UNEXPECTED_RETURN);
@@ -2698,7 +2680,7 @@ public final class NewParserTest extends BaseJSTypeTestCase {
     ParseResult result = ParserRunner.parse(
         new SimpleSourceFile("input", false),
         source,
-        ParserRunner.createConfig(isIdeMode, mode, null),
+        ParserRunner.createConfig(isIdeMode, mode, false, null),
         testErrorReporter);
     Node script = result.ast;
 
@@ -2720,7 +2702,7 @@ public final class NewParserTest extends BaseJSTypeTestCase {
     Node script = ParserRunner.parse(
         file,
         string,
-        ParserRunner.createConfig(isIdeMode, mode, null),
+        ParserRunner.createConfig(isIdeMode, mode, false, null),
         testErrorReporter).ast;
 
     // verifying that all warnings were seen
diff --git a/test/com/google/javascript/jscomp/parsing/TypeSyntaxTest.java b/test/com/google/javascript/jscomp/parsing/TypeSyntaxTest.java
index fc421309d..b234c2687 100644
--- a/test/com/google/javascript/jscomp/parsing/TypeSyntaxTest.java
+++ b/test/com/google/javascript/jscomp/parsing/TypeSyntaxTest.java
@@ -65,13 +65,6 @@ public final class TypeSyntaxTest extends TestCase {
     testErrorManager.expectErrors(errors);
   }
 
-  private void testNotEs6TypedFullError(String source, String error) {
-    expectErrors(error);
-    parse(source, LanguageMode.ECMASCRIPT6);
-    expectErrors(error);
-    parse(source, LanguageMode.ECMASCRIPT6_STRICT);
-  }
-
   private void testNotEs6Typed(String source, String... features) {
     for (int i = 0; i < features.length; i++) {
       features[i] =
@@ -564,47 +557,6 @@ public final class TypeSyntaxTest extends TestCase {
     testNotEs6Typed("var x: typeof y;", "type annotation");
   }
 
-  public void testAccessibilityModifier() {
-    parse("class Foo {\n  private constructor() {\n  }\n}");
-    parse("class Foo {\n  protected static bar: number;\n}");
-    parse("class Foo {\n  protected bar() {\n  }\n}");
-    parse("class Foo {\n  private get() {\n  }\n}");
-    parse("class Foo {\n  private set() {\n  }\n}");
-    parse("class Foo {\n  private ['foo']() {\n  }\n}");
-    parse("class Foo {\n  private [Symbol.iterator]() {\n  }\n}");
-    parse("class Foo {\n  private ['foo'];\n}");
-
-    // TODO(moz): Enable this
-    //parse("class Foo {\n  constructor(public bar) {}}");
-
-    expectErrors("Parse error. primary expression expected");
-    parse("public var x;");
-    expectErrors("Parse error. primary expression expected");
-    parse("public function foo() {}");
-    expectErrors("Parse error. Semi-colon expected");
-    parse("class Foo { static private constructor() {}}");
-
-
-    testNotEs6TypedFullError(
-        "class Foo { private constructor() {} }",
-        "Parse error. Accessibility modifier is only supported in ES6 typed mode");
-    testNotEs6TypedFullError(
-        "class Foo { protected bar; }",
-        "Parse error. Accessibility modifier is only supported in ES6 typed mode");
-    testNotEs6TypedFullError(
-        "class Foo { protected bar() {} }",
-        "Parse error. Accessibility modifier is only supported in ES6 typed mode");
-    testNotEs6TypedFullError(
-        "class Foo { private get() {} }",
-        "Parse error. Accessibility modifier is only supported in ES6 typed mode");
-    testNotEs6TypedFullError(
-        "class Foo { private set() {} }",
-        "Parse error. Accessibility modifier is only supported in ES6 typed mode");
-    testNotEs6TypedFullError(
-        "class Foo { private [Symbol.iterator]() {} }",
-        "Parse error. Accessibility modifier is only supported in ES6 typed mode");
-  }
-
   public void testOptionalProperty() {
     parse("interface I {\n  foo?: number;\n}");
     parse("interface I {\n  foo?(): number;\n}");