Ticket Created

bug: SDK 8.0.0-Beta DF crashes in simulator when starting to play activity data simulation

class MyView extends WatchUi.DataField {
    var foo = 0;
    var bar;
    var heartRate;
  
    function initialize() {
        DataField.initialize();
        readSettings();
    }

    function readSettings() {
		foo = Application.Properties.getValue("foo"); // Numeric, default value 0
    }

    function compute(info as Activity.Info) {
        heartRate = foo <= 0 // exception on this line
			? info.currentHeartRate
			: bar != null
				? bar.average
				: null;
    }
} 

foo = 0 and bar = null all the time.

All works well after I start the DF in the simulator: in Simulation > Activity Data I can click start/pause/resume/stop.

However at the moment I click on play (with the random generated data, not a saved fit file) the above code crashes in the indicated line. Happens at least on fr965 and fr255.

Needless to say that the code works with SDK 7.4.3 both in simulator and on thousands of real devices.

  • I can also make the code work on 8.0.0-beta by adding parens [although I don't think they should be necessary]:


  • btw my version of compute is exactly the same as in OP.

    The generated mir files contents for compute() are completely different for 7.4.3 and 8.0.0-beta, and they do suggest that (nested?) ternaries are being compiled improperly in 8.0.0-beta.

    7.4.3:

        function compute(info as Activity.Info) as Void {
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_64_52_91_4_start:
    [ ".../TestFooDF/source/TestFooDFView.mc" 77 9 ]
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_begin:
            %tmp.2 = getv ? :foo;
            %tmp.3 = 0;
            %tmp.4 = lte %tmp.2 %tmp.3;
            bf %tmp.4 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_false;
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_true:
            %tmp.5 = lgetv %info;
            %tmp.6 = getv %tmp.5 :currentHeartRate;
            push %tmp.6;
            goto @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_end;
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_false:
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_79_5_81_6_begin:
            %tmp.8 = getv ? :bar;
            %tmp.9 = null;
            %tmp.10 = ne %tmp.8 %tmp.9;
            bf %tmp.10 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_79_5_81_6_false;
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_79_5_81_6_true:
            %tmp.12 = getv ? :bar;
            %tmp.13 = as %tmp.12 { (!Null) };
            %tmp.14 = getv %tmp.13 :average;
            push %tmp.14;
            goto @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_79_5_81_6_end;
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_79_5_81_6_false:
            %tmp.15 = null;
            push %tmp.15;
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_79_5_81_6_end:
            %tmp.16 = phi [%tmp.10 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_79_5_81_6_begin] [%tmp.14 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_79_5_81_6_true] [%tmp.15 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_79_5_81_6_false] [%tmp.16 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_79_5_81_6_end];
            push %tmp.16;
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_end:
            %tmp.17 = phi [%tmp.4 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_begin] [%tmp.6 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_true] [%tmp.16 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_false] [%tmp.17 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_end];
            putv self :heartRate %tmp.17;
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_64_52_91_4_stop:
        }

    Note that when foo <= 0, currentHeartRate is pushed and control correctly jumps to the end.

    8.0.0-beta:

        function compute(info as Activity.Info) as Void {
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_64_52_91_4_start:
    [ ".../TestFooDF/source/TestFooDFView.mc" 77 9 ]
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_begin:
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_79_12_begin:
            symbol [ foo %tmp.2 77 21 24 ];
            %tmp.2 = getv ? :foo;
            %tmp.3 = 0;
            %tmp.4 = lte %tmp.2 %tmp.3;
            bf %tmp.4 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_79_12_false;
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_79_12_true:
            %tmp.5 = lgetv %info;
            symbol [ info %tmp.5 78 5 9 ];
            symbol [ currentHeartRate %tmp.6 78 10 26 ];
            %tmp.6 = getv %tmp.5 :currentHeartRate;
            push %tmp.6;
            goto @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_79_12_end;
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_79_12_false:
            symbol [ bar %tmp.8 79 5 8 ];
            %tmp.8 = getv ? :bar;
            %tmp.9 = null;
            %tmp.10 = ne %tmp.8 %tmp.9;
            push %tmp.10;
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_79_12_end:
            %tmp.11 = phi [%tmp.4 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_79_12_begin] [%tmp.6 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_79_12_true] [%tmp.10 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_79_12_false] [%tmp.11 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_79_12_end];
            bf %tmp.11 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_false;
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_true:
            symbol [ bar %tmp.13 80 6 9 ];
            %tmp.13 = getv ? :bar;
            %tmp.14 = as %tmp.13 { (!Null) };
            symbol [ average %tmp.15 80 10 17 ];
            %tmp.15 = getv %tmp.14 :average;
            push %tmp.15;
            goto @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_end;
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_false:
            %tmp.16 = null;
            push %tmp.16;
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_end:
            %tmp.17 = phi [%tmp.11 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_begin] [%tmp.15 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_true] [%tmp.16 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_false] [%tmp.17 @_PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_77_21_81_6_end];
            symbol [ heartRate ? 77 9 18 ];
            putv self :heartRate %tmp.17;
    _PATH_PREFIX_TestFooDF_source_TestFooDFView_mc_64_52_91_4_stop:
        }

    Note that when foo <= 0, currentHeartRate is pushed and control incorrectly jumps to the middle.

  • TL;DR

    - I think the original code and "var x = foo <= 0;" are crashing for different reasons.

    - I agree with Kyle.ConnectIQ's implicit assessment that the problem is due to a bug in the evaluation of the ternary expressions. (Maybe something to do with precedence and nested ternaries?)