| 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 470a96d14c1e53abe1a1d0d67cc890a556e4206b..04e5256d08bb1553dcbeef0f79642b7bf24df807 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
|
| @@ -20,8 +20,10 @@ import '../elements/elements.dart';
|
| import '../io/source_information.dart';
|
| import '../js/js.dart' as js show
|
| js,
|
| + objectLiteral,
|
| LiteralStatement,
|
| Template,
|
| + InterpolatedExpression,
|
| isIdentityTemplate;
|
| import '../native/native.dart' show
|
| NativeBehavior;
|
| @@ -691,6 +693,9 @@ class IrBuilder {
|
| assert(!element.isLocal);
|
| assert(!element.isInstanceMember);
|
| assert(isOpen);
|
| + if (program.isJsInterop(element)) {
|
| + return buildInvokeJsInteropMember(element, arguments);
|
| + }
|
| return addPrimitive(
|
| new ir.InvokeStatic(element, selector, arguments, sourceInformation));
|
| }
|
| @@ -2066,6 +2071,86 @@ class IrBuilder {
|
| buildReturn(value: value, sourceInformation: source);
|
| }
|
|
|
| + static _isNotNull(ir.Primitive value) =>
|
| + value is! ir.Constant || !value.value.isNull;
|
| +
|
| + /// Builds a call to a resolved js-interop element.
|
| + ir.Primitive buildInvokeJsInteropMember(FunctionElement element,
|
| + List<ir.Primitive> arguments) {
|
| + program.addNativeMethod(element);
|
| + String target = program.getJsInteropTargetPath(element);
|
| + // Strip off trailing arguments that were not specified.
|
| + // TODO(jacobr,sigmund): assert that the trailing arguments are all null.
|
| + // TODO(jacobr): rewrite named arguments to an object literal matching
|
| + // the factory constructor case.
|
| + var inputs = arguments.where(_isNotNull).toList();
|
| +
|
| + var behavior = new NativeBehavior()..sideEffects.setAllSideEffects();
|
| + DartType type = element.isConstructor ?
|
| + element.enclosingClass.thisType : element.type.returnType;
|
| + // Native behavior effects here are similar to native/behavior.dart.
|
| + // The return type is dynamic if we don't trust js-interop type
|
| + // declarations.
|
| + behavior.typesReturned.add(
|
| + program.trustJSInteropTypeAnnotations ? type : const DynamicType());
|
| +
|
| + // The allocation effects include the declared type if it is native (which
|
| + // includes js interop types).
|
| + if (type.element != null && program.isNative(type.element)) {
|
| + behavior.typesInstantiated.add(type);
|
| + }
|
| +
|
| + // It also includes any other JS interop type if we don't trust the
|
| + // annotation or if is declared too broad.
|
| + if (!program.trustJSInteropTypeAnnotations || type.isObject ||
|
| + type.isDynamic) {
|
| + behavior.typesInstantiated.add(program.jsJavascriptObjectType);
|
| + }
|
| +
|
| + String code;
|
| + if (element.isGetter) {
|
| + code = target;
|
| + } else if (element.isSetter) {
|
| + code = "$target = #";
|
| + } else {
|
| + var args = new List.filled(inputs.length, '#').join(',');
|
| + code = element.isConstructor ? "new $target($args)" : "$target($args)";
|
| + }
|
| + return buildForeignCode(js.js.parseForeignJS(code), inputs, behavior);
|
| + // TODO(sigmund): should we record the source-information here?
|
| + }
|
| +
|
| + /// Builds an object literal that results from invoking a factory constructor
|
| + /// of a js-interop anonymous type.
|
| + ir.Primitive buildJsInteropObjectLiteral(ConstructorElement constructor,
|
| + List<ir.Primitive> arguments, {SourceInformation source}) {
|
| + assert(program.isJsInteropAnonymous(constructor));
|
| + program.addNativeMethod(constructor);
|
| + FunctionSignature params = constructor.functionSignature;
|
| + int i = 0;
|
| + var filteredArguments = <ir.Primitive>[];
|
| + var entries = new Map<String, js.Expression>();
|
| + params.orderedForEachParameter((ParameterElement parameter) {
|
| + // TODO(jacobr): throw if parameter names do not match names of property
|
| + // names in the class.
|
| + assert (parameter.isNamed);
|
| + ir.Primitive argument = arguments[i++];
|
| + if (_isNotNull(argument)) {
|
| + filteredArguments.add(argument);
|
| + entries[parameter.name] =
|
| + new js.InterpolatedExpression(filteredArguments.length - 1);
|
| + }
|
| + });
|
| + var code = new js.Template(null, js.objectLiteral(entries));
|
| + var behavior = new NativeBehavior();
|
| + if (program.trustJSInteropTypeAnnotations) {
|
| + behavior.typesReturned.add(constructor.enclosingClass.thisType);
|
| + }
|
| +
|
| + // TODO(sigmund): should we record the source-information here?
|
| + return buildForeignCode(code, filteredArguments, behavior);
|
| + }
|
| +
|
| /// 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
|
| @@ -2551,6 +2636,13 @@ class IrBuilder {
|
| Selector selector =
|
| new Selector(SelectorKind.CALL, element.memberName, callStructure);
|
| ClassElement cls = element.enclosingClass;
|
| + if (program.isJsInterop(element)) {
|
| + if (program.isJsInteropAnonymous(element)) {
|
| + return buildJsInteropObjectLiteral(element, arguments,
|
| + source: sourceInformation);
|
| + }
|
| + return buildInvokeJsInteropMember(element, arguments);
|
| + }
|
| if (program.requiresRuntimeTypesFor(cls)) {
|
| InterfaceType interface = type;
|
| Iterable<ir.Primitive> typeArguments =
|
|
|