Skip to content

Commit cdc7446

Browse files
committed
fixes #11
minor optimizations
1 parent 7cf8073 commit cdc7446

File tree

2 files changed

+56
-52
lines changed

2 files changed

+56
-52
lines changed

index.js

Lines changed: 53 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,29 @@
77

88
'use strict';
99

10+
const { deleteProperty } = Reflect;
11+
const isPrimitive = require('is-primitive');
1012
const isPlainObject = require('is-plain-object');
1113

12-
const isObject = val => {
13-
return (typeof val === 'object' && val !== null) || typeof val === 'function';
14+
const isObject = value => {
15+
return (typeof value === 'object' && value !== null) || typeof value === 'function';
1416
};
1517

1618
const isUnsafeKey = key => {
1719
return key === '__proto__' || key === 'constructor' || key === 'prototype';
1820
};
1921

2022
const validateKey = key => {
21-
if (typeof key !== 'string' && typeof key !== 'number') {
22-
key = String(key);
23+
if (!isPrimitive(key)) {
24+
throw new TypeError('Object keys must be strings or symbols');
2325
}
2426

2527
if (isUnsafeKey(key)) {
2628
throw new Error(`Cannot set unsafe key: "${key}"`);
2729
}
2830
};
2931

30-
const toString = input => {
32+
const toStringKey = input => {
3133
return Array.isArray(input) ? input.flat().map(String).join(',') : input;
3234
};
3335

@@ -43,71 +45,74 @@ const createMemoKey = (input, options) => {
4345
};
4446

4547
const memoize = (input, options, fn) => {
46-
const key = toString(options ? createMemoKey(input, options) : input);
48+
const key = toStringKey(options ? createMemoKey(input, options) : input);
4749
validateKey(key);
4850

49-
const val = setValue.cache.get(key) || fn();
50-
setValue.cache.set(key, val);
51-
return val;
51+
const value = setValue.cache.get(key) || fn();
52+
setValue.cache.set(key, value);
53+
return value;
5254
};
5355

54-
const isNumber = value => {
55-
if (value.trim() !== '') {
56-
const number = Number(value);
57-
return { is: Number.isInteger(number), number };
58-
}
59-
return { is: false };
60-
};
61-
62-
const splitString = (input, options) => {
63-
const opts = options || {};
64-
const sep = opts.separator || '.';
65-
const preserve = sep === '/' ? false : opts.preservePaths;
56+
const splitString = (input, options = {}) => {
57+
const sep = options.separator || '.';
58+
const preserve = sep === '/' ? false : options.preservePaths;
6659

67-
if (typeof input === 'symbol') {
60+
if (typeof input === 'string' && preserve !== false && /\//.test(input)) {
6861
return [input];
6962
}
7063

71-
if (typeof opts.split === 'function') {
72-
return opts.split(input);
73-
}
64+
const parts = [];
65+
let part = '';
7466

75-
const keys = Array.isArray(input) ? input : input.split(sep);
76-
77-
if (typeof input === 'string' && preserve !== false && /\//.test(input)) {
78-
return [input];
79-
}
67+
const push = part => {
68+
let number;
69+
if (part.trim() !== '' && Number.isInteger((number = Number(part)))) {
70+
parts.push(number);
71+
} else {
72+
parts.push(part);
73+
}
74+
};
8075

81-
for (let i = 0; i < keys.length; i++) {
82-
if (typeof keys[i] !== 'string') break;
83-
const { is, number } = isNumber(keys[i]);
76+
for (let i = 0; i < input.length; i++) {
77+
const value = input[i];
8478

85-
if (is) {
86-
keys[i] = number;
79+
if (value === '\\') {
80+
part += input[++i];
8781
continue;
8882
}
8983

90-
while (keys[i] && i < keys.length && keys[i].endsWith('\\') && typeof keys[i + 1] === 'string') {
91-
keys[i] = keys[i].slice(0, -1) + sep + keys.splice(i + 1, 1);
84+
if (value === sep) {
85+
push(part);
86+
part = '';
87+
continue;
9288
}
89+
90+
part += value;
91+
}
92+
93+
if (part) {
94+
push(part);
9395
}
9496

95-
return keys;
97+
return parts;
9698
};
9799

98100
const split = (input, options) => {
101+
if (options && typeof options.split === 'function') return options.split(input);
102+
if (typeof input === 'symbol') return [input];
103+
if (Array.isArray(input)) return input;
99104
return memoize(input, options, () => splitString(input, options));
100105
};
101106

102-
const setProp = (obj, prop, value, options) => {
107+
const assignProp = (obj, prop, value, options) => {
103108
validateKey(prop);
104109

105110
// Delete property when "value" is undefined
106111
if (value === undefined) {
107-
delete obj[prop];
112+
deleteProperty(obj, prop);
108113

109114
} else if (options && options.merge) {
110-
const merge = options.merge === true ? Object.assign : options.merge;
115+
const merge = options.merge === 'function' ? options.merge : Object.assign;
111116

112117
// Only merge plain objects
113118
if (merge && isPlainObject(obj[prop]) && isPlainObject(value)) {
@@ -123,28 +128,25 @@ const setProp = (obj, prop, value, options) => {
123128
return obj;
124129
};
125130

126-
const setValue = (obj, path, value, options) => {
127-
if (!path) return obj;
128-
if (!isObject(obj)) return obj;
131+
const setValue = (target, path, value, options) => {
132+
if (!path || !isObject(target)) return target;
129133

130134
const keys = split(path, options);
131-
const len = keys.length;
132-
const target = obj;
135+
let obj = target;
133136

134-
for (let i = 0; i < len; i++) {
137+
for (let i = 0; i < keys.length; i++) {
135138
const key = keys[i];
136139
const next = keys[i + 1];
137140

138141
validateKey(key);
139142

140143
if (next === undefined) {
141-
setProp(obj, key, value, options);
144+
assignProp(obj, key, value, options);
142145
break;
143146
}
144147

145148
if (typeof next === 'number' && !Array.isArray(obj[key])) {
146-
obj[key] = [];
147-
obj = obj[key];
149+
obj = obj[key] = [];
148150
continue;
149151
}
150152

@@ -158,6 +160,7 @@ const setValue = (obj, path, value, options) => {
158160
return target;
159161
};
160162

163+
setValue.split = split;
161164
setValue.cache = new Map();
162165
setValue.clear = () => {
163166
setValue.cache = new Map();

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,12 @@
2828
"test": "mocha"
2929
},
3030
"dependencies": {
31-
"is-plain-object": "^2.0.4"
31+
"is-plain-object": "^2.0.4",
32+
"is-primitive": "^3.0.1"
3233
},
3334
"devDependencies": {
3435
"gulp-format-md": "^2.0.0",
35-
"mocha": "^8.3.2",
36+
"mocha": "^9.1.1",
3637
"split-string": "^6.1.0"
3738
},
3839
"keywords": [

0 commit comments

Comments
 (0)