We have had a number of conversations about extensibility. The spec supports payment method-specific data, for example. And we have discussed a companion spec about JSON-LD extensibility.
We expect to add features to future versions of the API. How will the API support feature detection? What are the individual features we will label in this version?
The nature of the way specs like this are engineered into products means that features tend to be added incrementally. It is necessary that we consider each feature addition/change on its own to make sure it can be featured detected. We don't need to have an issue open to consider this; feature detection patterns are well-known to web developers.
Recommend closing this issue.
What is the feature detection pattern that the browser API uses? I'm fine with closing one as long as we know which one we think we're going to use.
My understanding is that feature detection would be done by inspecting the type system.
Ian
If this is true, can we get that text into the spec? Perhaps a section on feature detection?
Is that necessary? My understanding is that JS developers may know how to do this; e.g., I found this in the wikipedia:
https://en.wikipedia.org/wiki/Feature_detection_(web_development)
Ian
How does one understand how to see if billing address is supported on a payment request using the link above? Note that I'm just plucking that one feature out of thin air, you could ask the same question for each capability in the payment request API.
I will leave to those who know these things more than I do to show code.
Ian
I will leave to those who know these things more than I do to show code.
And until that is done, and there is some spec text outlining a general approach to addressing this problem, we should keep the issue open.
@ianbjacobs is correct.
Stand to be corrected by @adrianba , @rsolomakhin or @adamroach but my assumption is that code like the following would be used.
How to do this is not something I'd expect in the spec, this is a generic feature detection technique.
if(PaymentOptions.requestShipping) //Check if get Shipping address feature is present
if(PaymentOptions.requestPayerEmail) //Check if get email feature is present
if(PaymentOptions.requestPayerPhone) //Check if get phone feature is present
@adrianba and @adamroach: does if (PaymentOptions.requestShipping) work in Edge and Firefox? It seems to be not working in Chrome, because PaymentOptions is a dictionary, not an interface. I wonder if this is a bug in Chrome that I need to fix or _all_ browsers behave the same.
No, you can't feature detect against dictionaries but you can/should against interfaces. This is general best practice for web APIs.
So you can test against for the shippingAddress attribute of PaymentRequest or the payerEmail attribute of PaymentResponse.
Thanks @adrianba and @rsolomakhin
@msporny, if there are any features you feel can't be easily detected via presence of an interface member please log an issue specific to that feature so we can discuss a way to address that.
So you can test against for the shippingAddress attribute of PaymentRequest
Can you give us a code example of checking for this on PaymentRequest @adrianba? I think you're saying we need to instantiate a payment request before we can feature detect?
Another way to address this is to copy the pattern employed by getUserMedia() for constraints (which are passed as a dictionary): we could define a dictionary (e.g. PaymentOptionsSupportedUserData) that contains a key for each kind of data that is supported by the browser implementation. See MediaDevices.getSupportedConstraints() and MediaTrackSupportedConstraints for an example of how this works.
Something like
if(PaymentRequest.prototype.hasOwnProperty("shippingAddress")) {
// shipping address is supported
}
You don't need to create an instance.
The problem with having supports() methods is that they often don't provide the right granularity or web developers make mistakes that proliferate, which causes implementations to have to lie about support. We've seen this with such methods before.
@adrianba --
The problem with having
supports()methods is that they often don't provide the right granularity or web developers make mistakes that proliferate, which causes implementations to have to lie about support. We've seen this with such methods before.
I agree in the _general_ case, where the binding between feature names and specific function calls is only defined via specification, that this is true. When you're trying to figure out whether you can include a value in a dictionary and have it honored, using a dictionary with exact key names is 100% unambiguous. By contrast, what you're proposing -- using the presence of a member on a structure to infer the validity of a differently-name dictionary key on another -- actually has the same kind of problem that you're highlighting with supports() methods: developers have to make somewhat oblique inferences rather than having something that can be determined programmatically.
To be clear, what I'm proposing would end up looking like:
if(PaymentOptions.getSupportedOptions()['requestShipping']){
// can use 'requestShipping' in the dictionary
}
...as contrasted with:
if(PaymentRequest.prototype.hasOwnProperty("shippingAddress")){
// can use 'requestShipping' in the dictionary
}
So you can see how one of these has a straight line (e.g., requestShipping -> requestShipping) while the other has an inference (e.g. shippingAddress -> requestShipping)
Most helpful comment
To be clear, what I'm proposing would end up looking like:
...as contrasted with:
So you can see how one of these has a straight line (e.g., requestShipping -> requestShipping) while the other has an inference (e.g. shippingAddress -> requestShipping)