Access to Map values in Safari 7.1+
Asked Answered
V

2

6

Safari has support for ES6 Maps and Sets in version 7.1 and higher (MDN). I'm using a Map in my application and at some point want access to the values. Calling the values() function on the map seems like the way to go and returns an Iterator. By calling next() on the returned Iterator, one should be able to iterate over the values. This works fine in Chrome, but Safari does something strange. It returns a Map Iterator when calling values(), but the returned iterator has no next() function.

m = new Map();
m.set(1, "test");
m.set("2", false);
it = m.values(); // returns Map Iterator
it.next(); // TypeError: undefined is not a function

Am I missing something obvious, or is the Safari implementation only partial? Is there another way to get access to the values? Using the for..of construct is not an option because this is new syntax and is not supported in older browsers (for which I use the es6-collections shim).

Verbid answered 16/4, 2015 at 8:54 Comment(2)
If it really is how you describe, then that's a bug.Celom
Yes, this is a bug in Safari (7.1/8): github.com/paulmillr/es6-shim/issues/326Subantarctic
V
0

This indeed seems to be a bug with Safari 7.1 and 8. I managed to work around this issue by first checking if the next function was available and if not, I used the for...of construct. Because this is invalid syntax pre-ES6, I had to wrap it in an eval statement:

m = new Map();
m.set(1, "test");
m.set("2", false);
it = m.values(); // returns an Iterator
if (typeof it.next === 'function') {
    v = it.next();
    // do something with v here
} else {
    eval("for (v of iterator) /* do something with v here */");
}
Verbid answered 20/4, 2015 at 12:22 Comment(3)
" Because this is invalid syntax pre-ES6, I had to wrap it in an eval statement" That doesn't seem to make sense. If the engine doesn't understand for/of, using eval instead won't make a difference. It seems to me that the linter you may be using doesn't understand ES6, which is a separate problem.Celom
@FelixKling It does make a difference. The for/of case only gets executed in Safari 7.1/8 which does support it. The other browsers make use of a polyfill that has a working iterator. I can't put the for/of in plain code because other browsers would complain about the invalid syntax and do nothing at all.Verbid
I see. Still. Using eval here is not a clean solution. I would probably use a library that polyfills the non-standard behavior. Core-js claims it does, but I haven't tested it in Safari.Celom
S
0

In my case, I was using toArray on the values returned which was failing in Safari.

I found out that Safari is still (~10 years later) lagging behind in support for Iterators. It seems like they've just started adding some of the helper functions: https://github.com/WebKit/WebKit/pull/27865

Spelter answered 16/10 at 1:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.