Skip to content

Commit 73f4d49

Browse files
committed
[rfw] Fix fontWeight not applied in release mode
FontWeight is not a real Dart enum; it is a hand-crafted class with static const members. The previous implementation decoded fontWeight via enumValue(), which matched strings against FontWeight.value.toString(). In AOT/release builds this is not guaranteed to be stable, so matches silently failed and fontWeight defaulted to null (rendered as w400). Add a dedicated ArgumentDecoders.fontWeight() method that maps strings ("w100"–"w900", "normal", "bold") and integers (100–900) to the correct FontWeight constant using an explicit switch, without relying on toString(). Update textStyle and strutStyle to use it. Fixes flutter/flutter#180223 Made-with: Cursor
1 parent bf6d7db commit 73f4d49

2 files changed

Lines changed: 57 additions & 4 deletions

File tree

packages/rfw/lib/src/flutter/argument_decoders.dart

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,46 @@ class ArgumentDecoders {
632632
return null;
633633
}
634634

635+
/// Returns a [FontWeight] from the specified string or integer.
636+
///
637+
/// This does not use [FontWeight.toString], which is not guaranteed to be
638+
/// stable in release builds (since [FontWeight] is not a real Dart enum).
639+
///
640+
/// Supported string values: `"w100"` through `"w900"`, `"normal"` (mapped to
641+
/// [FontWeight.w400]), and `"bold"` (mapped to [FontWeight.w700]).
642+
///
643+
/// Supported integer values: `100` through `900` in increments of 100.
644+
static FontWeight? fontWeight(DataSource source, List<Object> key) {
645+
final int? numeric = source.v<int>(key);
646+
if (numeric != null) {
647+
switch (numeric) {
648+
case 100: return FontWeight.w100;
649+
case 200: return FontWeight.w200;
650+
case 300: return FontWeight.w300;
651+
case 400: return FontWeight.w400;
652+
case 500: return FontWeight.w500;
653+
case 600: return FontWeight.w600;
654+
case 700: return FontWeight.w700;
655+
case 800: return FontWeight.w800;
656+
case 900: return FontWeight.w900;
657+
}
658+
}
659+
switch (source.v<String>(key)) {
660+
case 'w100': return FontWeight.w100;
661+
case 'w200': return FontWeight.w200;
662+
case 'w300': return FontWeight.w300;
663+
case 'w400':
664+
case 'normal': return FontWeight.w400;
665+
case 'w500': return FontWeight.w500;
666+
case 'w600': return FontWeight.w600;
667+
case 'w700':
668+
case 'bold': return FontWeight.w700;
669+
case 'w800': return FontWeight.w800;
670+
case 'w900': return FontWeight.w900;
671+
}
672+
return null;
673+
}
674+
635675
/// Returns a [FontFeature] from the specified map.
636676
///
637677
/// The `feature` key is used as the font feature name (defaulting to the
@@ -1276,7 +1316,7 @@ class ArgumentDecoders {
12761316
/// following keys: 'fontFamily` (string), `fontFamilyFallback` ([list] of
12771317
/// [string]), `fontSize` (double), `height` (double), `leadingDistribution`
12781318
/// ([enumValue] of [TextLeadingDistribution]), `leading` (double),
1279-
/// `fontWeight` ([enumValue] of [FontWeight]), `fontStyle` ([enumValue] of
1319+
/// `fontWeight` ([fontWeight]), `fontStyle` ([enumValue] of
12801320
/// [FontStyle]), `forceStrutHeight` (boolean).
12811321
static StrutStyle? strutStyle(DataSource source, List<Object> key) {
12821322
if (!source.isMap(key)) {
@@ -1289,7 +1329,7 @@ class ArgumentDecoders {
12891329
height: source.v<double>([...key, 'height']),
12901330
leadingDistribution: enumValue<TextLeadingDistribution>(TextLeadingDistribution.values, source, [...key, 'leadingDistribution']),
12911331
leading: source.v<double>([...key, 'leading']),
1292-
fontWeight: enumValue<FontWeight>(FontWeight.values, source, [...key, 'fontWeight']),
1332+
fontWeight: fontWeight(source, [...key, 'fontWeight']),
12931333
fontStyle: enumValue<FontStyle>(FontStyle.values, source, [...key, 'fontStyle']),
12941334
forceStrutHeight: source.v<bool>([...key, 'forceStrutHeight']),
12951335
);
@@ -1350,7 +1390,7 @@ class ArgumentDecoders {
13501390
///
13511391
/// Otherwise (even if it has no keys), the [TextStyle] is created from the
13521392
/// following keys: `color` ([color]), `backgroundColor` ([color]), `fontSize`
1353-
/// (double), `fontWeight` ([enumValue] of [FontWeight]), `fontStyle`
1393+
/// (double), `fontWeight` ([fontWeight]), `fontStyle`
13541394
/// ([enumValue] of [FontStyle]), `letterSpacing` (double), `wordSpacing`
13551395
/// (double), `textBaseline` ([enumValue] of [TextBaseline]), `height`
13561396
/// (double), `leadingDistribution` ([enumValue] of
@@ -1369,7 +1409,7 @@ class ArgumentDecoders {
13691409
color: color(source, [...key, 'color']),
13701410
backgroundColor: color(source, [...key, 'backgroundColor']),
13711411
fontSize: source.v<double>([...key, 'fontSize']),
1372-
fontWeight: enumValue<FontWeight>(FontWeight.values, source, [...key, 'fontWeight']),
1412+
fontWeight: fontWeight(source, [...key, 'fontWeight']),
13731413
fontStyle: enumValue<FontStyle>(FontStyle.values, source, [...key, 'fontStyle']),
13741414
letterSpacing: source.v<double>([...key, 'letterSpacing']),
13751415
wordSpacing: source.v<double>([...key, 'wordSpacing']),

packages/rfw/test/argument_decoders_test.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,19 @@ void main() {
187187
await tester.pump();
188188
expect(tester.widget<Directionality>(find.byType(Directionality)).textDirection, TextDirection.ltr);
189189

190+
runtime.update(const LibraryName(<String>['test']), parseLibraryFile('''
191+
import core;
192+
widget root = Directionality(
193+
textDirection: "ltr",
194+
child: Text(
195+
text: 'Hello',
196+
style: { fontWeight: "w700" },
197+
),
198+
);
199+
'''));
200+
await tester.pump();
201+
expect(tester.widget<Text>(find.byType(Text)).style!.fontWeight, FontWeight.w700);
202+
190203
runtime.update(const LibraryName(<String>['test']), parseLibraryFile('''
191204
import core;
192205
widget root = FittedBox(

0 commit comments

Comments
 (0)