Skip to content

Slow interop type tests: foo.isA<Foo> or foo.isInstanceOfString("Foo")Β #60344

Open
@mkustermann

Description

@mkustermann

Currently it seems the following code

import 'dart:js_interop';

@JS()
external JSAny get object;

@JS("Window")
extension type Window(JSAny? obj) {}

main() {
  print(object.instanceOfString('Window'));
  // or
  print(object.isA<Window>());
}

get compiled to something like this

main() {
    print(JSAnyUtilityExtension|instanceOfString(object));
}

which is implemented in sdk/lib/js_interop/js_interop.dart

  bool instanceOfString(String constructorName) {
    if (constructorName.isEmpty) return false;
    final parts = constructorName.split('.');
    JSObject? constructor = globalContext;
    for (final part in parts) {
      constructor = constructor?[part] as JSObject?;
      if (constructor == null) return false;
    }
    return instanceof(constructor as JSFunction);
  }

  // Implemented as
  //   JS("(o, c) => o instance of c",
  //       obj.toExternRef,
  //       constructor.toExternRef)`
  external bool instanceof(JSFunction constructor);

This is very inefficient as we do the instanceOfString logic (splitting string by ., looking up in the global context) for every type test.

A simple optimization would be to just cache the constructor in a global variable, so any following type checks will simply call the JS <obj> instanceof <constructor>. Maybe there's other ways to optimize it more, but at least this we should do.

One may also consider compiling this to per-type JS helper functions, e.g. object.isA<Window> to (o) => o instanceof Window instead of a generic (o, c) => o instanceof c -- if that's beneficial for performance

In some DOM related code (e.g. jaspr) this shows up on the profile and I think we should optimize this.

/cc @srujzs @osa1 Could one of you take a look at this?
One could

Metadata

Metadata

Assignees

Labels

area-web-jsIssues related to JavaScript support for Dart Web, including DDC, dart2js, and JS interop.web-js-interopIssues that impact all js interop

Type

No type

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions