map.js (3129B)
1 import { setSafeProperty, hasSafeProperty, getSafeProperty } from './customs.js'; 2 import { isObject } from './is.js'; 3 /** 4 * A map facade on a bare object. 5 * 6 * The small number of methods needed to implement a scope, 7 * forwarding on to the SafeProperty functions. Over time, the codebase 8 * will stop using this method, as all objects will be Maps, rather than 9 * more security prone objects. 10 */ 11 12 export class ObjectWrappingMap { 13 constructor(object) { 14 this.wrappedObject = object; 15 } 16 17 keys() { 18 return Object.keys(this.wrappedObject); 19 } 20 21 get(key) { 22 return getSafeProperty(this.wrappedObject, key); 23 } 24 25 set(key, value) { 26 setSafeProperty(this.wrappedObject, key, value); 27 return this; 28 } 29 30 has(key) { 31 return hasSafeProperty(this.wrappedObject, key); 32 } 33 34 } 35 /** 36 * Creates an empty map, or whatever your platform's polyfill is. 37 * 38 * @returns an empty Map or Map like object. 39 */ 40 41 export function createEmptyMap() { 42 return new Map(); 43 } 44 /** 45 * Creates a Map from the given object. 46 * 47 * @param { Map | { [key: string]: unknown } | undefined } mapOrObject 48 * @returns 49 */ 50 51 export function createMap(mapOrObject) { 52 if (!mapOrObject) { 53 return createEmptyMap(); 54 } 55 56 if (isMap(mapOrObject)) { 57 return mapOrObject; 58 } 59 60 if (isObject(mapOrObject)) { 61 return new ObjectWrappingMap(mapOrObject); 62 } 63 64 throw new Error('createMap can create maps from objects or Maps'); 65 } 66 /** 67 * Unwraps a map into an object. 68 * 69 * @param {Map} map 70 * @returns { [key: string]: unknown } 71 */ 72 73 export function toObject(map) { 74 if (map instanceof ObjectWrappingMap) { 75 return map.wrappedObject; 76 } 77 78 var object = {}; 79 80 for (var key of map.keys()) { 81 var value = map.get(key); 82 setSafeProperty(object, key, value); 83 } 84 85 return object; 86 } 87 /** 88 * Returns `true` if the passed object appears to be a Map (i.e. duck typing). 89 * 90 * Methods looked for are `get`, `set`, `keys` and `has`. 91 * 92 * @param {Map | object} object 93 * @returns 94 */ 95 96 export function isMap(object) { 97 // We can use the fast instanceof, or a slower duck typing check. 98 // The duck typing method needs to cover enough methods to not be confused with DenseMatrix. 99 if (!object) { 100 return false; 101 } 102 103 return object instanceof Map || object instanceof ObjectWrappingMap || typeof object.set === 'function' && typeof object.get === 'function' && typeof object.keys === 'function' && typeof object.has === 'function'; 104 } 105 /** 106 * Copies the contents of key-value pairs from each `objects` in to `map`. 107 * 108 * Object is `objects` can be a `Map` or object. 109 * 110 * This is the `Map` analog to `Object.assign`. 111 */ 112 113 export function assign(map) { 114 for (var _len = arguments.length, objects = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 115 objects[_key - 1] = arguments[_key]; 116 } 117 118 for (var args of objects) { 119 if (!args) { 120 continue; 121 } 122 123 if (isMap(args)) { 124 for (var key of args.keys()) { 125 map.set(key, args.get(key)); 126 } 127 } else if (isObject(args)) { 128 for (var _key2 of Object.keys(args)) { 129 map.set(_key2, args[_key2]); 130 } 131 } 132 } 133 134 return map; 135 }