Skip to content

Instantly share code, notes, and snippets.

@wingo
Created September 26, 2013 10:36
Show Gist options
  • Save wingo/6712480 to your computer and use it in GitHub Desktop.
Save wingo/6712480 to your computer and use it in GitHub Desktop.
// Assuming that for-of and proxies are available, this function will detect the
// version of for-of being used, and bind the std_iterator object.
//
// The return value will be one of:
//
// * 'old-spidermonkey' for currently deployed spidermonkey. This code will call
// y.iterator() on "for (x of y) ...", then call "next" on that iterator to yield
// values until next() throws StopIteration. When control exits the loop,
// .close() is called on the iterator.
//
// * 'old-v8' for currently deployed v8 --harmony. This is like ES6, except that
// the RHS is expected to already be an iterator. This V8 doesn't call @@iterator
// on the RHS.
//
// * 'es6' for ES6 as currently specified (2013-09-05 draft). This will call the
// @@iterator method on the right-hand-side (RHS) of the for-of to produce an
// iterator from an iterable. Then next() will be called on that iterator, which
// is expected to return objects of the form {value: foo, done: bool}. If done is
// false, foo will be bound to the iteration variable and the body will be
// executed, and loop back. When done is true, the loop exits. Unlike
// old-spidermonkey, .close() is never called on the iterator.
//
// The exact spelling of @@iterator is an issue. It is specified to be a symbol in
// the std::iteration module, but no currently deployed engine implements ES6
// modules, and SM doesn't implement symbols. So instead SpiderMonkey will use some
// placeholder string, but the precise spelling of that string should not be relied
// on by an application. This code assumes that any key passed to the get handler
// of a proxy that is not 'iterator' or 'next' is actually the @@iterator symbol.
//
var std_iterator;
function DetectForOfKind() {
try {
for (var x of Proxy.create({get: function(obj, name) {
switch (name) {
case 'iterator': throw 'old-spidermonkey';
case 'next': throw 'old-v8';
default: std_iterator = name; throw 'es6';
}
}}))
break;
throw 'error';
} catch (e) {
return e;
}
}
var for_of_kind = DetectForOfKind();
@wingo
Copy link
Author

wingo commented Sep 27, 2013

For the record, though we already chatted elsewhere: yep :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment