Javascript check yield support
Asked Answered
S

7

28

I read about the yield keyword in JavaScript and I need to use it in my project. I read that this keyword has been implemented starting from a certain version of JS so I think that old browsers don't support it (right?).

Is there a way to check if the yield keyword is supported? or at least is there a way to check if the version of JS is greater or equal than the one that implements that keyword (1.7)?

Samoyed answered 19/2, 2010 at 15:11 Comment(0)
K
33

Here's a function for checking if yield can be used.

var can_yield = (function(){ 
    try { 
        return eval("!!Function('yield true;')().next()"); 
    } 
    catch(e) { 
        return false; 
    } 
})();
Kitchenmaid answered 30/8, 2011 at 20:40 Comment(1)
ahhhh love that JavaScript :)) +1 for you!Sphygmomanometer
M
14

yield introduces new syntax to JavaScript. You won't be able to use yield unless you have specified that you want the new JavaScript syntax, by including a version number in the script type attribute(*).

When you specify a script version, only browsers that support the given version will execute the block at all. So only Firefox, and not IE, Opera or WebKit, will execute the top block in:

<script type="text/javascript;version=1.7">
    function x() {
        yield 0;
    }
    var canyield= true;
</script>
<script type="text/javascript">
    if (!window.canyield) {
        // do some fallback for other browsers
    }
</script>

(*: note that the type and version specified in the type attribute exclusively determines whether external scripts are fetched, executed, and the mode for the execution. The Content-Type of a script is, unfortunately, completely ignored.)

Myrmeco answered 19/2, 2010 at 16:9 Comment(1)
Sadly, this is unable to detect if Chrome has the Experimental JavaScript flag turned on, which enables yield in that browser as of version 31.x. Works great in Firefox though.Homeopathic
M
9

Here's my take on checking for native yield support.

var canYield = (function(){try{yield;}catch(e){}}())!==undefined;

Modernizr test

define(['Modernizr'], function( Modernizr ) {
  // native yield support.
  Modernizr.addTest('yield', (function(){try{yield;}catch(e){}}())!==undefined);
});

Performance http://jsperf.com/yield-support enter image description here enter image description here

Mothy answered 11/4, 2013 at 18:11 Comment(0)
S
6

Strictly speaking, only Mozilla Browsers support JavaScript. All browsers should support ECMAScript and older versions of JavaScript are implementations of ECMAScript.

This site lists what versions of Javascript are supported on what versions of browser.

MSIE uses JScript. JScript does not have yield in it. Therefore, using yield will limit the browser support for your page.

Try https://developer.mozilla.org/en/New_in_JavaScript_1.7 for info on using JavaScript 1.7

Sibley answered 19/2, 2010 at 15:23 Comment(2)
So there's no way to check it without browser sniffing?Samoyed
This answer is out of date now that yield support has been released for Google Chrome.Presumably
H
4

I have spent a lot of time with yield recently, and bobince isn't completely wrong, but Chrome 31 does not interpret JavaScript version to 1.7 blocks, even with the Experimental JavaScript flag turned on (chrome://flags/#enable-javascript-harmony). Due to implementation differences between Chrome 31 and Firefox, Tymon Sturgeon's method is unable to detect yield in Chrome 31 with Experimental JS on, although it is very close. With a few modifications, it can detect the existence of yield for both Firefox and Chrome 31 with Experimental JS on.

First I'll quickly cover the yield differences (writing it the long way for clarity):

In Firefox:

var fooGen = function(){ yield 1; yield 2; };
var iterator = fooGen();
console.log(iterator.next());    // prints 1
console.log(iterator.next());    // prints 2

In Chrome 31 with Experimental JavaScript enabled:

// Note the *
var fooGen = function*(){ yield 1; yield 2; };
var iterator = fooGen();
console.log(iterator.next().value);    // prints 1
console.log(iterator.next().value);    // prints 2

.value is required in Chrome because it yields an object, but more importantly, the generator requires a "*" in the function definition. Also, I could not find a way to create a generator from the capital "F" Function: new Function('', '{yield 5;}'); in Chrome. If you know how, leave a comment below.

To properly detect yield in Firefox and Chrome, I have used a bit of code with some back and forth:

<script type="application/javascript">
    var can_yield = (function(){ 
        try {
            // Assuming Chrome's generator syntax
            var funcUsingYield = new Function('', '{ var interp = function* generator(){ yield true; }}');
            return true;
        } catch(e) { 
            return false; 
        } 
    })();
</script>

<script type="application/javascript;version=1.7">
    // Redefine the `can_yield` function inside a JS1.7 block. Probably safe to simply return true
    can_yield = (function(){ 
        try { 
            return eval("!!Function('yield true;')().next()"); 
        } 
        catch(e) { 
            return false; 
        } 
    })();
</script>

<script type="application/javascript">
    if(!can_yield)
    {
        alert("Can't Yield!");
    }
</script>

Tested in:

  • Firefox 25: yield works
  • Chrome 31 with Experimental JS On: yield works
  • Chrome 31 with Experimental JS Off: yield does not work
  • and IE10: yield does not work
Homeopathic answered 25/11, 2013 at 6:25 Comment(0)
K
2

we actually implemented "yield", programmatically, in "pure javascript" i.e. WITHOUT USING FIREFOX "yield", for pyjamas, after noting that skulpt also had done likewise.

in theory, the exact same thing could be done either manually (i.e. by laboriously hand-coding a translated function by following the rules on how to turn a function into a generator) or by running javascript through a javascript-to-javascript language translator (!)

what's required to implement such a "Beast" is that you have to make the function capable of skipping up to the point where it was last "exited" (by a yield statement). thus, all variables must be stored in temporary state (!) and the code-execution altered accordingly, to accept this temporary state-info. that includes while statements, for loops as well as "if" statements.

it can be done...

... but it's just a bitch of a job: you need, effectively to write an entire compiler that parses any javascript program, then "transforms" it, and then outputs the modified javascript.

l.

Khajeh answered 4/10, 2011 at 20:39 Comment(1)
that's how C# does itFishworm
D
1

whell, actually there are some techniques you can use, but I doubt such techniques have any real value

(function test_key_word(keyword){
var wrong = false;
try {
    eval(keyword + "=42");
} 
catch(e) {
    wrong = true;
} finally {
    if (wrong) { return "definitely wrong" }
    else 
    if (window[keyword] !== 42) {
        return "very probably, wrong"
    }
    else {
        return "can be acceptable, but nevertheless i wouldn't rely upon such tests"
    }
}})("in")
Dumpcart answered 29/3, 2011 at 10:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.