| Index: pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
|
| diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
|
| index bf53dae59e3e5d17595e6801855705e53e438049..55f9f290c18e6b14e4b93ec3457b5213a293f1f8 100644
|
| --- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
|
| +++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
|
| @@ -653,23 +653,44 @@ class FragmentEmitter {
|
| return js.js('function #() { }', name);
|
| }
|
|
|
| - List<js.Name> fieldNames =
|
| - cls.fields.map((Field field) => field.name).toList();
|
| - if (cls.hasRtiField) {
|
| - fieldNames.add(namer.rtiFieldJsName);
|
| + var statements = <js.Statement>[];
|
| + var parameters = <js.Name>[];
|
| + var thisRef;
|
| +
|
| + // If there are many references to `this`, cache it in a local.
|
| + if (cls.fields.length + (cls.hasRtiField ? 1 : 0) >= 4) {
|
| + // TODO(29455): Fix js_ast printer and minifier to avoid conflicts between
|
| + // js.Name and string-named variables, then use '_' in the js template
|
| + // text.
|
| +
|
| + // We pick '_' in minified mode because no field minifies to '_'. This
|
| + // avoids a conflict with one of the parameters which are named the same
|
| + // as the fields. Unminified, a field might have the name '_', so we pick
|
| + // '$_', which is an impossible member name since we escape '$'s in names.
|
| + js.Name underscore = compiler.options.enableMinification
|
| + ? new StringBackedName('_')
|
| + : new StringBackedName(r'$_');
|
| + statements.add(js.js.statement('var # = this;', underscore));
|
| + thisRef = underscore;
|
| + } else {
|
| + thisRef = js.js('this');
|
| }
|
|
|
| - Iterable<js.Name> assignments = fieldNames.map((js.Name field) {
|
| - return js.js("this.#field = #field", {"field": field});
|
| - });
|
| -
|
| - // TODO(sra): Cache 'this' in a one-character local for 4 or more uses of
|
| - // 'this'. i.e. "var _=this;_.a=a;_.b=b;..."
|
| + for (Field field in cls.fields) {
|
| + js.Name paramName = field.name;
|
| + parameters.add(paramName);
|
| + statements
|
| + .add(js.js.statement('#.# = #', [thisRef, field.name, paramName]));
|
| + }
|
|
|
| - // TODO(sra): Separate field and field initializer parameter names so the
|
| - // latter may be fully minified.
|
| + if (cls.hasRtiField) {
|
| + js.Name paramName = namer.rtiFieldJsName;
|
| + parameters.add(paramName);
|
| + statements.add(js.js
|
| + .statement('#.# = #', [thisRef, namer.rtiFieldJsName, paramName]));
|
| + }
|
|
|
| - return js.js('function #(#) { # }', [name, fieldNames, assignments]);
|
| + return js.js('function #(#) { # }', [name, parameters, statements]);
|
| }
|
|
|
| /// Emits the prototype-section of the fragment.
|
|
|