| Index: pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
 | 
| diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
 | 
| index 77806c00c334282149e35f446964ba6b83a99a65..c9886775cb8ac9f8777a31b4380c3246b5df65fc 100644
 | 
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
 | 
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
 | 
| @@ -20,7 +20,7 @@ import 'cps_ir_builder_task.dart' show DartCapturedVariables,
 | 
|      GlobalProgramInformation;
 | 
|  
 | 
|  import '../common.dart' as types show TypeMask;
 | 
| -import '../js/js.dart' as js show Template;
 | 
| +import '../js/js.dart' as js show Template, js, LiteralStatement;
 | 
|  import '../native/native.dart' show NativeBehavior;
 | 
|  
 | 
|  /// A mapping from variable elements to their compile-time values.
 | 
| @@ -2025,6 +2025,80 @@ class IrBuilder {
 | 
|      }
 | 
|    }
 | 
|  
 | 
| +  /// Build a call to the closure conversion helper for the [Function] typed
 | 
| +  /// value in [value].
 | 
| +  ir.Primitive _convertDartClosure(ir.Primitive value, FunctionType type) {
 | 
| +    ir.Constant arity = buildIntegerConstant(type.computeArity());
 | 
| +    return buildStaticFunctionInvocation(
 | 
| +        program.closureConverter,
 | 
| +        CallStructure.TWO_ARGS,
 | 
| +        <ir.Primitive>[value, arity]);
 | 
| +  }
 | 
| +
 | 
| +  /// Generate the body for a native function [function] that is annotated with
 | 
| +  /// an implementation in JavaScript (provided as string in [javaScriptCode]).
 | 
| +  void buildNativeFunctionBody(FunctionElement function,
 | 
| +                               String javaScriptCode) {
 | 
| +    NativeBehavior behavior = new NativeBehavior();
 | 
| +    behavior.sideEffects.setAllSideEffects();
 | 
| +    // Generate a [ForeignCode] statement from the given native code.
 | 
| +    buildForeignCode(
 | 
| +        js.js.statementTemplateYielding(
 | 
| +            new js.LiteralStatement(javaScriptCode)),
 | 
| +        <ir.Primitive>[],
 | 
| +        behavior);
 | 
| +  }
 | 
| +
 | 
| +  /// Generate the body for a native function that redirects to a native
 | 
| +  /// JavaScript function, getter, or setter.
 | 
| +  ///
 | 
| +  /// Generates a call to the real target, which is given by [functions]'s
 | 
| +  /// `fixedBackendName`, passing all parameters as arguments.  The target can
 | 
| +  /// be the JavaScript implementation of a function, getter, or setter.
 | 
| +  void buildRedirectingNativeFunctionBody(FunctionElement function,
 | 
| +                                          SourceInformation source) {
 | 
| +    String name = function.fixedBackendName;
 | 
| +    List<ir.Primitive> arguments = <ir.Primitive>[];
 | 
| +    NativeBehavior behavior = new NativeBehavior();
 | 
| +    behavior.sideEffects.setAllSideEffects();
 | 
| +    program.addNativeMethod(function);
 | 
| +    // Construct the access of the target element.
 | 
| +    String code = function.isInstanceMember ? '#.$name' : name;
 | 
| +    if (function.isInstanceMember) {
 | 
| +      arguments.add(state.thisParameter);
 | 
| +    }
 | 
| +    // Collect all parameters of the function and templates for them to be
 | 
| +    // inserted into the JavaScript code.
 | 
| +    List<String> argumentTemplates = <String>[];
 | 
| +    function.functionSignature.forEachParameter((ParameterElement parameter) {
 | 
| +      ir.Primitive input = environment.lookup(parameter);
 | 
| +      DartType type = program.unaliasType(parameter.type);
 | 
| +      if (type is FunctionType) {
 | 
| +        // The parameter type is a function type either directly or through
 | 
| +        // typedef(s).
 | 
| +        input = _convertDartClosure(input, type);
 | 
| +      }
 | 
| +      arguments.add(input);
 | 
| +      argumentTemplates.add('#');
 | 
| +    });
 | 
| +    // Construct the application of parameters for functions and setters.
 | 
| +    if (function.kind == ElementKind.FUNCTION) {
 | 
| +      code = "$code(${argumentTemplates.join(', ')})";
 | 
| +    } else if (function.kind == ElementKind.SETTER) {
 | 
| +      code = "$code = ${argumentTemplates.single}";
 | 
| +    } else {
 | 
| +      assert(argumentTemplates.isEmpty);
 | 
| +      assert(function.kind == ElementKind.GETTER);
 | 
| +    }
 | 
| +    // Generate the [ForeignCode] expression and a return statement to return
 | 
| +    // its value.
 | 
| +    ir.Primitive value = buildForeignCode(
 | 
| +        js.js.uncachedExpressionTemplate(code),
 | 
| +        arguments,
 | 
| +        behavior);
 | 
| +    buildReturn(value: value, sourceInformation: source);
 | 
| +  }
 | 
| +
 | 
|    /// Create a blocks of [statements] by applying [build] to all reachable
 | 
|    /// statements. The first statement is assumed to be reachable.
 | 
|    // TODO(johnniwinther): Type [statements] as `Iterable` when `NodeList` uses
 | 
| @@ -2599,6 +2673,7 @@ class IrBuilder {
 | 
|                                  List<ir.Primitive> arguments,
 | 
|                                  NativeBehavior behavior,
 | 
|                                  {Element dependency}) {
 | 
| +    assert(behavior != null);
 | 
|      types.TypeMask type = program.getTypeMaskForForeign(behavior);
 | 
|      ir.Primitive result = _continueWithExpression((k) => new ir.ForeignCode(
 | 
|          codeTemplate,
 | 
| @@ -2608,7 +2683,7 @@ class IrBuilder {
 | 
|          k,
 | 
|          dependency: dependency));
 | 
|      if (!codeTemplate.isExpression) {
 | 
| -      // Close the term if this is a "throw" expression.
 | 
| +      // Close the term if this is a "throw" expression or native body.
 | 
|        add(new ir.Unreachable());
 | 
|        _current = null;
 | 
|      }
 | 
| 
 |