Redo "Steps towards making dart2js JS AST templates an indepentent library."

Adds fix for dart2js_incremental

TBR=floitsch@google.com

Review URL: https://codereview.chromium.org//917033002

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@43712 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/compiler/lib/src/io/source_information.dart b/pkg/compiler/lib/src/io/source_information.dart
index 5294261..c0e6e0a8 100644
--- a/pkg/compiler/lib/src/io/source_information.dart
+++ b/pkg/compiler/lib/src/io/source_information.dart
@@ -8,12 +8,13 @@
 import '../elements/elements.dart' show AstElement;
 import '../scanner/scannerlib.dart' show Token;
 import '../tree/tree.dart' show Node;
+import '../js/js.dart' show JavaScriptNodeSourceInformation;
 import 'code_output.dart';
 import 'source_file.dart';
 
 /// Interface for passing source information, for instance for use in source
 /// maps, through the backend.
-abstract class SourceInformation {
+abstract class SourceInformation extends JavaScriptNodeSourceInformation {
   SourceSpan get sourceSpan;
   void beginMapping(CodeOutput output);
   void endMapping(CodeOutput output);
diff --git a/pkg/compiler/lib/src/js/builder.dart b/pkg/compiler/lib/src/js/builder.dart
index 0fa01cc..72b4507 100644
--- a/pkg/compiler/lib/src/js/builder.dart
+++ b/pkg/compiler/lib/src/js/builder.dart
@@ -5,7 +5,7 @@
 // Utilities for building JS ASTs at runtime.  Contains a builder class
 // and a parser that parses part of the language.
 
-part of js;
+part of js_ast;
 
 
 /**
diff --git a/pkg/compiler/lib/src/js/characters.dart b/pkg/compiler/lib/src/js/characters.dart
new file mode 100644
index 0000000..ae6740f
--- /dev/null
+++ b/pkg/compiler/lib/src/js/characters.dart
@@ -0,0 +1,117 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library js_character_codes;
+
+const int $EOF = 0;
+const int $STX = 2;
+const int $BS  = 8;
+const int $TAB = 9;
+const int $LF = 10;
+const int $VTAB = 11;
+const int $FF = 12;
+const int $CR = 13;
+const int $SPACE = 32;
+const int $BANG = 33;
+const int $DQ = 34;
+const int $HASH = 35;
+const int $$ = 36;
+const int $PERCENT = 37;
+const int $AMPERSAND = 38;
+const int $SQ = 39;
+const int $OPEN_PAREN = 40;
+const int $CLOSE_PAREN = 41;
+const int $STAR = 42;
+const int $PLUS = 43;
+const int $COMMA = 44;
+const int $MINUS = 45;
+const int $PERIOD = 46;
+const int $SLASH = 47;
+const int $0 = 48;
+const int $1 = 49;
+const int $2 = 50;
+const int $3 = 51;
+const int $4 = 52;
+const int $5 = 53;
+const int $6 = 54;
+const int $7 = 55;
+const int $8 = 56;
+const int $9 = 57;
+const int $COLON = 58;
+const int $SEMICOLON = 59;
+const int $LT = 60;
+const int $EQ = 61;
+const int $GT = 62;
+const int $QUESTION = 63;
+const int $AT = 64;
+const int $A = 65;
+const int $B = 66;
+const int $C = 67;
+const int $D = 68;
+const int $E = 69;
+const int $F = 70;
+const int $G = 71;
+const int $H = 72;
+const int $I = 73;
+const int $J = 74;
+const int $K = 75;
+const int $L = 76;
+const int $M = 77;
+const int $N = 78;
+const int $O = 79;
+const int $P = 80;
+const int $Q = 81;
+const int $R = 82;
+const int $S = 83;
+const int $T = 84;
+const int $U = 85;
+const int $V = 86;
+const int $W = 87;
+const int $X = 88;
+const int $Y = 89;
+const int $Z = 90;
+const int $OPEN_SQUARE_BRACKET = 91;
+const int $BACKSLASH = 92;
+const int $CLOSE_SQUARE_BRACKET = 93;
+const int $CARET = 94;
+const int $_ = 95;
+const int $BACKPING = 96;
+const int $a = 97;
+const int $b = 98;
+const int $c = 99;
+const int $d = 100;
+const int $e = 101;
+const int $f = 102;
+const int $g = 103;
+const int $h = 104;
+const int $i = 105;
+const int $j = 106;
+const int $k = 107;
+const int $l = 108;
+const int $m = 109;
+const int $n = 110;
+const int $o = 111;
+const int $p = 112;
+const int $q = 113;
+const int $r = 114;
+const int $s = 115;
+const int $t = 116;
+const int $u = 117;
+const int $v = 118;
+const int $w = 119;
+const int $x = 120;
+const int $y = 121;
+const int $z = 122;
+const int $OPEN_CURLY_BRACKET = 123;
+const int $BAR = 124;
+const int $CLOSE_CURLY_BRACKET = 125;
+const int $TILDE = 126;
+const int $DEL = 127;
+const int $NBSP = 160;
+const int $LS = 0x2028;
+const int $PS = 0x2029;
+
+const int $FIRST_SURROGATE = 0xd800;
+const int $LAST_SURROGATE = 0xdfff;
+const int $LAST_CODE_POINT = 0x10ffff;
diff --git a/pkg/compiler/lib/src/js/js.dart b/pkg/compiler/lib/src/js/js.dart
index fac460d..a5bbec4 100644
--- a/pkg/compiler/lib/src/js/js.dart
+++ b/pkg/compiler/lib/src/js/js.dart
@@ -1,23 +1,64 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
 library js;
 
-import 'precedence.dart';
-import '../util/characters.dart' as charCodes;
-import '../util/util.dart';
+// TODO(sra): This will become a package import.
+import 'js_ast.dart';
+export 'js_ast.dart';
+
 import '../io/code_output.dart' show CodeBuffer;
 import '../io/source_information.dart' show SourceInformation;
 import '../js_emitter/js_emitter.dart' show USE_NEW_EMITTER;
-
-// TODO(floitsch): remove this dependency (currently necessary for the
-// CodeBuffer).
 import '../dart2jslib.dart' as leg;
+import '../util/util.dart' show NO_LOCATION_SPANNABLE;
+import '../dump_info.dart' show DumpInfoTask;
 
-import '../dump_info.dart';
 
-part 'nodes.dart';
-part 'builder.dart';
-part 'printer.dart';
-part 'template.dart';
+CodeBuffer prettyPrint(Node node, leg.Compiler compiler,
+                       {DumpInfoTask monitor,
+                        bool allowVariableMinification: true}) {
+  JavaScriptPrintingOptions options = new JavaScriptPrintingOptions(
+      shouldCompressOutput: compiler.enableMinification,
+      minifyLocalVariables: allowVariableMinification,
+      preferSemicolonToNewlineInMinifiedOutput: USE_NEW_EMITTER);
+  Dart2JSJavaScriptPrintingContext context =
+      new Dart2JSJavaScriptPrintingContext(compiler, monitor);
+  Printer printer = new Printer(options, context);
+  printer.visit(node);
+  return context.outBuffer;
+}
+
+class Dart2JSJavaScriptPrintingContext implements JavaScriptPrintingContext {
+  final leg.Compiler compiler;
+  final DumpInfoTask monitor;
+  final CodeBuffer outBuffer = new CodeBuffer();
+
+  Dart2JSJavaScriptPrintingContext(leg.Compiler this.compiler,
+      DumpInfoTask this.monitor);
+
+  void error(String message) {
+    compiler.internalError(NO_LOCATION_SPANNABLE, message);
+  }
+
+  void emit(String string) {
+    outBuffer.add(string);
+  }
+
+  void enterNode(Node node) {
+    SourceInformation sourceInformation = node.sourceInformation;
+    if (sourceInformation != null) {
+      sourceInformation.beginMapping(outBuffer);
+    }
+    if (monitor != null) monitor.enteringAst(node, outBuffer.length);
+  }
+
+  void exitNode(Node node) {
+    if (monitor != null) monitor.exitingAst(node, outBuffer.length);
+    SourceInformation sourceInformation = node.sourceInformation;
+    if (sourceInformation != null) {
+      sourceInformation.endMapping(outBuffer);
+    }
+  }
+}
diff --git a/pkg/compiler/lib/src/js/js_ast.dart b/pkg/compiler/lib/src/js/js_ast.dart
new file mode 100644
index 0000000..ee8289e
--- /dev/null
+++ b/pkg/compiler/lib/src/js/js_ast.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library js_ast;
+
+import 'precedence.dart';
+import 'characters.dart' as charCodes;
+
+part 'nodes.dart';
+part 'builder.dart';
+part 'printer.dart';
+part 'template.dart';
diff --git a/pkg/compiler/lib/src/js/nodes.dart b/pkg/compiler/lib/src/js/nodes.dart
index 60b3a85..92446fa 100644
--- a/pkg/compiler/lib/src/js/nodes.dart
+++ b/pkg/compiler/lib/src/js/nodes.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of js;
+part of js_ast;
 
 abstract class NodeVisitor<T> {
   T visitProgram(Program node);
@@ -29,7 +29,6 @@
   T visitLiteralStatement(LiteralStatement node);
   T visitDartYield(DartYield node);
 
-  T visitBlob(Blob node);
   T visitLiteralExpression(LiteralExpression node);
   T visitVariableDeclarationList(VariableDeclarationList node);
   T visitAssignment(Assignment node);
@@ -109,7 +108,6 @@
   T visitDefault(Default node) => visitNode(node);
 
   T visitExpression(Expression node) => visitNode(node);
-  T visitBlob(Blob node) => visitExpression(node);
   T visitVariableReference(VariableReference node) => visitExpression(node);
 
   T visitLiteralExpression(LiteralExpression node) => visitExpression(node);
@@ -173,10 +171,14 @@
   T visitDartYield(DartYield node) => visitStatement(node);
 }
 
-abstract class Node {
-  SourceInformation get sourceInformation => _sourceInformation;
+/// This tag interface has no behaviour but must be implemented by any class
+/// that is to be stored on a [Node] as source information.
+abstract class JavaScriptNodeSourceInformation {}
 
-  SourceInformation _sourceInformation;
+abstract class Node {
+  JavaScriptNodeSourceInformation get sourceInformation => _sourceInformation;
+
+  JavaScriptNodeSourceInformation _sourceInformation;
 
   accept(NodeVisitor visitor);
   void visitChildren(NodeVisitor visitor);
@@ -187,7 +189,8 @@
 
   // Returns a node equivalent to [this], but with new source position and end
   // source position.
-  Node withSourceInformation(SourceInformation sourceInformation) {
+  Node withSourceInformation(
+      JavaScriptNodeSourceInformation sourceInformation) {
     if (sourceInformation == _sourceInformation) {
       return this;
     }
@@ -522,8 +525,8 @@
   LiteralStatement _clone() => new LiteralStatement(code);
 }
 
-// Not a real javascript node, but represents the yield statement from a dart
-// program translated to javascript.
+// Not a real JavaScript node, but represents the yield statement from a dart
+// program translated to JavaScript.
 class DartYield extends Statement {
   final Expression expression;
 
@@ -546,25 +549,6 @@
   Statement toStatement() => new ExpressionStatement(this);
 }
 
-/// Wrap a CodeBuffer as an expression.
-class Blob extends Expression {
-  // TODO(ahe): This class is an aid to convert everything to ASTs, remove when
-  // not needed anymore.
-
-  final CodeBuffer buffer;
-
-  Blob(this.buffer);
-
-  accept(NodeVisitor visitor) => visitor.visitBlob(this);
-
-  void visitChildren(NodeVisitor visitor) {}
-
-  Blob _clone() => new Blob(buffer);
-
-  int get precedenceLevel => PRIMARY;
-
-}
-
 class LiteralExpression extends Expression {
   final String template;
   final List<Expression> inputs;
@@ -947,9 +931,12 @@
   /**
    * Constructs a LiteralString from a string value.
    *
-   * The constructor does not add the required quotes.  If [value] is
-   * not surrounded by quotes, the resulting object is invalid as a JS
-   * value.
+   * The constructor does not add the required quotes.  If [value] is not
+   * surrounded by quotes and property escaped, the resulting object is invalid
+   * as a JS value.
+   *
+   * TODO(sra): Introduce variants for known valid strings that don't allocate a
+   * new string just to add quotes.
    */
   LiteralString(this.value);
 
@@ -958,7 +945,7 @@
 }
 
 class LiteralNumber extends Literal {
-  final String value;
+  final String value;  // Must be a valid JavaScript number literal.
 
   LiteralNumber(this.value);
 
@@ -1127,7 +1114,7 @@
 /**
  * An asynchronous await.
  *
- * Not part of javascript. We desugar this expression before outputting.
+ * Not part of JavaScript. We desugar this expression before outputting.
  * Should only occur in a [Fun] with `asyncModifier` async or asyncStar.
  */
 class Await extends Expression {
diff --git a/pkg/compiler/lib/src/js/printer.dart b/pkg/compiler/lib/src/js/printer.dart
index d359a05..6ee3f3e 100644
--- a/pkg/compiler/lib/src/js/printer.dart
+++ b/pkg/compiler/lib/src/js/printer.dart
@@ -2,32 +2,77 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of js;
+part of js_ast;
 
-class Printer extends Indentation implements NodeVisitor {
+
+class JavaScriptPrintingOptions {
   final bool shouldCompressOutput;
-  leg.DiagnosticListener diagnosticListener;
-  CodeBuffer outBuffer;
-  bool inForInit = false;
-  bool atStatementBegin = false;
+  final bool minifyLocalVariables;
+  final bool preferSemicolonToNewlineInMinifiedOutput;
+
+  JavaScriptPrintingOptions(
+      {this.shouldCompressOutput: false,
+       this.minifyLocalVariables: false,
+       this.preferSemicolonToNewlineInMinifiedOutput: false});
+}
+
+
+/// An environment in which JavaScript printing is done.  Provides emitting of
+/// text and pre- and post-visit callbacks.
+abstract class JavaScriptPrintingContext {
+  /// Signals an error.  This should happen only for serious internal errors.
+  void error(String message) { throw message; }
+
+  /// Adds [string] to the output.
+  void emit(String string);
+
+  /// Callback immediately before printing [node].  Whitespace may be printed
+  /// after this callback before the first non-whitespace character for [node].
+  void enterNode(Node node) {}
+  /// Callback after printing the last character representing [node].
+  void exitNode(Node node) {}
+}
+
+/// A simple implementation of [JavaScriptPrintingContext] suitable for tests.
+class SimpleJavaScriptPrintingContext extends JavaScriptPrintingContext {
+  final StringBuffer buffer = new StringBuffer();
+
+  void emit(String string) {
+    buffer.write(string);
+  }
+
+  String getText() => buffer.toString();
+}
+
+
+class Printer implements NodeVisitor {
+  final JavaScriptPrintingOptions options;
+  final JavaScriptPrintingContext context;
+  final bool shouldCompressOutput;
   final DanglingElseVisitor danglingElseVisitor;
   final LocalNamer localNamer;
+
+  bool inForInit = false;
+  bool atStatementBegin = false;
   bool pendingSemicolon = false;
   bool pendingSpace = false;
-  DumpInfoTask monitor = null;
+
+  // The current indentation level.
+  int _indentLevel = 0;
+  // A cache of all indentation strings used so far.
+  List<String> _indentList = <String>[""];
 
   static final identifierCharacterRegExp = new RegExp(r'^[a-zA-Z_0-9$]');
   static final expressionContinuationRegExp = new RegExp(r'^[-+([]');
 
-  Printer(leg.DiagnosticListener diagnosticListener, DumpInfoTask monitor,
-          { bool enableMinification: false, allowVariableMinification: true })
-      : shouldCompressOutput = enableMinification,
-        monitor = monitor,
-        diagnosticListener = diagnosticListener,
-        outBuffer = new CodeBuffer(),
-        danglingElseVisitor = new DanglingElseVisitor(diagnosticListener),
-        localNamer = determineRenamer(enableMinification,
-                                      allowVariableMinification);
+  Printer(JavaScriptPrintingOptions options,
+          JavaScriptPrintingContext context)
+      : options = options,
+        context = context,
+        shouldCompressOutput = options.shouldCompressOutput,
+        danglingElseVisitor = new DanglingElseVisitor(context),
+        localNamer = determineRenamer(options.shouldCompressOutput,
+                                      options.minifyLocalVariables);
 
   static LocalNamer determineRenamer(bool shouldCompressOutput,
                                      bool allowVariableMinification) {
@@ -35,6 +80,25 @@
         ? new MinifyRenamer() : new IdentityNamer();
   }
 
+
+  // The current indentation string.
+  String get indentation {
+    // Lazily add new indentation strings as required.
+    while (_indentList.length <= _indentLevel) {
+      _indentList.add(_indentList.last + "  ");
+    }
+    return _indentList[_indentLevel];
+  }
+
+  void indentMore() {
+    _indentLevel++;
+  }
+
+  void indentLess() {
+    _indentLevel--;
+  }
+
+
   /// Always emit a newline, even under `enableMinification`.
   void forceLine() {
     out("\n");
@@ -58,7 +122,7 @@
     if (str != "") {
       if (pendingSemicolon) {
         if (!shouldCompressOutput) {
-          outBuffer.add(";");
+          context.emit(";");
         } else if (str != "}") {
           // We want to output newline instead of semicolon because it makes
           // the raw stack traces much easier to read and it also makes line-
@@ -71,20 +135,21 @@
           // If we're using the new emitter where most pretty printed code
           // is escaped in strings, it is a lot easier to deal with semicolons
           // than newlines because the former doesn't need escaping.
-          if (USE_NEW_EMITTER || expressionContinuationRegExp.hasMatch(str)) {
-            outBuffer.add(";");
+          if (options.preferSemicolonToNewlineInMinifiedOutput ||
+              expressionContinuationRegExp.hasMatch(str)) {
+            context.emit(";");
           } else {
-            outBuffer.add("\n");
+            context.emit("\n");
           }
         }
       }
       if (pendingSpace &&
           (!shouldCompressOutput || identifierCharacterRegExp.hasMatch(str))) {
-        outBuffer.add(" ");
+        context.emit(" ");
       }
       pendingSpace = false;
       pendingSemicolon = false;
-      outBuffer.add(str);
+      context.emit(str);
       lastAddedString = str;
     }
   }
@@ -111,26 +176,10 @@
     }
   }
 
-  void beginSourceRange(Node node) {
-    if (node.sourceInformation != null) {
-      node.sourceInformation.beginMapping(outBuffer);
-    }
-  }
-
-  void endSourceRange(Node node) {
-    if (node.sourceInformation != null) {
-      node.sourceInformation.endMapping(outBuffer);
-    }
-  }
-
   visit(Node node) {
-    beginSourceRange(node);
-    if (monitor != null) monitor.enteringAst(node, outBuffer.length);
-
+    context.enterNode(node);
     node.accept(this);
-
-    if (monitor != null) monitor.exitingAst(node, outBuffer.length);
-    endSourceRange(node);
+    context.exitNode(node);
   }
 
   visitCommaSeparated(List<Node> nodes, int hasRequiredType,
@@ -155,10 +204,6 @@
     visitAll(program.body);
   }
 
-  visitBlob(Blob node) {
-    outBuffer.addBuffer(node.buffer);
-  }
-
   bool blockBody(Node body, {bool needsSeparation, bool needsNewline}) {
     if (body is Block) {
       spaceOut();
@@ -172,16 +217,18 @@
     } else {
       lineOut();
     }
-    indentBlock(() => visit(body));
+    indentMore();
+    visit(body);
+    indentLess();
     return false;
   }
 
   void blockOutWithoutBraces(Node node) {
     if (node is Block) {
-      beginSourceRange(node);
+      context.enterNode(node);
       Block block = node;
       block.statements.forEach(blockOutWithoutBraces);
-      endSourceRange(node);
+      context.exitNode(node);
     } else {
       visit(node);
     }
@@ -189,13 +236,15 @@
 
   void blockOut(Block node, bool shouldIndent, bool needsNewline) {
     if (shouldIndent) indent();
-    beginSourceRange(node);
+    context.enterNode(node);
     out("{");
     lineOut();
-    indentBlock(() => node.statements.forEach(blockOutWithoutBraces));
+    indentMore();
+    node.statements.forEach(blockOutWithoutBraces);
+    indentLess();
     indent();
     out("}");
-    endSourceRange(node);
+    context.exitNode(node);
     if (needsNewline) lineOut();
   }
 
@@ -407,7 +456,9 @@
     out(")");
     spaceOut();
     outLn("{");
-    indentBlock(() => visitAll(node.cases));
+    indentMore();
+    visitAll(node.cases);
+    indentLess();
     outIndentLn("}");
   }
 
@@ -418,14 +469,18 @@
                           newInForInit: false, newAtStatementBegin: false);
     outLn(":");
     if (!node.body.statements.isEmpty) {
-      indentBlock(() => blockOutWithoutBraces(node.body));
+      indentMore();
+      blockOutWithoutBraces(node.body);
+      indentLess();
     }
   }
 
   visitDefault(Default node) {
     outIndentLn("default:");
     if (!node.body.statements.isEmpty) {
-      indentBlock(() => blockOutWithoutBraces(node.body));
+      indentMore();
+      blockOutWithoutBraces(node.body);
+      indentLess();
     }
   }
 
@@ -642,8 +697,7 @@
         rightPrecedenceRequirement = UNARY;
         break;
       default:
-        diagnosticListener
-            .internalError(NO_LOCATION_SPANNABLE, "Forgot operator: $op");
+        context.error("Forgot operator: $op");
     }
 
     visitNestedExpression(left, leftPrecedenceRequirement,
@@ -880,8 +934,7 @@
     List<String> parts = template.split('#');
     int inputsLength = inputs == null ? 0 : inputs.length;
     if (parts.length != inputsLength + 1) {
-      diagnosticListener.internalError(NO_LOCATION_SPANNABLE,
-          'Wrong number of arguments for JS: $template');
+      context.error('Wrong number of arguments for JS: $template');
     }
     // Code that uses JS must take care of operator precedences, and
     // put parenthesis if needed.
@@ -1008,15 +1061,14 @@
  * as then-statement in an [If] that has an else branch.
  */
 class DanglingElseVisitor extends BaseVisitor<bool> {
-  leg.DiagnosticListener diagnosticListener;
+  JavaScriptPrintingContext context;
 
-  DanglingElseVisitor(this.diagnosticListener);
+  DanglingElseVisitor(this.context);
 
   bool visitProgram(Program node) => false;
 
   bool visitNode(Statement node) {
-    diagnosticListener
-        .internalError(NO_LOCATION_SPANNABLE, "Forgot node: $node");
+    context.error("Forgot node: $node");
     return null;
   }
 
@@ -1055,18 +1107,6 @@
 }
 
 
-CodeBuffer prettyPrint(Node node, leg.Compiler compiler,
-                       {DumpInfoTask monitor,
-                        bool allowVariableMinification: true}) {
-  Printer printer =
-      new Printer(compiler, monitor,
-                  enableMinification: compiler.enableMinification,
-                  allowVariableMinification: allowVariableMinification);
-  printer.visit(node);
-  return printer.outBuffer;
-}
-
-
 abstract class LocalNamer {
   String getName(String oldName);
   String declareVariable(String oldName);
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index 3f5bfaa..656b1af 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -966,11 +966,6 @@
   }
 
   @override
-  js.Expression visitBlob(js.Blob node) {
-    return node;
-  }
-
-  @override
   void visitBlock(js.Block node) {
     for (js.Statement statement in node.statements) {
       visitStatement(statement);
@@ -1822,11 +1817,6 @@
   }
 
   @override
-  bool visitBlob(js.Blob node) {
-    return false;
-  }
-
-  @override
   bool visitBlock(js.Block node) {
     bool containsAwait = false;
     for (js.Statement statement in node.statements) {
diff --git a/pkg/compiler/lib/src/js/template.dart b/pkg/compiler/lib/src/js/template.dart
index f08fe52..7740431 100644
--- a/pkg/compiler/lib/src/js/template.dart
+++ b/pkg/compiler/lib/src/js/template.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of js;
+part of js_ast;
 
 class TemplateManager {
   Map<String, Template> expressionTemplates = new Map<String, Template>();
@@ -499,8 +499,6 @@
 
   Instantiator visitLiteralStatement(LiteralStatement node) =>
       TODO('visitLiteralStatement');
-  Instantiator visitBlob(Blob node) =>
-      TODO('visitBlob');
   Instantiator visitLiteralExpression(LiteralExpression node) =>
       TODO('visitLiteralExpression');
 
@@ -709,12 +707,12 @@
 }
 
 /**
- * InterpolatedNodeAnalysis extract [InterpolatedNode]s from AST.
+ * InterpolatedNodeAnalysis determines which AST trees contain
+ * [InterpolatedNode]s, and the names of the named interpolated nodes.
  */
 class InterpolatedNodeAnalysis extends BaseVisitor {
-  final Setlet<Node> containsInterpolatedNode = new Setlet<Node>();
-  final List<InterpolatedNode> interpolatedNodes = <InterpolatedNode>[];
-  final Setlet<String> holeNames = new Setlet<String>();
+  final Set<Node> containsInterpolatedNode = new Set<Node>();
+  final Set<String> holeNames = new Set<String>();
   int count = 0;
 
   InterpolatedNodeAnalysis();
@@ -734,7 +732,6 @@
   }
 
   visitInterpolatedNode(InterpolatedNode node) {
-    interpolatedNodes.add(node);
     containsInterpolatedNode.add(node);
     if (node.isNamed) holeNames.add(node.nameOrPosition);
     ++count;
diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
index 8b1bcec..a575e1c 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
@@ -868,8 +868,8 @@
         cachedEmittedConstants.add(constantValue);
       }
       jsAst.Expression init = buildConstantInitializer(constantValue);
-      constantOutput.addBuffer(jsAst.prettyPrint(init, compiler,
-                                         monitor: compiler.dumpInfoTask));
+      constantOutput.addBuffer(
+          jsAst.prettyPrint(init, compiler, monitor: compiler.dumpInfoTask));
       constantOutput.add('$N');
     }
     if (compiler.hasIncrementalSupport && isMainFragment) {
diff --git a/pkg/compiler/lib/src/use_unused_api.dart b/pkg/compiler/lib/src/use_unused_api.dart
index 909b000..77f0bc9 100644
--- a/pkg/compiler/lib/src/use_unused_api.dart
+++ b/pkg/compiler/lib/src/use_unused_api.dart
@@ -51,10 +51,10 @@
   useSetlet(null);
   useImmutableEmptySet(null);
   useElementVisitor(new ElementVisitor());
-  useJs(new js.Program(null));
-  useJs(new js.Blob(null));
-  useJs(new js.NamedFunction(null, null));
-  useJs(new js.ArrayHole());
+  useJsNode(new js.Program(null));
+  useJsNode(new js.NamedFunction(null, null));
+  useJsNode(new js.ArrayHole());
+  useJsOther(new js.SimpleJavaScriptPrintingContext());
   useJsBackend(null);
   useConcreteTypesInferrer(null);
   useColor();
@@ -170,10 +170,14 @@
     ..visitWarnOnUseElement(null);
 }
 
-useJs(js.Node node) {
+useJsNode(js.Node node) {
   node.asVariableUse();
 }
 
+useJsOther(js.SimpleJavaScriptPrintingContext context) {
+  context.getText();
+}
+
 useJsBackend(js_backend.JavaScriptBackend backend) {
   backend.assembleCode(null);
   backend.annotations.noInlining(null);
diff --git a/pkg/dart2js_incremental/lib/library_updater.dart b/pkg/dart2js_incremental/lib/library_updater.dart
index 217abdb..bc269e2 100644
--- a/pkg/dart2js_incremental/lib/library_updater.dart
+++ b/pkg/dart2js_incremental/lib/library_updater.dart
@@ -995,9 +995,13 @@
   }
 
   String prettyPrintJs(jsAst.Node node) {
-    jsAst.Printer printer = new jsAst.Printer(compiler, null);
+    jsAst.JavaScriptPrintingOptions options =
+        new jsAst.JavaScriptPrintingOptions();
+    jsAst.JavaScriptPrintingContext context =
+        new jsAst.Dart2JSJavaScriptPrintingContext(compiler, null);
+    jsAst.Printer printer = new jsAst.Printer(options, context);
     printer.blockOutWithoutBraces(node);
-    return printer.outBuffer.getText();
+    return context.outBuffer.getText();
   }
 
   String callNameFor(FunctionElement element) {
diff --git a/tests/compiler/dart2js/async_await_js_transform_test.dart b/tests/compiler/dart2js/async_await_js_transform_test.dart
index bbcec9b..1006186 100644
--- a/tests/compiler/dart2js/async_await_js_transform_test.dart
+++ b/tests/compiler/dart2js/async_await_js_transform_test.dart
@@ -18,9 +18,12 @@
       endOfIteration: new VariableUse("endOfIteration"),
       newIterable: new VariableUse("Iterator"),
       safeVariableName: (String name) => "__$name").rewrite(fun);
-  Printer printer = new Printer(new PrintDiagnosticListener(), null);
+ 
+  JavaScriptPrintingOptions options = new JavaScriptPrintingOptions();
+  JavaScriptPrintingContext context = new SimpleJavaScriptPrintingContext();
+  Printer printer = new Printer(options, context);
   printer.visit(rewritten);
-  Expect.stringEquals(expected, printer.outBuffer.getText());
+  Expect.stringEquals(expected, context.getText());
 }
 
 main() {
@@ -943,4 +946,4 @@
   }
   return thenHelper(null, __helper, __completer, null);
 }""");
-}
\ No newline at end of file
+}