| function shouldBe(actual, expected) { |
| if (actual !== expected) |
| throw new Error('bad value: ' + actual); |
| } |
| |
| function shouldThrow(func, errorMessage) { |
| var errorThrown = false; |
| var error = null; |
| try { |
| func(); |
| } catch (e) { |
| errorThrown = true; |
| error = e; |
| } |
| if (!errorThrown) |
| throw new Error('not thrown'); |
| if (String(error) !== errorMessage) |
| throw new Error(`bad error: ${String(error)}`); |
| } |
| |
| shouldBe(JSON.stringify(Object.getOwnPropertyDescriptor(Object, "fromEntries")), `{"writable":true,"enumerable":false,"configurable":true}`); |
| shouldBe(Object.fromEntries.length, 1); |
| |
| shouldThrow(() => Object.fromEntries(null), `TypeError: null is not an object`); |
| shouldThrow(() => Object.fromEntries(undefined), `TypeError: undefined is not an object`); |
| shouldThrow(() => Object.fromEntries(0), `TypeError: undefined is not a function`); |
| shouldThrow(() => Object.fromEntries(true), `TypeError: undefined is not a function`); |
| shouldThrow(() => Object.fromEntries(Symbol("Cocoa")), `TypeError: undefined is not a function`); |
| shouldThrow(() => Object.fromEntries("Cocoa"), `TypeError: Object.fromEntries requires the first iterable parameter yields objects`); |
| shouldThrow(() => Object.fromEntries([0]), `TypeError: Object.fromEntries requires the first iterable parameter yields objects`); |
| shouldThrow(() => Object.fromEntries([["Cocoa", "Cappuccino"], 0]), `TypeError: Object.fromEntries requires the first iterable parameter yields objects`); |
| |
| { |
| let object = Object.fromEntries([]); |
| shouldBe(JSON.stringify(object), `{}`); |
| } |
| { |
| let object = Object.fromEntries([["Cocoa", "Cappuccino"]]); |
| shouldBe(JSON.stringify(object), `{"Cocoa":"Cappuccino"}`); |
| shouldBe(JSON.stringify(Object.getOwnPropertyDescriptor(object, "Cocoa")), `{"value":"Cappuccino","writable":true,"enumerable":true,"configurable":true}`); |
| } |
| { |
| let obj = { abc: 1, def: 2, ghij: 3 }; |
| let res = Object.fromEntries( |
| Object.entries(obj) |
| .filter(([ key, val ]) => key.length === 3) |
| .map(([ key, val ]) => [ key, val * 2 ]) |
| ); |
| shouldBe(JSON.stringify(res), `{"abc":2,"def":4}`); |
| } |
| { |
| let map = new Map([ [ 'a', 1 ], [ 'b', 2 ], [ 'c', 3 ] ]); |
| let obj = Object.fromEntries(map); |
| shouldBe(JSON.stringify(obj), `{"a":1,"b":2,"c":3}`); |
| } |
| { |
| let arr = [ { name: 'Alice', age: 40 }, { name: 'Bob', age: 36 } ]; |
| let obj = Object.fromEntries(arr.map(({ name, age }) => [ name, age ])); |
| shouldBe(JSON.stringify(obj), `{"Alice":40,"Bob":36}`); |
| } |
| { |
| Object.defineProperty(Object.prototype, "bad", { |
| get() { throw new Error("out"); }, |
| set(v) { throw new Error("out"); } |
| }); |
| shouldThrow(() => { |
| let object = {}; |
| object.bad; |
| }, `Error: out`); |
| shouldThrow(() => { |
| let object = {}; |
| object.bad = 42; |
| }, `Error: out`); |
| let object = Object.fromEntries([["bad", "value"]]); |
| shouldBe(JSON.stringify(object), `{"bad":"value"}`); |
| } |
| { |
| var counter = 0; |
| class Recorder { |
| constructor(first, second) |
| { |
| this.first = first; |
| this.second = second; |
| } |
| |
| get 0() |
| { |
| shouldBe(counter++, this.first); |
| return this.first; |
| } |
| |
| get 1() |
| { |
| shouldBe(counter++, this.second); |
| return this.second; |
| } |
| } |
| var result = Object.fromEntries([new Recorder(0, 1), new Recorder(2, 3)]); |
| shouldBe(result[0], 1); |
| shouldBe(result[2], 3); |
| shouldBe(counter, 4); |
| } |
| { |
| class Iterable { |
| constructor() |
| { |
| } |
| |
| *[Symbol.iterator]() |
| { |
| yield [0, 1]; |
| yield [1, 2]; |
| } |
| } |
| |
| var result = Object.fromEntries(new Iterable); |
| shouldBe(result[0], 1); |
| shouldBe(result[1], 2); |
| } |
| { |
| class Iterator { |
| constructor() |
| { |
| this.index = 0; |
| } |
| |
| next() |
| { |
| if (this.index === 4) |
| throw new Error("out"); |
| |
| this.index++; |
| return { |
| value: [0, 1], |
| done: false |
| }; |
| } |
| } |
| |
| class Iterable { |
| constructor() |
| { |
| } |
| |
| [Symbol.iterator]() |
| { |
| return new Iterator; |
| } |
| } |
| |
| try { |
| Object.fromEntries(new Iterable); |
| } catch (error) { |
| shouldBe(String(error), `Error: out`); |
| } |
| } |
| { |
| let array = [[], ['c', 'd']]; |
| let object = Object.fromEntries(array); |
| shouldBe(JSON.stringify(Object.keys(object).sort()), `["c","undefined"]`); |
| shouldBe(object.c, 'd'); |
| shouldBe(object.undefined, undefined); |
| } |
| { |
| let symbol = Symbol('Cocoa'); |
| let array = [[symbol, 42]]; |
| let object = Object.fromEntries(array); |
| shouldBe(Object.getOwnPropertySymbols(object).length, 1); |
| shouldBe(Object.getOwnPropertyNames(object).length, 0); |
| shouldBe(object.hasOwnProperty(symbol), true); |
| shouldBe(object[symbol], 42); |
| } |
| { |
| Object.defineProperty(Object.prototype, "hello", { |
| get() { |
| throw new Error("out"); |
| }, |
| set() { |
| throw new Error("out"); |
| } |
| }); |
| let result = Object.fromEntries([["hello", 42]]); |
| shouldBe(result.hello, 42); |
| } |
| { |
| let array = [['a', 'b'], ['c', 'd']]; |
| Object.defineProperty(array, 0, { |
| get() |
| { |
| array.push(['e', 'f']); |
| return ['a', 'b']; |
| } |
| }); |
| let object = Object.fromEntries(array); |
| shouldBe(JSON.stringify(object), `{"a":"b","c":"d","e":"f"}`); |
| } |