Something went wrong. Try again.
javascript for 🐜's, a tiny runtime with big ambitions antjs.org
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269import { test, testDeep, testThrows, summary } from './helpers.js';
console.log('Object Tests\n');
let obj = { a: 1, b: 2, c: 3 };test('object property access', obj.a, 1);test('object bracket access', obj['b'], 2);test('object property count', Object.keys(obj).length, 3);
obj.d = 4;test('add property', obj.d, 4);
obj.a = 10;test('modify property', obj.a, 10);
delete obj.d;test('delete property', obj.d, undefined);
test('in operator true', 'a' in obj, true);test('in operator false', 'z' in obj, false);
testDeep('Object.keys', Object.keys({ x: 1, y: 2 }), ['x', 'y']);testDeep('Object.values', Object.values({ x: 1, y: 2 }), [1, 2]);testDeep('Object.entries', Object.entries({ x: 1 }), [['x', 1]]);
let merged = Object.assign({}, { a: 1 }, { b: 2 });test('Object.assign a', merged.a, 1);test('Object.assign b', merged.b, 2);
let assignGetterCalls = 0;const assignGetterSource = {};Object.defineProperty(assignGetterSource, 'Module', { enumerable: true, get() { assignGetterCalls++; return function fn() {}; }});const assignGetterTarget = Object.assign({}, assignGetterSource);test('Object.assign copies getter value', typeof assignGetterTarget.Module, 'function');test('Object.assign calls getter once', assignGetterCalls, 1);
const ordered = { 2: true, 0: true, 1: true, ' ': true, 9: true, D: true, B: true, '-1': true};ordered.A = true;ordered[3] = true;'EFGHIJKLMNOPQRSTUVWXYZ'.split('').forEach(key => ordered[key] = true);Object.defineProperty(ordered, 'C', { value: true, enumerable: true });Object.defineProperty(ordered, '4', { value: true, enumerable: true });delete ordered[2];ordered[2] = true;
test('Object.getOwnPropertyNames order', Object.getOwnPropertyNames(ordered).join(''), '012349 DB-1AEFGHIJKLMNOPQRSTUVWXYZC');
const overflowNameOrder = { a: 1 };overflowNameOrder['18446744073709551616'] = 2;test('Object.getOwnPropertyNames overflow-like key order', Object.getOwnPropertyNames(overflowNameOrder).join('|'), 'a|18446744073709551616');
let assignOrder = '';const assignTarget = {};'012349 DBACEFGHIJKLMNOPQRST'.split('').concat(-1).forEach(key => { Object.defineProperty(assignTarget, key, { set() { assignOrder += key; } });});const assignSource = { 2: 2, 0: 0, 1: 1, ' ': ' ', 9: 9, D: 'D', B: 'B', '-1': '-1' };Object.defineProperty(assignSource, 'A', { value: 'A', enumerable: true });Object.defineProperty(assignSource, '3', { value: '3', enumerable: true });Object.defineProperty(assignSource, 'C', { value: 'C', enumerable: true });Object.defineProperty(assignSource, '4', { value: '4', enumerable: true });delete assignSource[2];assignSource[2] = true;'EFGHIJKLMNOPQRST'.split('').forEach(key => assignSource[key] = key);Object.assign(assignTarget, assignSource);test('Object.assign property order', assignOrder, '012349 DB-1ACEFGHIJKLMNOPQRST');
const assignedArray = Object.assign({}, [10, 20]);test('Object.assign dense array source 0', assignedArray[0], 10);test('Object.assign dense array source 1', assignedArray[1], 20);
const sparseArraySource = [];Object.defineProperty(sparseArraySource, '2', { value: 2, enumerable: true });const assignedSparseArray = Object.assign({}, sparseArraySource);test('Object.assign sparse array source index', assignedSparseArray[2], 2);
let overflowAssignOrder = '';const overflowAssignTarget = {};Object.defineProperty(overflowAssignTarget, 'a', { set() { overflowAssignOrder += 'a'; } });Object.defineProperty(overflowAssignTarget, '18446744073709551616', { set() { overflowAssignOrder += 'h'; }});const overflowAssignSource = { a: 1 };overflowAssignSource['18446744073709551616'] = 2;Object.assign(overflowAssignTarget, overflowAssignSource);test('Object.assign overflow-like key order', overflowAssignOrder, 'ah');
let nested = { a: { b: { c: 1 } } };test('nested access', nested.a.b.c, 1);
let computed = { ['key' + 1]: 'value' };test('computed property', computed.key1, 'value');
let short = 'hello';let shorthand = { short };test('shorthand property', shorthand.short, 'hello');
let methodObj = { value: 42, getValue() { return this.value; }};test('method shorthand', methodObj.getValue(), 42);
let source = { a: 1, b: 2 };let spread = { ...source, c: 3 };test('spread a', spread.a, 1);test('spread c', spread.c, 3);
let { a, b } = { a: 1, b: 2, c: 3 };test('destructuring a', a, 1);test('destructuring b', b, 2);
let { x: renamed } = { x: 5 };test('destructuring rename', renamed, 5);
let { y = 10 } = {};test('destructuring default', y, 10);
test('hasOwnProperty true', { a: 1 }.hasOwnProperty('a'), true);test('hasOwnProperty false', { a: 1 }.hasOwnProperty('b'), false);test('string primitive has own index', 'xy'.hasOwnProperty('0'), true);test('string primitive has own length', 'xy'.hasOwnProperty('length'), true);test('Object.hasOwn string primitive index', Object.hasOwn('xy', '1'), true);test('boxed string has own index', Object('xy').hasOwnProperty('0'), true);
let stringIndexDesc = Object.getOwnPropertyDescriptor('xy', '0');test('string index descriptor value', stringIndexDesc.value, 'x');test('string index descriptor writable', stringIndexDesc.writable, false);test('string index descriptor enumerable', stringIndexDesc.enumerable, true);test('string index descriptor configurable', stringIndexDesc.configurable, false);
let stringLengthDesc = Object.getOwnPropertyDescriptor(Object('xy'), 'length');test('string length descriptor value', stringLengthDesc.value, 2);test('string length descriptor enumerable', stringLengthDesc.enumerable, false);testDeep('Object.keys boxed string', Object.keys(Object('xy')), ['0', '1']);testDeep('Object.getOwnPropertyNames boxed string', Object.getOwnPropertyNames(Object('xy')), ['0', '1', 'length']);
let frozen = Object.freeze({ a: 1 });test('Object.isFrozen', Object.isFrozen(frozen), true);
let sealed = Object.seal({ a: 1 });test('Object.isSealed', Object.isSealed(sealed), true);
let proto = { inherited: true };let child = Object.create(proto);test('Object.create inherits', child.inherited, true);
test('Object.getPrototypeOf', Object.getPrototypeOf([]) === Array.prototype, true);
testDeep( 'Object.fromEntries', Object.fromEntries([ ['a', 1], ['b', 2] ]), { a: 1, b: 2 });
test( 'Object.fromEntries preserves native function identity under an alias', Object.fromEntries([['alias', Math.max]]).alias === Math.max, true);test( 'Object.fromEntries does not rename an aliased native function', Object.fromEntries([['alias', Math.max]]).alias.name, Math.max.name);test( 'Object.fromEntries aliases of one native function match each other', Object.fromEntries([['a', Array.prototype.push]]).a === Object.fromEntries([['b', Array.prototype.push]]).b, true);test( 'Object.fromEntries preserves native function identity under a symbol key', (() => { const key = Symbol('alias'); return Object.fromEntries([[key, Math.min]])[key] === Math.min; })(), true);test( 'Object.fromEntries result inherits from Object.prototype', Object.getPrototypeOf(Object.fromEntries([['a', 1]])) === Object.prototype, true);test( 'Object.fromEntries result has Object.prototype methods', Object.fromEntries([['a', 1]]).hasOwnProperty('a'), true);test( 'Object.defineProperty preserves native function identity under an alias', (() => { const o = {}; Object.defineProperty(o, 'alias', { value: Math.max, configurable: true }); return o.alias === Math.max; })(), true);
let descriptorSource = {};const descriptorSymbol = Symbol('descriptor');Object.defineProperty(descriptorSource, 'hidden', { value: 42, enumerable: false, writable: false, configurable: false});Object.defineProperty(descriptorSource, 'computed', { get() { return 7; }, enumerable: true, configurable: true});descriptorSource.visible = 'yes';descriptorSource[descriptorSymbol] = 'symbol value';
const descriptors = Object.getOwnPropertyDescriptors(descriptorSource);test('Object.getOwnPropertyDescriptors exists', typeof Object.getOwnPropertyDescriptors, 'function');test('descriptors data value', descriptors.visible.value, 'yes');test('descriptors hidden value', descriptors.hidden.value, 42);test('descriptors hidden enumerable', descriptors.hidden.enumerable, false);test('descriptors hidden writable', descriptors.hidden.writable, false);test('descriptors hidden configurable', descriptors.hidden.configurable, false);test('descriptors accessor getter', typeof descriptors.computed.get, 'function');test('descriptors accessor enumerable', descriptors.computed.enumerable, true);test('descriptors symbol value', descriptors[descriptorSymbol].value, 'symbol value');
const arrayDescriptors = Object.getOwnPropertyDescriptors(['item']);test('array descriptor index value', arrayDescriptors[0].value, 'item');test('array descriptor length value', arrayDescriptors.length.value, 1);const proxyUndefinedDescriptor = new Proxy({ a: 1 }, { getOwnPropertyDescriptor() {}});test('Object.getOwnPropertyDescriptors skips undefined proxy descriptors', Object.getOwnPropertyDescriptors(proxyUndefinedDescriptor).hasOwnProperty('a'), false);testThrows('Object.getOwnPropertyDescriptors throws without argument', () => Object.getOwnPropertyDescriptors());testThrows('Object.getOwnPropertyDescriptors throws on null', () => Object.getOwnPropertyDescriptors(null));test('Object.getOwnPropertyDescriptors boxes number primitive', typeof Object.getOwnPropertyDescriptors(1), 'object');
summary();