Skip to content
Snippets Groups Projects
Commit 5cb1ba27 authored by Mike Pennisi's avatar Mike Pennisi
Browse files

Add tests for Array.from

Limit tests to behavior of method when invoked with an iterable.
parent 741b7992
No related branches found
No related tags found
No related merge requests found
Showing
with 647 additions and 0 deletions
// 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);
});
// 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);
});
// 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);
});
// 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');
// 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);
});
// 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);
});
// 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');
// 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);
// 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);
// 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');
// 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');
// 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');
// 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);
// 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);
// 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);
});
// 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);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment