dart-lang / web

Lightweight browser API bindings built around JS static interop.
https://pub.dev/packages/web
BSD 3-Clause "New" or "Revised" License
128 stars 22 forks source link

Feature detection #181

Open mnordine opened 7 months ago

mnordine commented 7 months ago

Let's say we have the following:

import 'package:web/web.dart';

Future<void> main() async {
  window.navigator.vibrate([400] as VibratePattern);
}

Not all browsers have vibrate() on navigator. What's the best way to detect this?

import 'dart:js_interop_unsafe';

import 'package:web/web.dart';

Future<void> main() async {
  if (window.navigator.has('vibrate')) {
    window.navigator.vibrate([400] as VibratePattern);
  }
}

?

kevmoo commented 7 months ago

We likely need to make a list of these features and add some logic to generate "checkers"

CC @srujzs

See also https://github.com/dart-lang/web/issues/175

kevmoo commented 7 months ago

@mnordine – has is a pretty good idea. We're discussing discoverability here!

ditman commented 7 months ago

I'd be happy with has in JSObject (similar to JS' in?)

srujzs commented 7 months ago

I'd be happy with has in JSObject (similar to JS' in?)

Yup, and that's what the implementation of hasProperty (and by extension, has) does.

The downside is having to use a String instead of a Dart symbol, but I don't think we can do better. One suggestion was generating a symbol for each member but that's a lot of extra code and bloats the package quite a bit. We could imagine some API that takes a member tear-off as an argument instead of a String like has, but tear-offs are disallowed and only methods can be torn-off anyways.

ditman commented 7 months ago

@srujzs can a version of has be moved to somewhere that doesn't have "unsafe" in the name? :P

srujzs commented 7 months ago

It's a good question. :) A lot of the members in dart:js_interop_unsafe exist there because getting/setting/calling arbitrary properties is potentially unsafe from a security perspective. However, querying whether an arbitrary property exists in an object is probably always okay, and therefore has and hasProperty may be able to be moved to dart:js_interop. I should verify with someone who knows more before I do that. FWIW, the library documentation says usage of the library is fine as long as strings are statically analyzable, but maybe the dart.dev documentation should make that clear too.