Skip to content

[dart2js] Revisit dynamic calling convention to avoid minification problems #48268

Open
@rakudrama

Description

@rakudrama

For historical reasons, dart2js does not make much distinction between instance method calls and dynamic calls. In Dart 1, all instance calls where effectively dynamic calls. Now the vast majority of calls are not dynamic so we should consider compiling dynamic calls differently.

dart2js uses code of the form a.b() for both instance calls and dynamic calls for selectors that do not use the interceptor calling convention. For example, this method:

demo(dynamic x, dynamic y) {
  print(x.difference(y));
  print(x.intersection(y));
}

compiles the calls differently because intersection is defined for JavaScript DOMRect, but difference is not defined on any type that is not declared as an ordinary Dart class.

demo(x, y) {
  A.print(x.difference$1(y));
  A.print(getInterceptor(x).intersection$1(x, y));
}

We can minify intersection$1 to anything we like since all JavaScript calls have a receiver that we control.

We currently have to be careful with minifying difference$1. For example, we can't choose at, since String.prototype.at is defined and will return some value rather than crashing with a TypeError that can be understood as a NoSuchMethodError.
This problem could be solved by using the interceptor calling convention for dynamic calls, but that comes at a cost of making all methods that can be called from dynamic calls compatible the more cumbersome interceptor calling convention.

One could use different selector for dynamic calls. This selector would be for the 'dynamic entry point' which could, in spec mode, contain checks on all parameters.
When there are no checks over those required for the instance call entry point (e.g. Set.difference could have been written to require parametric covariance check) the dynamic selector could just be an alias.

To avoid collisions with the JavaScript environment, the dynamic selector could be a JavaScript symbol x[dynamicSelectors.intersection$1](y).

One downside of having dynamic and instance entry-points is that functions, including tear-offs, need them too.
Tearing-off a method that passes to a dynamic closure call implies the need for dynamic checking of the arguments.
Most tearoffs would appear to escape to a potential dynamic closure call.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3A lower priority bug or feature requestarea-web-jsIssues related to JavaScript support for Dart Web, including DDC, dart2js, and JS interop.dart2js-interceptorsweb-dart2js

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions