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