-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a dart:js_interop
API that can determine if an Object
is a JS value
#56905
Comments
dart:js_interop
API that can determine if a Object
is a JS value dart:js_interop
API that can determine if an Object
is a JS value
Any update on this? |
We urgently need something like the extension below, with official support for each platform: extension ObjectToJSAnyNullableExtension on Object? {
bool get isJSAny;
bool get isJSObject;
} NOTE: After discussing this issue with other developers, we concluded that, without a secure way to cast |
@srujzs is the expert here. I will make sure we follow-up this week. |
Thanks for the quick response |
I want to get this done before the next stable, for both the JS compilers and dart2wasm. I don't believe we need |
I agree that It also provides an opportunity for an optimized implementation of Therefore, it is much easier to implement I have internally implemented a |
FYI: @srujzs I have published the package js_interop_utils, which includes a temporary implementation of
This might help clarify the issues involved in implementing an official version. |
What is the intended use-case for this API? When compiled to JavaScript, all values are JavaScript values, so it sounds like the function of really asking On Wasm, there are Dart types representing and containing JS values, so it can easily check if a value is one of those. Is that the intended behavior? Can you trust that if |
When working on a real-world project, it’s very common to have a DOM element passed through an Once you have an Without a safe way to cast an |
You can take a look at the https://github.com/gmpassos/js_interop_utils/blob/master/lib/src/js_interop_utils_extensions.dart https://github.com/gmpassos/web_utils/blob/master/lib/src/web_utils_extensions.dart |
I can see how, from an implementation perspective, re: your implementations, returning
This is more or less what I intend for this s/JSValue/JSAny. If yes, cast to Object o;
if (o.isJSAny) {
if (o.isA<JSString>()) {
...
} else if (o.isA<JSNumber>()) {
...
}
...
} else {
if (o is String) {
...
} else if (o is num) {
...
}
} In this case, the |
I wasn’t expecting to have ambiguous cases with “true”, as all primitives will be treated as JS values depending on the platform. It can be complicated to include all String, num, and bool types as JSAny, if they can be treated as normal Dart types. I vote for “true” to not include ambiguous cases. Do not forget that the user, as a developer, will write !isJSAny and isJSAny if you don’t return null for ambiguous states. In other words, if you can only trust “true,” then !"false" does not have the same meaning, as false can also represent ambiguity. IMHO, if ambiguous states are possible, the function can only have two implementations:
You cannot return a false that may also indicate an ambiguous state, as this would lead to misuse of the function. But yes, an isXYZ getter that can return null is an unusual choice for an API. |
Note: I was hoping that we wouldn’t have ambiguous cases/detections in the official implementation. However, due to the internal implementation for JS or Wasm, it might be necessary. This is why isJSObject is also interesting: it doesn’t have ambiguous detections, so we can always trust its return value. |
I'd go for returning true if It does mean that primitives in JS code will return true, but likely instances of Dart classes, records and maybe functions will be recognized. It's not wrong, primitives can be cast to On Warm it's just There are objects that are unambiguously Dart values, and objects that are definitely not, and then there might be values which can be either, and the only answer that is useful there is whether Telling people that it could be either isn't helping them. |
I agree with you. After thinking more about it, a core function that returns true|false|null is not a good idea. Developers are not accustomed to handling this kind of pattern and may use it incorrectly. I think a good solution is to have With |
Historically, it was common for users to treat JS values through interop as Dart types and not JS types, mainly because the concept of "JS types" did not exist yet. So, values may flow through as
Object
ordynamic
to other parts of code. This code may accept both a Dart and a JS value, making it difficult to determine how to treat such a value without some way of distinguishing the two runtimes.The canonical way to type-check Dart objects is to use
is
, but we don't want users using that if it's a JS value, as it may give inconsistent values. This is partially why we have theinvalid_runtime_check_with_js_interop_types
lint.The canonical way to type-check JS values is to use
isA
, but that requires a cast toJSAny
in the first place. This cast will always succeed when compiling to JS (because it'sObject
under-the-hood there), but may fail when compiling to Wasm (because it'sJSValue
). This is our best option today.So, to determine how to type-check a given
Object
, it is useful to know whether it's a JS value in the first place. One such mechanism is a compiler-specificexternal
patched API indart:js_interop
.Some quirks that we might come across:
String
,int
/double
/num
,bool
) are both Dart and JS values when compiling to JS. This is not true when compiling to Wasm. We may want to always treat them as JS values for the sake of this API, but users should be aware that they should still type-check for the Dart primitive types when this API returns false so that they handle the Wasm case correctly.invalid_runtime_check_with_js_interop_types
check to account for this new API e.g. pointing users to this API when they do ais JSAny
check.The text was updated successfully, but these errors were encountered: