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 = |