Skip to content

Commit 57004a7

Browse files
Merge pull request #989 from Workiva/clean-up-and-optimize-generated-props
FED-4215 Low-hanging dart2js code side optimizations
2 parents acdc10a + 57c6845 commit 57004a7

File tree

153 files changed

+2181
-9917
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

153 files changed

+2181
-9917
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# OverReact Changelog
22

33
## Unreleased
4+
- [#989] Optimize generated code to decrease dart2js compile size, saving ~577 bytes per component (when using `-03 --csp --minify`)
45
- [#992] Fix compilation errors for legacy boilerplate defined in libraries with a Dart language version of >=3.0
56

67
## 5.4.6

example/boilerplate_versions/dart2_only/basic_component1.over_react.g.dart

Lines changed: 2 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

example/boilerplate_versions/dart2_only/basic_component2.over_react.g.dart

Lines changed: 11 additions & 50 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/src/builder/codegen/component_generator.dart

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ abstract class ComponentGenerator extends BoilerplateDeclarationGenerator {
6060
// implemented for Component2.
6161
// This implementation here is necessary so that mixin accesses aren't compiled as index$ax
6262
outputContentsBuffer
63-
..writeln(' ${nullSafety ? 'late ' : ''}${propsNames.jsMapImplName} _cachedTypedProps;')
63+
..writeln(' ${nullSafety ? 'late ' : ''}${propsNames.implName} _cachedTypedProps;')
6464
..writeln()
6565
..writeln(' @override')
66-
..writeln(' ${propsNames.jsMapImplName} get props => _cachedTypedProps;')
66+
..writeln(' ${propsNames.implName} get props => _cachedTypedProps;')
6767
..writeln()
6868
..writeln(' @override')
6969
..writeln(' set props(Map value) {')
@@ -81,8 +81,8 @@ abstract class ComponentGenerator extends BoilerplateDeclarationGenerator {
8181
..writeln()
8282
..writeln(' @override ')
8383
..writeln(
84-
' ${propsNames.jsMapImplName} typedPropsFactoryJs(JsBackedMap${nullSafety ? '?' : ''} backingMap)'
85-
' => ${propsNames.jsMapImplName}(backingMap);')
84+
' ${propsNames.implName} typedPropsFactoryJs(JsBackedMap${nullSafety ? '?' : ''} backingMap)'
85+
' => ${propsNames.implName}(backingMap);')
8686
..writeln();
8787
}
8888

@@ -96,9 +96,9 @@ abstract class ComponentGenerator extends BoilerplateDeclarationGenerator {
9696
final stateNames = this.stateNames!;
9797
if (isComponent2) {
9898
outputContentsBuffer
99-
..writeln(' ${nullSafety ? 'late ' : ''}${stateNames.jsMapImplName} _cachedTypedState;')
99+
..writeln(' ${nullSafety ? 'late ' : ''}${stateNames.implName} _cachedTypedState;')
100100
..writeln(' @override')
101-
..writeln(' ${stateNames.jsMapImplName} get state => _cachedTypedState;')
101+
..writeln(' ${stateNames.implName} get state => _cachedTypedState;')
102102
..writeln()
103103
..writeln(' @override')
104104
..writeln(' set state(Map value) {')
@@ -111,8 +111,8 @@ abstract class ComponentGenerator extends BoilerplateDeclarationGenerator {
111111
..writeln()
112112
..writeln(' @override ')
113113
..writeln(
114-
' ${stateNames.jsMapImplName} typedStateFactoryJs(JsBackedMap${nullSafety ? '?' : ''} backingMap)'
115-
' => ${stateNames.jsMapImplName}(backingMap);')
114+
' ${stateNames.implName} typedStateFactoryJs(JsBackedMap${nullSafety ? '?' : ''} backingMap)'
115+
' => ${stateNames.implName}(backingMap);')
116116
..writeln();
117117
}
118118
outputContentsBuffer

lib/src/builder/codegen/names.dart

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -143,30 +143,6 @@ class TypedMapNames {
143143
/// | Mixin-based | FooProps | $FooProps |
144144
String get implName => '$_prefix$privateSourcePrefix\$$_normalizedName';
145145

146-
/// The name of the generated concrete props/state implementation subclass
147-
/// that can be backed by any Map.
148-
///
149-
/// Example:
150-
///
151-
/// | Version | [consumerName] | Value |
152-
/// |-------------|----------------|-----------------------|
153-
/// | Legacy | _$FooProps | _$$FooProps$PlainMap |
154-
/// | Legacy | _$_FooProps | _$$_FooProps$PlainMap |
155-
/// | Mixin-based | FooProps | $FooProps$PlainMap |
156-
String get plainMapImplName => '$implName\$PlainMap';
157-
158-
/// The name of the generated concrete props/state implementation subclass
159-
/// that can be backed only by JsBackedMaps.
160-
///
161-
/// Example:
162-
///
163-
/// | Version | [consumerName] | Value |
164-
/// |-------------|----------------|--------------------|
165-
/// | Legacy | _$FooProps | _$$FooProps$JsMap |
166-
/// | Legacy | _$_FooProps | _$$_FooProps$JsMap |
167-
/// | Mixin-based | FooProps | $FooProps$JsMap |
168-
String get jsMapImplName => '$implName\$JsMap';
169-
170146
/// The name of the consumable props/state class.
171147
///
172148
/// - For legacy backwards compatible boilerplate, this is the companion class.

lib/src/builder/codegen/typed_map_impl_generator.dart

Lines changed: 15 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -95,18 +95,10 @@ abstract class TypedMapImplGenerator extends BoilerplateDeclarationGenerator {
9595
void _generateFactory() {
9696
assert(factoryNames.length == 1, 'factoryNames must have a length of 1');
9797

98-
outputContentsBuffer.write(
99-
'${names.implName} ${factoryNames.first.implName}([Map${nullSafety ? '?' : ''} backingProps]) => ');
100-
101-
if (!isComponent2) {
102-
/// _$$FooProps _$Foo([Map backingProps]) => _$$FooProps(backingProps);
103-
outputContentsBuffer.writeln('${names.implName}(backingProps);');
104-
} else {
105-
/// _$$FooProps _$Foo([Map backingProps]) => backingProps == null ? $jsMapImplName(JsBackedMap()) : _$$FooProps(backingProps);
106-
// Optimize this case for when backingProps is null to promote inlining of `jsMapImplName` typing
107-
outputContentsBuffer.writeln(
108-
'backingProps == null ? ${names.jsMapImplName}(JsBackedMap()) : ${names.implName}(backingProps);');
109-
}
98+
// _$$FooProps _$Foo([Map? backingProps]) => _$$FooProps(backingProps);
99+
outputContentsBuffer.writeln(
100+
'${names.implName} ${factoryNames.first.implName}([Map${nullSafety ? '?' : ''} backingProps])'
101+
' => ${names.implName}(backingProps);');
110102
}
111103

112104
String _generateImplClassHeader();
@@ -168,70 +160,32 @@ abstract class TypedMapImplGenerator extends BoilerplateDeclarationGenerator {
168160
'componentFactoryName/propKeyNamespace must not be specified for state');
169161
}
170162
}
171-
172-
final classDeclaration = StringBuffer();
173-
if (isComponent2) {
174-
// This class will only have a factory constructor that instantiates one
175-
// of two subclasses.
176-
classDeclaration.write('abstract ');
177-
}
178-
179-
classDeclaration
180-
..write(_generateImplClassHeader())
181-
..write(' {');
182-
183163
final propsOrState = isProps ? 'props' : 'state';
184164

185-
// Class declaration
186165
final buffer = StringBuffer()
166+
// Class declaration
187167
..writeln('// Concrete $propsOrState implementation.')
188168
..writeln('//')
189169
..writeln(
190170
'// Implements constructor and backing map${isProps ? ', and links up to generated component factory' : ''}.')
191171
..write(internalGeneratedMemberDeprecationLine())
192-
..writeln(classDeclaration);
193-
194-
// Constructors
195-
if (isComponent2) {
196-
buffer
197-
..writeln(' ${names.implName}._();')
198-
..writeln()
199-
..writeln(' factory ${names.implName}(Map${nullSafety ? '?' : ''} backingMap) {')
200-
..writeln(' if (backingMap == null || backingMap is JsBackedMap) {')
201-
..writeln(
202-
' return ${names.jsMapImplName}(backingMap as JsBackedMap${nullSafety ? '?' : ''});')
203-
..writeln(' } else {')
204-
..writeln(' return ${names.plainMapImplName}(backingMap);')
205-
..writeln(' }')
206-
..writeln(' }');
207-
} else {
208-
buffer
209-
..writeln(
210-
' // This initializer of `_$propsOrState` to an empty map, as well as the reassignment')
211-
..writeln(
212-
' // of `_$propsOrState` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217')
213-
// TODO need to remove this workaround once https://github.com/dart-lang/sdk/issues/36217 is fixed get nice dart2js output
214-
..writeln(
215-
' ${names.implName}(Map${nullSafety ? '?' : ''} backingMap) : this._$propsOrState = {} {')
216-
..writeln(' this._$propsOrState = backingMap ?? {};')
217-
..writeln(' }');
218-
}
172+
..write(_generateImplClassHeader())
173+
..writeln(' {')
174+
// Constructor
175+
..writeln(' ${names.implName}([Map${nullSafety ? '?' : ''} backingMap])'
176+
' : this.$propsOrState = backingMap ?? JsBackedMap();');
219177

220178
// This needs to be a top-level member and not a static member, and it needs to be unique
221179
// to avoid collisions across typed map impls within the library, potentially in multiple parts.
222180
// So, we'll just namespace it by the impl name.
223181
final topLevelGetPropKeyAliasName = '_\$getPropKey\$${names.implName}';
224182

225183
// Members
226-
if (!isComponent2) {
227-
buffer
228-
..writeln()
229-
..writeln(' /// The backing $propsOrState map proxied by this class.')
230-
..writeln(' @override')
231-
..writeln(' Map get $propsOrState => _$propsOrState;')
232-
..writeln(' Map _$propsOrState;');
233-
}
234184
buffer
185+
..writeln()
186+
..writeln(' /// The backing $propsOrState map proxied by this class.')
187+
..writeln(' @override')
188+
..writeln(' final Map $propsOrState;')
235189
..writeln()
236190
..writeln(
237191
' /// Let `${isProps ? 'UiProps' : 'UiState'}` internals know that this class has been generated.')
@@ -296,38 +250,6 @@ abstract class TypedMapImplGenerator extends BoilerplateDeclarationGenerator {
296250
..writeln('const $topLevelGetPropKeyAliasName = getPropKey;');
297251
}
298252

299-
// Component2-specific classes
300-
if (isComponent2) {
301-
// TODO need to remove this workaround once https://github.com/dart-lang/sdk/issues/36217 is fixed get nice dart2js output
302-
buffer
303-
..writeln()
304-
..writeln('''
305-
// Concrete $propsOrState implementation that can be backed by any [Map].
306-
${internalGeneratedMemberDeprecationLine()}class ${names.plainMapImplName}$typeParamsOnClass extends ${names.implName}$typeParamsOnSuper {
307-
// This initializer of `_$propsOrState` to an empty map, as well as the reassignment
308-
// of `_$propsOrState` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217
309-
${names.plainMapImplName}(Map${nullSafety ? '?' : ''} backingMap) : this._$propsOrState = {}, super._() {
310-
this._$propsOrState = backingMap ?? {};
311-
}
312-
/// The backing $propsOrState map proxied by this class.
313-
@override
314-
Map get $propsOrState => _$propsOrState;
315-
Map _$propsOrState;
316-
}
317-
// Concrete $propsOrState implementation that can only be backed by [JsMap],
318-
// allowing dart2js to compile more optimal code for key-value pair reads/writes.
319-
${internalGeneratedMemberDeprecationLine()}class ${names.jsMapImplName}$typeParamsOnClass extends ${names.implName}$typeParamsOnSuper {
320-
// This initializer of `_$propsOrState` to an empty map, as well as the reassignment
321-
// of `_$propsOrState` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217
322-
${names.jsMapImplName}(JsBackedMap${nullSafety ? '?' : ''} backingMap) : this._$propsOrState = JsBackedMap(), super._() {
323-
this._$propsOrState = backingMap ?? JsBackedMap();
324-
}
325-
/// The backing $propsOrState map proxied by this class.
326-
@override
327-
JsBackedMap get $propsOrState => _$propsOrState;
328-
JsBackedMap _$propsOrState;
329-
}''');
330-
}
331253
return buffer.toString();
332254
}
333255
}
@@ -488,7 +410,7 @@ class _TypedMapImplGenerator extends TypedMapImplGenerator {
488410
'${factoryName.privateConfigName} = UiFactoryConfig(\n'
489411
'propsFactory: PropsFactory(\n'
490412
'map: (map) => ${names.implName}(map),\n'
491-
'jsMap: (map) => ${names.jsMapImplName}(map),),\n'
413+
'jsMap: (map) => ${names.implName}(map),),\n'
492414
'displayName: \'${factoryName.consumerName}\');\n\n'
493415
'@Deprecated(r\'Use the private variable, ${factoryName.privateConfigName}, instead \'\n'
494416
'\'and update the `over_react` lower bound to version 4.1.0. \'\n'

0 commit comments

Comments
 (0)