Closed
Description
Both ExternalDartReference.toDartObject
and Object.toExternalReference
are defined as extensions on non-null types.
This poses a problem for generic APIs which could contain null:
extension type WritableSignal<T>(JSFunction _) implements Signal<T> {
@JS('u')
external void _update(JSExportedDartFunction update);
void update(T Function(T) function) {
_update(_jsCompatibleFunction(function).toJS);
}
/// Wraps [function] in a JS compatible function signature.
///
/// We can't simply cast `T Function(T)` as `ExternalDartReference Function(ExternalDartReference)`.
ExternalDartReference? Function(ExternalDartReference?) _jsCompatibleFunction(
T Function(T) function,
) {
return (value) {
return function(_trustAs(value?.toDartObject))?.toExternalReference;
};
}
}
/// Returns [value] typed as [T] while omitting the `as` cast.
@pragma('dart2js:as:trust')
T _trustAs<T>(Object? value) => value as T;
Note the implementation of the wrapper function must use ?.
to access both toDartObject
and toExternalReference
because T
could be parameterized with a nullable type.
This causes dart2js
to emit rather inefficient JavaScript:
A.WritableSignal__jsCompatibleFunction_closure.prototype = {
call$1(value) {
var t1 = value == null ? null : value;
t1 = this.$function.call$1(t1);
return t1 == null ? null : t1;
}
};
If I'm not mistaken, isn't this simply equivalent to:
A.WritableSignal__jsCompatibleFunction_closure.prototype = {
call$1(value) {
return this.$function.call$1(t1);
}
};
(Which could potentially be further inlined).
Could we simply redefine these extensions on Object?
and ExternalDartReference?
, removing the need for the ?.
access?
ExternalDartReference? Function(ExternalDartReference?) _jsCompatibleFunction(
T Function(T) function,
) {
return (value) {
return function(_trustAs(value.toDartObject)).toExternalReference;
};
}
}
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Done