Chromium Code Reviews| 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..2985331a069fba7272819b4d1d7944ceb5005163 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,8 +693,12 @@ class IrBuilder { |
| assert(!element.isLocal); |
| assert(!element.isInstanceMember); |
| assert(isOpen); |
| - return addPrimitive( |
| - new ir.InvokeStatic(element, selector, arguments, sourceInformation)); |
| + if (program.isJsInterop(element)) { |
| + return buildInvokeJsInteropMember(element, arguments); |
| + } else { |
|
Jacob
2016/02/11 17:54:33
style not: remove else.
Siggi Cherem (dart-lang)
2016/02/11 21:16:53
Done.
|
| + return addPrimitive( |
| + new ir.InvokeStatic(element, selector, arguments, sourceInformation)); |
| + } |
| } |
| ir.Primitive _buildInvokeSuper(Element target, |
| @@ -2066,6 +2072,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, |
|
Siggi Cherem (dart-lang)
2016/02/11 03:13:30
most of this code logic is line-per-line as it was
Jacob
2016/02/11 17:54:33
Acknowledged.
|
| + List<ir.Primitive> arguments) { |
| + program.addNativeMethod(element); |
| + String target = program.getJsInteropTargetPath(element); |
| + // Strip off trailing arguments that were not specified. |
| + // TODO(jacobr): assert that the trailing arguments are all null. |
|
Jacob
2016/02/11 17:54:33
hey now... shouldn't this be
TODO(sigmund)?
:)
Siggi Cherem (dart-lang)
2016/02/11 21:16:53
The comment was there before, I just made it a TOD
|
| + // 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; |
|
Siggi Cherem (dart-lang)
2016/02/11 03:13:30
difference 1: I use `target` directly here, SSA cr
Jacob
2016/02/11 17:54:33
Acknowledged.
|
| + } 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); |
|
Siggi Cherem (dart-lang)
2016/02/11 03:13:31
difference 2: I no longer attach the code to the b
|
| + // TODO(sigmund): should we record the source-information here? |
|
Siggi Cherem (dart-lang)
2016/02/11 03:13:31
difference 3: I have no place to store source-info
Jacob
2016/02/11 17:54:33
Will that result in a good source maps exerience u
Siggi Cherem (dart-lang)
2016/02/11 21:16:53
Yeah, I think that is likely to be an issue here a
|
| + } |
| + |
| + /// 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 +2637,14 @@ 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); |
| + } else { |
|
Jacob
2016/02/11 17:54:33
sme nit about unneeded else
Siggi Cherem (dart-lang)
2016/02/11 21:16:53
Done.
|
| + return buildInvokeJsInteropMember(element, arguments); |
| + } |
| + } |
| if (program.requiresRuntimeTypesFor(cls)) { |
| InterfaceType interface = type; |
| Iterable<ir.Primitive> typeArguments = |