Add tests for Array.from

Limit tests to behavior of method when invoked with an iterable.
This commit is contained in:
Mike Pennisi 2015-07-15 18:45:38 -04:00
parent 741b799286
commit 5cb1ba27d3
16 changed files with 647 additions and 0 deletions

View File

@ -0,0 +1,22 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 22.1.2.1
description: Error accessing items' `Symbol.iterator` attribute
info: >
[...]
4. Let usingIterator be GetMethod(items, @@iterator).
5. ReturnIfAbrupt(usingIterator).
features: [Symbol.iterator]
---*/
var items = {};
Object.defineProperty(items, Symbol.iterator, {
get: function() {
throw new Test262Error();
}
});
assert.throws(Test262Error, function() {
Array.from(items);
});

View File

@ -0,0 +1,28 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 22.1.2.1
description: Error advancing iterator
info: >
[...]
6. If usingIterator is not undefined, then
[...]
g. Repeat
i. Let Pk be ToString(k).
ii. Let next be IteratorStep(iterator).
iii. ReturnIfAbrupt(next).
features: [Symbol.iterator]
---*/
var items = {};
items[Symbol.iterator] = function() {
return {
next: function() {
throw new Test262Error();
}
};
};
assert.throws(Test262Error, function() {
Array.from(items);
});

View File

@ -0,0 +1,26 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 22.1.2.1
description: >
Error creating object with custom constructor (traversed via iterator)
info: >
[...]
6. If usingIterator is not undefined, then
a. If IsConstructor(C) is true, then
i. Let A be Construct(C).
b. Else,
i. Let A be ArrayCreate(0).
c. ReturnIfAbrupt(A).
features: [Symbol.iterator]
---*/
var C = function() {
throw new Test262Error();
};
var items = {};
items[Symbol.iterator] = function() {};
assert.throws(Test262Error, function() {
Array.from.call(C, items);
});

View File

@ -0,0 +1,46 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 22.1.2.1
description: Creating object with custom constructor (traversed via iterator)
info: >
[...]
6. If usingIterator is not undefined, then
a. If IsConstructor(C) is true, then
i. Let A be Construct(C).
b. Else,
i. Let A be ArrayCreate(0).
c. ReturnIfAbrupt(A).
features: [Symbol.iterator]
---*/
var thisVal, args;
var callCount = 0;
var C = function() {
thisVal = this;
args = arguments;
callCount += 1;
};
var result;
var items = {};
items[Symbol.iterator] = function() {
return {
next: function() {
return { done: true };
}
};
};
result = Array.from.call(C, items);
assert(
result instanceof C, 'Constructed value is an instance of the constructor'
);
assert.sameValue(
result.constructor,
C,
'Constructed value correctly defines a `constructor` property'
);
assert.sameValue(callCount, 1, 'Constructor invoked exactly once');
assert.sameValue(thisVal, result, 'Constructed value is returned');
assert.sameValue(args.length, 0, 'Constructor invoked without arguments');

View File

@ -0,0 +1,22 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 22.1.2.1
description: Error creating iterator object
info: >
[...]
6. If usingIterator is not undefined, then
[...]
d. Let iterator be GetIterator(items, usingIterator).
e. ReturnIfAbrupt(iterator).
features: [Symbol.iterator]
---*/
var items = {};
items[Symbol.iterator] = function() {
throw new Test262Error();
};
assert.throws(Test262Error, function() {
Array.from(items);
});

View File

@ -0,0 +1,34 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 22.1.2.1
description: Error retrieving value of iterator result
info: >
[...]
6. If usingIterator is not undefined, then
[...]
g. Repeat
[...]
v. Let nextValue be IteratorValue(next).
vi. ReturnIfAbrupt(nextValue).
features: [Symbol.iterator]
---*/
var items = {};
var poisonedValue = {};
Object.defineProperty(poisonedValue, 'value', {
get: function() {
throw new Test262Error();
}
});
items[Symbol.iterator] = function() {
return {
next: function() {
return poisonedValue;
}
};
};
assert.throws(Test262Error, function() {
Array.from(items);
});

View File

@ -0,0 +1,63 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 22.1.2.1
description: >
Arguments of mapping function (traversed via iterator)
info: >
[...]
2. If mapfn is undefined, let mapping be false.
3. else
a. If IsCallable(mapfn) is false, throw a TypeError exception.
b. If thisArg was supplied, let T be thisArg; else let T be undefined.
c. Let mapping be true
[...]
6. If usingIterator is not undefined, then
[...]
g. Repeat
[...]
vii. If mapping is true, then
1. Let mappedValue be Call(mapfn, T, «nextValue, k»).
2. If mappedValue is an abrupt completion, return
IteratorClose(iterator, mappedValue).
3. Let mappedValue be mappedValue.[[value]].
features: [Symbol.iterator]
---*/
var args = [];
var firstResult = { done: false, value: {} };
var secondResult = { done: false, value: {} };
var mapFn = function(value, idx) {
args.push(arguments);
};
var items = {};
var nextResult = firstResult;
var nextNextResult = secondResult;
items[Symbol.iterator] = function() {
return {
next: function() {
var result = nextResult;
nextResult = nextNextResult;
nextNextResult = { done: true };
return result;
}
};
};
Array.from(items, mapFn);
assert.sameValue(args.length, 2, 'Iteration count');
assert.sameValue(args[0].length, 2, 'First iteration: arguments length');
assert.sameValue(
args[0][0], firstResult.value, 'First iteration: first argument'
);
assert.sameValue(args[0][1], 0, 'First iteration: second argument');
assert.sameValue(args[1].length, 2, 'Second iteration: arguments length');
assert.sameValue(
args[1][0], secondResult.value, 'Second iteration: first argument'
);
assert.sameValue(args[1][1], 1, 'Second iteration: second argument');

View File

@ -0,0 +1,41 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 22.1.2.1
description: Error invoking map function (traversed via iterator)
info: >
[...]
6. If usingIterator is not undefined, then
[...]
g. Repeat
[...]
vii. If mapping is true, then
1. Let mappedValue be Call(mapfn, T, «nextValue, k»).
2. If mappedValue is an abrupt completion, return
IteratorClose(iterator, mappedValue).
features: [Symbol.iterator]
---*/
var closeCount = 0;
var mapFn = function() {
throw new Test262Error();
};
var items = {};
items[Symbol.iterator] = function() {
return {
return: function() {
closeCount += 1;
},
next: function() {
return {
done: false
};
}
};
};
assert.throws(Test262Error, function() {
Array.from(items, mapFn);
});
assert.sameValue(closeCount, 1);

View File

@ -0,0 +1,58 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 22.1.2.1
description: Value returned by mapping function (traversed via iterator)
info: >
[...]
2. If mapfn is undefined, let mapping be false.
3. else
a. If IsCallable(mapfn) is false, throw a TypeError exception.
b. If thisArg was supplied, let T be thisArg; else let T be undefined.
c. Let mapping be true
[...]
6. If usingIterator is not undefined, then
[...]
g. Repeat
[...]
vii. If mapping is true, then
1. Let mappedValue be Call(mapfn, T, «nextValue, k»).
2. If mappedValue is an abrupt completion, return
IteratorClose(iterator, mappedValue).
3. Let mappedValue be mappedValue.[[value]].
features: [Symbol.iterator]
---*/
var thisVals = [];
var nextResult = { done: false, value: {} };
var nextNextResult = { done: false, value: {} };
var firstReturnVal = {};
var secondReturnVal = {};
var mapFn = function(value, idx) {
var returnVal = nextReturnVal;
nextReturnVal = nextNextReturnVal;
nextNextReturnVal = null;
return returnVal;
};
var nextReturnVal = firstReturnVal;
var nextNextReturnVal = secondReturnVal;
var items = {};
var result;
items[Symbol.iterator] = function() {
return {
next: function() {
var result = nextResult;
nextResult = nextNextResult;
nextNextResult = { done: true };
return result;
}
};
};
result = Array.from(items, mapFn);
assert.sameValue(result.length, 2);
assert.sameValue(result[0], firstReturnVal);
assert.sameValue(result[1], secondReturnVal);

View File

@ -0,0 +1,49 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 22.1.2.1
description: >
`this` value of mapping function with custom `this` argument (traversed via iterator)
info: >
[...]
2. If mapfn is undefined, let mapping be false.
3. else
a. If IsCallable(mapfn) is false, throw a TypeError exception.
b. If thisArg was supplied, let T be thisArg; else let T be undefined.
c. Let mapping be true
[...]
6. If usingIterator is not undefined, then
[...]
g. Repeat
[...]
vii. If mapping is true, then
1. Let mappedValue be Call(mapfn, T, «nextValue, k»).
features: [Symbol.iterator]
---*/
var thisVals = [];
var nextResult = { done: false, value: {} };
var nextNextResult = { done: false, value: {} };
var mapFn = function() {
thisVals.push(this);
};
var items = {};
var thisVal = {};
items[Symbol.iterator] = function() {
return {
next: function() {
var result = nextResult;
nextResult = nextNextResult;
nextNextResult = { done: true };
return result;
}
};
};
Array.from(items, mapFn, thisVal);
assert.sameValue(thisVals.length, 2);
assert.sameValue(thisVals[0], thisVal, 'First iteration `this` value');
assert.sameValue(thisVals[1], thisVal, 'Second iteration `this` value');

View File

@ -0,0 +1,50 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 22.1.2.1
description: >
`this` value of mapping function in non-strict mode (traversed via iterator)
info: >
[...]
2. If mapfn is undefined, let mapping be false.
3. else
a. If IsCallable(mapfn) is false, throw a TypeError exception.
b. If thisArg was supplied, let T be thisArg; else let T be undefined.
c. Let mapping be true
[...]
6. If usingIterator is not undefined, then
[...]
g. Repeat
[...]
vii. If mapping is true, then
1. Let mappedValue be Call(mapfn, T, «nextValue, k»).
features: [Symbol.iterator]
flags: [noStrict]
---*/
var thisVals = [];
var nextResult = { done: false, value: {} };
var nextNextResult = { done: false, value: {} };
var mapFn = function() {
thisVals.push(this);
};
var items = {};
var global = function() { return this; }();
items[Symbol.iterator] = function() {
return {
next: function() {
var result = nextResult;
nextResult = nextNextResult;
nextNextResult = { done: true };
return result;
}
};
};
Array.from(items, mapFn);
assert.sameValue(thisVals.length, 2);
assert.sameValue(thisVals[0], global, 'First iteration `this` value');
assert.sameValue(thisVals[1], global, 'Second iteration `this` value');

