3

Just realized my script doesn't work on my iphone, and found that the following line is the culprit.

return (this.currentElements[0].labels[0].textContent ?? 'This field') + " must be one of " + validValues.join(', ');

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator indicates that Safari 13.4 supports it, and I think I have 13.3. Regardless, need to resolve.

Is there a way to tell if an operator such as ?? is supported by executing JavaScript on the client? If so, I would detect and execute some alternate approach if necessary.

A little off topic, but does anyone know of a polyfill that will work with Safari and iOS?

3
  • 1
    You can just put it in try catch block Commented Dec 9, 2020 at 18:46
  • 2
    @ritaj is correct but if you do that, you need to write the code twice - once for supported environments and once for unsupported ones. You can just skip that and transpile the code with Babel. Commented Dec 9, 2020 at 18:48
  • Or you could use the latest JavaScript spec and compile to a less modern version to support the browsers you want to support. Commented Dec 9, 2020 at 18:48

3 Answers 3

3

You can try this check

const operatorSupported = eval('null??true')

but the eval will throw if ?? is not supported so function should be try...catch

const operatorSupported = (() => {
  try {
    return eval('null??true');
  } catch(err){
    return false 
  }
})();

In order to run it once, the block is wrapped into anonymous function so eval becomes a bit performant

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks uke, Tried it using app.lambdatest.com (don't have a mac), and it causes the script to crash. I tried alert(operatorSupported?'true':'false') and if I just set operatorSupported to true, I get an alert, but not if I use eval('null??true') to set it.
Hey, not familiar with lamdatest. This code returns true for browser that supports it and undefined for those who not. There could be security checks about eval, but if you host the website it should be fine
You might be right, and I tried to confirm but couldn't. I went back to lamdatest to try eval('null?true:false'), but evidently there is a six minute trial time limit and accidently used it.
Thanks, seems to work, but will likely go with imvain2 solution unless I can find a good way to implement. Thinking something like nullishCoalese('this.currentElements[0].labels[0].textContent', 'This field'); which passes both to your solution, tries to eval, and if not performs some less performa solution.
3

Instead of checking to see if the function works, you can just rewrite it so that the end result will be the same.

_content = this.currentElements[0].labels[0].textContent;

return ((_content === null || _content === undefined) ? 'This field' : _content) + " must be one of " + validValues.join(', ');

You can even have a reusable function that does the same thing:

function nullish(a,b){
  return (a === null || a === undefined) ? b : a
}

1 Comment

Thanks imvain2, While I appreciate your answer and will likely use it, it doesn't really answer the specific question. Regardless, a vote up from me.
2

How to detect operator support?

Using try/catch alone is impossible. You can try/catch expressions but not new syntax. For example this code wouldn't even parse:

const support_dollar_operator = () => {
  try {
    1 $ 2;
    return true;
  } catch (e) {
    return false;
  }
}

support_dollar_operator(); // your browser exploded before that

However it is possible with eval:

const support_dollar_operator = () => {
  try {
    eval(`1 $ 2`);
    return true;
  } catch (e) {
    return false;
  }
}

support_dollar_operator();
//=> false

Is it possible to polyfill an operator?

Yes and no.

Yes you can use a new operator with tools such as Babel but behind the scene it will rewrite your code if that operator isn't supported by your target audience. It would look like this:

// your code
bar ?? 'baz'

// transpiled
bar == undefined ? 'baz' : bar

How do you fix your issue?

You haven't posted an error message so we can't assume that your issue is caused by ?? not being supported.

This would fail even if ?? is supported:

var foo;
foo.bar ?? 'baz';
//=> ERR: Uncaught TypeError: Cannot read property 'bar' of undefined

The ?? operator isn't meant to provide a fallback if something along the path is undefined. This is the job of the ?. "optional chaining" operator:

var foo;
foo?.bar ?? 'baz';
//=> 'baz'

In your code an error could be caused if either A or B is undefined:

(this.currentElements[0].labels[0].textContent ?? 'This field')
//    ^                  ^
//    A                  B

The good news is that the ?. operator is supported in Safari on iOS

3 Comments

Thank you for your response. Maybe this could be expanded to attempt to use ?? and if it throws an exception, split by . (and deal with arrays) and recursively check each property.
@user1032531 See update. I think we need to see an error message first.
Thanks customercommander. Yes, I too want to see an error message! I get no issues on Chrome, IE, FF, etc, but do on my iPhone7. There doesn't, however, appear a way to view errors on the phone. My hack solution has been to put alert messages all over the place so I can eliminate potential culprits. I also includes pages which just a few lines of script, and it appears that ?? was the issue. If you have better ways to view errors, please advise! Regarding ?. being more appropriate, they seem close but expect you are right. PHP just has the ?? so that is why I guess I used it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.