Skip to content

dart2js miscompilation of late final fields when optimizations are disabled #60115

@simolus3

Description

@simolus3

Consider this program:

void main() {
  final x = X();
  print('should be test');
  print(x.name);
}

final class X {
  late final String name = 'test';
}

Now, compile it with dart compile js -O0 --no-minify repro.dart. We'd expect this to print should be test and test, but:

$ node out.js
should be test
Instance of 'JavaScriptObject'

Relevant snippets from the generated code:

  var $ = {};
  A = {JS_CONST: function JS_CONST() {
    },
    printToConsole(line) {
      A.printString(line);
    },
    isSentinel(value) {
      return false; // ?????
    },
    X: function X() {
      this.__X_name_FI = $;
    },
  A.X.prototype = {
    get$name() {
      var value = this.__X_name_FI;
      if (A.boolConversionCheck(A.isSentinel(value))) {
        this.__X_name_FI !== $ && A.throwLateFieldADI("name");
        value = this.__X_name_FI = "test";
      }
      return value;
    }
  };

It looks like the definition for isSentinal should be value === $, but it's not. The broken isSentinal implementation then causes all late final fields to return the sentinel value, breaking Dart programs in weird ways.
This happens both on Dart 3.6.2 and a recent build from main (I've tested with 3.8.0-edge.1c24e58896b6706999f55b269f2477d393d97fab).

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-web-jsIssues related to JavaScript support for Dart Web, including DDC, dart2js, and JS interop.type-bugIncorrect behavior (everything from a crash to more subtle misbehavior)web-dart2js

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions