Description
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
Type
Projects
Status