Skip to content

Commit f5e544a

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. Also fix three pre-existing bugs where absolute keys were used instead of relative keys: textDirection in the sweep shader decoder, textBaseline and overflow in textStyle. Fixes flutter/flutter#180223 Made-with: Cursor
1 parent cac0fc5 commit f5e544a

2 files changed

Lines changed: 60 additions & 7 deletions

File tree

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

Lines changed: 47 additions & 7 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
@@ -1243,7 +1283,7 @@ class ArgumentDecoders {
12431283
case 'sweep':
12441284
return gradient(source, key)!.createShader(
12451285
rect(source, [...key, 'rect']) ?? Rect.zero,
1246-
textDirection: enumValue<TextDirection>(TextDirection.values, source, ['textDirection']) ?? TextDirection.ltr,
1286+
textDirection: enumValue<TextDirection>(TextDirection.values, source, [...key, 'textDirection']) ?? TextDirection.ltr,
12471287
);
12481288
default:
12491289
final ArgumentDecoder<Shader?>? decoder = shaderDecoders[type];
@@ -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,11 +1409,11 @@ 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']),
1376-
textBaseline: enumValue<TextBaseline>(TextBaseline.values, source, ['textBaseline']),
1416+
textBaseline: enumValue<TextBaseline>(TextBaseline.values, source, [...key, 'textBaseline']),
13771417
height: source.v<double>([...key, 'height']),
13781418
leadingDistribution: enumValue<TextLeadingDistribution>(TextLeadingDistribution.values, source, [...key, 'leadingDistribution']),
13791419
locale: locale(source, [...key, 'locale']),
@@ -1387,7 +1427,7 @@ class ArgumentDecoders {
13871427
decorationThickness: source.v<double>([...key, 'decorationThickness']),
13881428
fontFamily: source.v<String>([...key, 'fontFamily']),
13891429
fontFamilyFallback: list<String>(source, [...key, 'fontFamilyFallback'], string),
1390-
overflow: enumValue<TextOverflow>(TextOverflow.values, source, ['overflow']),
1430+
overflow: enumValue<TextOverflow>(TextOverflow.values, source, [...key, 'overflow']),
13911431
);
13921432
}
13931433

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)