| Index: pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart
|
| diff --git a/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart
|
| index ad7057b5154513348953c6f6d30b6f2a4cd1bfc7..d6272700206cab5d3a90d3da3aff06ba682a3717 100644
|
| --- a/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart
|
| +++ b/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart
|
| @@ -4,6 +4,7 @@
|
|
|
| library dart2js.new_js_emitter.model_emitter;
|
|
|
| +import '../../constants/values.dart' show ConstantValue;
|
| import '../../dart2jslib.dart' show Compiler;
|
| import '../../dart_types.dart' show DartType;
|
| import '../../elements/elements.dart' show ClassElement;
|
| @@ -113,7 +114,11 @@ class ModelEmitter {
|
| 'holders': emitHolders(program.holders),
|
| 'tearOff': buildTearOffCode(backend),
|
| 'parseFunctionDescriptor':
|
| - js.js.statement(parseFunctionDescriptorBoilerplate),
|
| + js.js.statement(parseFunctionDescriptorBoilerplate,
|
| + {'argCnt': js.string(namer.requiredParameterField),
|
| + 'defArgValues': js.string(namer.defaultValuesField),
|
| + 'callName': js.string(namer.callNameField)}),
|
| +
|
| 'cyclicThrow':
|
| backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()),
|
| 'outputContainsConstantList': program.outputContainsConstantList,
|
| @@ -122,6 +127,7 @@ class ModelEmitter {
|
| 'staticNonFinals':
|
| emitStaticNonFinalFields(fragment.staticNonFinalFields),
|
| 'operatorIsPrefix': js.string(namer.operatorIsPrefix),
|
| + 'callName': js.string(namer.callNameField),
|
| 'eagerClasses': emitEagerClassInitializations(fragment.libraries),
|
| 'invokeMain': fragment.invokeMain,
|
| 'code': code};
|
| @@ -552,19 +558,27 @@ class ModelEmitter {
|
| /// facilitate the generation of tearOffs at runtime. The format is an array
|
| /// with the following fields:
|
| ///
|
| - /// [InstanceMethod.aliasName] (optional).
|
| - /// [Method.code]
|
| - /// [DartMethod.callName]
|
| - /// isInterceptedMethod (optional, present if [DartMethod.needsTearOff]).
|
| - /// [DartMethod.tearOffName] (optional, present if [DartMethod.needsTearOff]).
|
| - /// functionType (optional, present if [DartMethod.needsTearOff]).
|
| + /// * [InstanceMethod.aliasName] (optional).
|
| + /// * [Method.code]
|
| + /// * [DartMethod.callName]
|
| + /// * isInterceptedMethod (optional, present if [DartMethod.needsTearOff]).
|
| + /// * [DartMethod.tearOffName] (optional, present if
|
| + /// [DartMethod.needsTearOff]).
|
| + /// * functionType (optional, present if [DartMethod.needsTearOff]).
|
| ///
|
| /// followed by
|
| ///
|
| - /// [ParameterStubMethod.name]
|
| - /// [ParameterStubMethod.code]
|
| + /// * [ParameterStubMethod.name]
|
| + /// * [ParameterStubMethod.callName]
|
| + /// * [ParameterStubMethod.code]
|
| ///
|
| /// for each stub in [DartMethod.parameterStubs].
|
| + ///
|
| + /// If the closure could be used in `Function.apply` (i.e.
|
| + /// [DartMethod.canBeApplied] is true) then the following fields are appended:
|
| + ///
|
| + /// * [DartMethod.requiredParameterCount]
|
| + /// * [DartMethod.optionalParameterDefaultValues]
|
|
|
| static final String parseFunctionDescriptorBoilerplate = r"""
|
| function parseFunctionDescriptor(proto, name, descriptor) {
|
| @@ -581,7 +595,7 @@ function parseFunctionDescriptor(proto, name, descriptor) {
|
|
|
| proto[name] = f;
|
| var funs = [f];
|
| - f.$callName = descriptor[++pos];
|
| + f[#callName] = descriptor[++pos];
|
|
|
| var isInterceptedOrParameterStubName = descriptor[pos + 1];
|
| var isIntercepted, tearOffName, reflectionInfo;
|
| @@ -591,9 +605,12 @@ function parseFunctionDescriptor(proto, name, descriptor) {
|
| reflectionInfo = descriptor[++pos];
|
| }
|
|
|
| - for (++pos; pos < descriptor.length; pos += 3) {
|
| + // We iterate in blocks of 3 but have to stop before we reach the (optional)
|
| + // two trailing items. To accomplish this, we only iterate until we reach
|
| + // length - 2.
|
| + for (++pos; pos < descriptor.length - 2; pos += 3) {
|
| var stub = descriptor[pos + 2];
|
| - stub.$callName = descriptor[pos + 1];
|
| + stub[#callName] = descriptor[pos + 1];
|
| proto[descriptor[pos]] = stub;
|
| funs.push(stub);
|
| }
|
| @@ -602,7 +619,10 @@ function parseFunctionDescriptor(proto, name, descriptor) {
|
| proto[tearOffName] =
|
| tearOff(funs, reflectionInfo, false, name, isIntercepted);
|
| }
|
| -
|
| + if (descriptor[pos] != null) {
|
| + f[#argCnt] = descriptor[pos];
|
| + f[#defArgValues] = descriptor[pos + 1];
|
| + }
|
| } else {
|
| proto[name] = descriptor;
|
| }
|
| @@ -618,6 +638,24 @@ function parseFunctionDescriptor(proto, name, descriptor) {
|
| }
|
| }
|
|
|
| + js.Expression _encodeOptionalParameterDefaultValues(DartMethod method) {
|
| + js.Expression result;
|
| + // TODO(herhut): Replace [js.LiteralNull] with [js.ArrayHole].
|
| + if (method.optionalParameterDefaultValues is List) {
|
| + List<ConstantValue> defs = method.optionalParameterDefaultValues;
|
| + Iterable<js.Expression> elements = defs.map(constantEmitter.reference);
|
| + return new js.ArrayInitializer(elements.toList());
|
| + } else {
|
| + Map<String, ConstantValue> defs = method.optionalParameterDefaultValues;
|
| + List<js.Property> properties = <js.Property>[];
|
| + defs.forEach((String name, ConstantValue value) {
|
| + properties.add(new js.Property(js.string(name),
|
| + constantEmitter.reference(value)));
|
| + });
|
| + return new js.ObjectInitializer(properties);
|
| + }
|
| + }
|
| +
|
| Iterable<js.Expression> emitInstanceMethod(Method method) {
|
|
|
| List<js.Expression> makeNameCodePair(Method method) {
|
| @@ -652,6 +690,10 @@ function parseFunctionDescriptor(proto, name, descriptor) {
|
| }
|
|
|
| data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet));
|
| + if (method.canBeApplied) {
|
| + data.add(js.number(method.requiredParameterCount));
|
| + data.add(_encodeOptionalParameterDefaultValues(method));
|
| + }
|
| return [js.string(method.name), new js.ArrayInitializer(data)];
|
| } else {
|
| // TODO(floitsch): not the most efficient way...
|
| @@ -695,6 +737,10 @@ function parseFunctionDescriptor(proto, name, descriptor) {
|
| data.add(js.string(method.tearOffName));
|
| data.add(_generateFunctionType(method.type));
|
| data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet));
|
| + if (method.canBeApplied) {
|
| + data.add(js.number(method.requiredParameterCount));
|
| + data.add(_encodeOptionalParameterDefaultValues(method));
|
| + }
|
| return [js.string(method.name), holderIndex,
|
| new js.ArrayInitializer(data)];
|
| } else {
|
| @@ -782,13 +828,13 @@ function parseFunctionDescriptor(proto, name, descriptor) {
|
| function compileAllStubs() {
|
| var funs;
|
| var fun = compile(name, descriptor[0]);
|
| - fun.\$callName = descriptor[1];
|
| + fun[#callName] = descriptor[1];
|
| holder[name] = fun;
|
| funs = [fun];
|
| for (var pos = 4; pos < descriptor.length; pos += 3) {
|
| var stubName = descriptor[pos];
|
| fun = compile(stubName, descriptor[pos + 2]);
|
| - fun.\$callName = descriptor[pos + 1];
|
| + fun[#callName] = descriptor[pos + 1];
|
| holder[stubName] = fun;
|
| funs.push(fun);
|
| }
|
|
|