View File

@ -0,0 +1,49 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 22.1.2.1
description: >
`this` value of mapping function in strict mode (traversed via iterator)
info: >
[...]
2. If mapfn is undefined, let mapping be false.
3. else
a. If IsCallable(mapfn) is false, throw a TypeError exception.
b. If thisArg was supplied, let T be thisArg; else let T be undefined.
c. Let mapping be true
[...]
6. If usingIterator is not undefined, then
[...]
g. Repeat
[...]
vii. If mapping is true, then
1. Let mappedValue be Call(mapfn, T, «nextValue, k»).
features: [Symbol.iterator]
flags: [onlyStrict]
---*/
var thisVals = [];
var nextResult = { done: false, value: {} };
var nextNextResult = { done: false, value: {} };
var mapFn = function() {
thisVals.push(this);
};
var items = {};
items[Symbol.iterator] = function() {
return {
next: function() {
var result = nextResult;
nextResult = nextNextResult;
nextNextResult = { done: true };
return result;
}
};
};
Array.from(items, mapFn);
assert.sameValue(thisVals.length, 2);
assert.sameValue(thisVals[0], undefined, 'First iteration `this` value');
assert.sameValue(thisVals[1], undefined, 'Second iteration `this` value');

View File

@ -0,0 +1,45 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 22.1.2.1
description: Error setting property on result value (traversed via iterator)
info: >
[...]
6. If usingIterator is not undefined, then
[...]
g. Repeat
[...]
ix. Let defineStatus be CreateDataPropertyOrThrow(A, Pk,
mappedValue).
x. If defineStatus is an abrupt completion, return
IteratorClose(iterator, defineStatus).
features: [Symbol.iterator]
---*/
var C = function() {
Object.defineProperty(this, '0', { configurable: false });
};
var closeCount = 0;
var items = {};
var nextResult = { done: false };
items[Symbol.iterator] = function() {
return {
return: function() {
closeCount += 1;
},
next: function() {
var result = nextResult;
nextResult = { done: true };
return result;
}
};
};
assert.throws(TypeError, function() {
Array.from.call(C, items);
});
assert.sameValue(closeCount, 1);

View File

@ -0,0 +1,41 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 22.1.2.1
description: Setting property on result value (traversed via iterator)
info: >
[...]
6. If usingIterator is not undefined, then
[...]
g. Repeat
[...]
ix. Let defineStatus be CreateDataPropertyOrThrow(A, Pk,
mappedValue).
features: [Symbol.iterator]
---*/
var items = {};
var firstIterResult = { done: false, value: {} };
var secondIterResult = { done: false, value: {} };
var thirdIterResult = { done: true, value: {} };
var nextIterResult = firstIterResult;
var nextNextIterResult = secondIterResult;
var result;
items[Symbol.iterator] = function() {
return {
next: function() {
var result = nextIterResult;
nextIterResult = nextNextIterResult;
nextNextIterResult = thirdIterResult;
return result;
}
};
};
result = Array.from(items);
assert.sameValue(result[0], firstIterResult.value);
assert.sameValue(result[1], secondIterResult.value);

View File

@ -0,0 +1,33 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 22.1.2.1
description: Error setting length of object (traversed via iterator)
info: >
[...]
6. If usingIterator is not undefined, then
[...]
g. Repeat
[...]
iv. If next is false, then
1. Let setStatus be Set(A, "length", k, true).
2. ReturnIfAbrupt(setStatus).
features: [Symbol.iterator]
---*/
var C = function() {};
var items = {};
Object.defineProperty(C.prototype, 'length', {
set: function(_) {
throw new Test262Error();
}
});
items[Symbol.iterator] = function() {
return {
next: function() { return { done: true }; }
};
};
assert.throws(Test262Error, function() {
Array.from.call(C, items);
});

View File

@ -0,0 +1,40 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 22.1.2.1
description: Setting length of object (traversed via iterator)
info: >
[...]
6. If usingIterator is not undefined, then
[...]
g. Repeat
[...]
iv. If next is false, then
1. Let setStatus be Set(A, "length", k, true).
2. ReturnIfAbrupt(setStatus).
3. Return A.
features: [Symbol.iterator]
---*/
var items = {};
var result, nextIterResult, lastIterResult;
items[Symbol.iterator] = function() {
return {
next: function() {
var result = nextIterResult;
nextIterResult = lastIterResult;
return result;
}
};
};
nextIterResult = lastIterResult = { done: true };
result = Array.from(items);
assert.sameValue(result.length, 0);
nextIterResult = { done: false };
lastIterResult = { done: true };
result = Array.from(items);
assert.sameValue(result.length, 1);