shell.js (2992B)
1 /*--- 2 defines: [assertSetContainsExactOrderedItems, SetLike, SetIteratorLike, LoggingProxy] 3 allow_unused: True 4 ---*/ 5 (function(global) { 6 // Save the primordial values. 7 const {Array, Error, Object, Proxy, Reflect, Set} = global; 8 9 const ArrayIsArray = Array.isArray; 10 const ReflectApply = Reflect.apply; 11 const ReflectDefineProperty = Reflect.defineProperty; 12 const ReflectGet = Reflect.get; 13 const ReflectGetPrototypeOf = Reflect.getPrototypeOf; 14 const SetPrototype = Set.prototype; 15 const SetPrototypeHas = SetPrototype.has; 16 const SetPrototypeSize = Object.getOwnPropertyDescriptor(SetPrototype, "size").get; 17 const SetPrototypeKeys = SetPrototype.keys; 18 const SetIteratorPrototypeNext = new Set().values().next; 19 20 function assertSetContainsExactOrderedItems(actual, expected) { 21 assertEq(ReflectGetPrototypeOf(actual), SetPrototype, "actual is a native Set object"); 22 assertEq(ArrayIsArray(expected), true, "expected is an Array object"); 23 24 assertEq(ReflectApply(SetPrototypeSize, actual, []), expected.length); 25 26 let index = 0; 27 let keys = ReflectApply(SetPrototypeKeys, actual, []); 28 29 while (true) { 30 let {done, value: item} = ReflectApply(SetIteratorPrototypeNext, keys, []); 31 if (done) { 32 break; 33 } 34 assertEq(item, expected[index], `Element at index ${index}:`); 35 index++; 36 } 37 } 38 global.assertSetContainsExactOrderedItems = assertSetContainsExactOrderedItems; 39 40 class SetLike { 41 #set; 42 43 constructor(values) { 44 this.#set = new Set(values); 45 } 46 47 get size() { 48 return ReflectApply(SetPrototypeSize, this.#set, []); 49 } 50 51 has(value) { 52 return ReflectApply(SetPrototypeHas, this.#set, [value]); 53 } 54 55 keys() { 56 let keys = ReflectApply(SetPrototypeKeys, this.#set, []); 57 return new SetIteratorLike(keys); 58 } 59 } 60 global.SetLike = SetLike; 61 62 class SetIteratorLike { 63 #keys; 64 65 constructor(keys) { 66 this.#keys = keys; 67 } 68 69 next() { 70 return ReflectApply(SetIteratorPrototypeNext, this.#keys, []); 71 } 72 73 // The |return| method of the iterator protocol is never called. 74 return() { 75 throw new Error("Unexpected call to |return| method"); 76 } 77 78 // The |throw| method of the iterator protocol is never called. 79 throw() { 80 throw new Error("Unexpected call to |throw| method"); 81 } 82 } 83 84 function LoggingProxy(obj, log) { 85 assertEq(ArrayIsArray(log), true); 86 87 let handler = new Proxy({ 88 get(t, pk, r) { 89 ReflectDefineProperty(log, log.length, { 90 value: pk, writable: true, enumerable: true, configurable: true, 91 }); 92 return ReflectGet(t, pk, r); 93 } 94 }, { 95 get(t, pk, r) { 96 ReflectDefineProperty(log, log.length, { 97 value: `[[${pk}]]`, writable: true, enumerable: true, configurable: true, 98 }); 99 return ReflectGet(t, pk, r); 100 } 101 }); 102 103 return {obj, proxy: new Proxy(obj, handler)}; 104 } 105 global.LoggingProxy = LoggingProxy; 106 })(this);