15

In ES6, I was trying to use the arguments object as an iterable when passed to the Set constructor. It works fine in IE11 and in Chrome 47. It does not work in Firefox 43 (throws a TypeError: arguments is not iterable). I've looked through the ES6 spec and cannot really find a definition of whether the arguments object should be an iterable or not.

Here's an example of what I was trying to do:

function destroyer(arr) {
  var removes = new Set(arguments);
  return arr.filter(function(item) {
    return !removes.has(item);
  });
}

// remove items 2, 3, 5 from the passed in array
var result = destroyer([3, 5, 1, 2, 2], 2, 3, 5);
log(result);

FYI, I know there are various work-arounds for this code such as copying the arguments object into a real array or using rest arguments. This question is about whether the arguments object is supposed to be an iterable or not in ES6 that can be used anywhere iterables are expected.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • 2
    This is a known FF bug: [The arguments object should support the ES6 @@iterator protocol](https://bugzilla.mozilla.org/show_bug.cgi?id=1067049) – apsillers Jan 05 '16 at 15:16
  • @apsillers - And it looks like the code has already been written to fix it (last month) and it is in the process of being reviewed and tested. – jfriend00 Jan 05 '16 at 15:40

1 Answers1

9

I suppose it is a bug in FF's implementation.

As per 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) section,

If argumentsObjectNeeded is true, then

a) If strict is true or if simpleParameterList is false, then

==> i) Let ao be CreateUnmappedArgumentsObject(argumentsList).

b) Else,

==> i) NOTE mapped argument object is only provided for non-strict functions that don’t have a rest parameter, any parameter default value initializers, or any destructured parameters .

==> ii) Let ao be CreateMappedArgumentsObject(func, formals, argumentsList, env).

Both CreateMappedArgumentsObject and CreateUnmappedArgumentsObject have

Perform DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor {[[Value]]:%ArrayProto_values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}).

It means that @@iterator property should have been actually defined on the arguments object.

Community
  • 1
  • 1
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
  • And, to demonstrate definitively that it's not defined: `(function(a) { return arguments[Symbol.iterator] })(1)` produces `undefined` in FF, but a function in other browsers. – apsillers Jan 05 '16 at 15:12
  • 2
    With a better idea what to search for now, I searched for a Firefox bug report on this and found it here: [The arguments object should support the ES6 @@iterator protocol](https://bugzilla.mozilla.org/show_bug.cgi?id=1067049). It looks like it is in the process of being released (code written to fix the bug last month). – jfriend00 Jan 05 '16 at 15:19
  • Thx for the pointer to the right place in the ES6 spec. I was expecting the description of the `arguments` object to mention `@@iterator`, but it was not mentioned there at all. The spec itself appears to be more procedural than object oriented which seems slightly ironic. – jfriend00 Jan 05 '16 at 16:16
  • The bug fix is now released and it works in Firefox 46. – jfriend00 Apr 27 '16 at 17:48