UNPKG

9.84 kBJavaScriptView Raw
1var consola = require('consola');
2var chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$';
3var unsafeChars = /[<>\b\f\n\r\t\0\u2028\u2029]/g;
4var reserved = /^(?:do|if|in|for|int|let|new|try|var|byte|case|char|else|enum|goto|long|this|void|with|await|break|catch|class|const|final|float|short|super|throw|while|yield|delete|double|export|import|native|return|switch|throws|typeof|boolean|default|extends|finally|package|private|abstract|continue|debugger|function|volatile|interface|protected|transient|implements|instanceof|synchronized)$/;
5var escaped = {
6 '<': '\\u003C',
7 '>': '\\u003E',
8 '/': '\\u002F',
9 '\\': '\\\\',
10 '\b': '\\b',
11 '\f': '\\f',
12 '\n': '\\n',
13 '\r': '\\r',
14 '\t': '\\t',
15 '\0': '\\0',
16 '\u2028': '\\u2028',
17 '\u2029': '\\u2029'
18};
19var objectProtoOwnPropertyNames = Object.getOwnPropertyNames(Object.prototype).sort().join('\0');
20// workaround to disable warnings, see https://github.com/nuxt/nuxt.js/issues/4026 for details
21var defaultLogLevel = process.env.NUXT_ENV_DEVALUE_LOG_LEVEL || 'warn';
22var logLimit = parseInt(process.env.NUXT_ENV_DEVALUE_LOG_LIMIT) || 99;
23function devalue(value, level) {
24 if (level === void 0) { level = defaultLogLevel; }
25 var counts = new Map();
26 var logNum = 0;
27 function log(message) {
28 if (logNum < logLimit) {
29 consola[level](message);
30 logNum += 1;
31 }
32 }
33 function walk(thing) {
34 if (typeof thing === 'function') {
35 consola[level]("Cannot stringify a function " + thing.name);
36 return;
37 }
38 if (counts.has(thing)) {
39 counts.set(thing, counts.get(thing) + 1);
40 return;
41 }
42 counts.set(thing, 1);
43 if (!isPrimitive(thing)) {
44 var type = getType(thing);
45 switch (type) {
46 case 'Number':
47 case 'String':
48 case 'Boolean':
49 case 'Date':
50 case 'RegExp':
51 return;
52 case 'Array':
53 thing.forEach(walk);
54 break;
55 case 'Set':
56 case 'Map':
57 Array.from(thing).forEach(walk);
58 break;
59 default:
60 var proto = Object.getPrototypeOf(thing);
61 if (proto !== Object.prototype &&
62 proto !== null &&
63 Object.getOwnPropertyNames(proto).sort().join('\0') !== objectProtoOwnPropertyNames) {
64 if (typeof thing.toJSON !== "function") {
65 log("Cannot stringify arbitrary non-POJOs " + thing.constructor.name);
66 }
67 }
68 else if (Object.getOwnPropertySymbols(thing).length > 0) {
69 log("Cannot stringify POJOs with symbolic keys " + Object.getOwnPropertySymbols(thing).map(function (symbol) { return symbol.toString(); }));
70 }
71 else {
72 Object.keys(thing).forEach(function (key) { return walk(thing[key]); });
73 }
74 }
75 }
76 }
77 walk(value);
78 var names = new Map();
79 Array.from(counts)
80 .filter(function (entry) { return entry[1] > 1; })
81 .sort(function (a, b) { return b[1] - a[1]; })
82 .forEach(function (entry, i) {
83 names.set(entry[0], getName(i));
84 });
85 function stringify(thing) {
86 if (names.has(thing)) {
87 return names.get(thing);
88 }
89 if (isPrimitive(thing)) {
90 return stringifyPrimitive(thing);
91 }
92 var type = getType(thing);
93 switch (type) {
94 case 'Number':
95 case 'String':
96 case 'Boolean':
97 return "Object(" + stringify(thing.valueOf()) + ")";
98 case 'RegExp':
99 return thing.toString();
100 case 'Date':
101 return "new Date(" + thing.getTime() + ")";
102 case 'Array':
103 var members = thing.map(function (v, i) { return i in thing ? stringify(v) : ''; });
104 var tail = thing.length === 0 || (thing.length - 1 in thing) ? '' : ',';
105 return "[" + members.join(',') + tail + "]";
106 case 'Set':
107 case 'Map':
108 return "new " + type + "([" + Array.from(thing).map(stringify).join(',') + "])";
109 default:
110 if (thing.toJSON) {
111 var json = thing.toJSON();
112 if (getType(json) === 'String') {
113 // Try to parse the returned data
114 try {
115 json = JSON.parse(json);
116 }
117 catch (e) { }
118 }
119 return stringify(json);
120 }
121 if (Object.getPrototypeOf(thing) === null) {
122 if (Object.keys(thing).length === 0) {
123 return 'Object.create(null)';
124 }
125 return "Object.create(null,{" + Object.keys(thing).map(function (key) { return safeKey(key) + ":{writable:true,enumerable:true,value:" + stringify(thing[key]) + "}"; }).join(',') + "})";
126 }
127 return "{" + Object.keys(thing).map(function (key) { return safeKey(key) + ":" + stringify(thing[key]); }).join(',') + "}";
128 }
129 }
130 var str = stringify(value);
131 if (names.size) {
132 var params_1 = [];
133 var statements_1 = [];
134 var values_1 = [];
135 names.forEach(function (name, thing) {
136 params_1.push(name);
137 if (isPrimitive(thing)) {
138 values_1.push(stringifyPrimitive(thing));
139 return;
140 }
141 var type = getType(thing);
142 switch (type) {
143 case 'Number':
144 case 'String':
145 case 'Boolean':
146 values_1.push("Object(" + stringify(thing.valueOf()) + ")");
147 break;
148 case 'RegExp':
149 values_1.push(thing.toString());
150 break;
151 case 'Date':
152 values_1.push("new Date(" + thing.getTime() + ")");
153 break;
154 case 'Array':
155 values_1.push("Array(" + thing.length + ")");
156 thing.forEach(function (v, i) {
157 statements_1.push(name + "[" + i + "]=" + stringify(v));
158 });
159 break;
160 case 'Set':
161 values_1.push("new Set");
162 statements_1.push(name + "." + Array.from(thing).map(function (v) { return "add(" + stringify(v) + ")"; }).join('.'));
163 break;
164 case 'Map':
165 values_1.push("new Map");
166 statements_1.push(name + "." + Array.from(thing).map(function (_a) {
167 var k = _a[0], v = _a[1];
168 return "set(" + stringify(k) + ", " + stringify(v) + ")";
169 }).join('.'));
170 break;
171 default:
172 values_1.push(Object.getPrototypeOf(thing) === null ? 'Object.create(null)' : '{}');
173 Object.keys(thing).forEach(function (key) {
174 statements_1.push("" + name + safeProp(key) + "=" + stringify(thing[key]));
175 });
176 }
177 });
178 statements_1.push("return " + str);
179 return "(function(" + params_1.join(',') + "){" + statements_1.join(';') + "}(" + values_1.join(',') + "))";
180 }
181 else {
182 return str;
183 }
184}
185function getName(num) {
186 var name = '';
187 do {
188 name = chars[num % chars.length] + name;
189 num = ~~(num / chars.length) - 1;
190 } while (num >= 0);
191 return reserved.test(name) ? name + "_" : name;
192}
193function isPrimitive(thing) {
194 return Object(thing) !== thing;
195}
196function stringifyPrimitive(thing) {
197 if (typeof thing === 'string')
198 return stringifyString(thing);
199 if (thing === void 0)
200 return 'void 0';
201 if (thing === 0 && 1 / thing < 0)
202 return '-0';
203 var str = String(thing);
204 if (typeof thing === 'number')
205 return str.replace(/^(-)?0\./, '$1.');
206 return str;
207}
208function getType(thing) {
209 return Object.prototype.toString.call(thing).slice(8, -1);
210}
211function escapeUnsafeChar(c) {
212 return escaped[c] || c;
213}
214function escapeUnsafeChars(str) {
215 return str.replace(unsafeChars, escapeUnsafeChar);
216}
217function safeKey(key) {
218 return /^[_$a-zA-Z][_$a-zA-Z0-9]*$/.test(key) ? key : escapeUnsafeChars(JSON.stringify((key)));
219}
220function safeProp(key) {
221 return /^[_$a-zA-Z][_$a-zA-Z0-9]*$/.test(key) ? "." + key : "[" + escapeUnsafeChars(JSON.stringify(key)) + "]";
222}
223function stringifyString(str) {
224 var result = '"';
225 for (var i = 0; i < str.length; i += 1) {
226 var char = str.charAt(i);
227 var code = char.charCodeAt(0);
228 if (char === '"') {
229 result += '\\"';
230 }
231 else if (char in escaped) {
232 result += escaped[char];
233 }
234 else if (code >= 0xd800 && code <= 0xdfff) {
235 var next = str.charCodeAt(i + 1);
236 // If this is the beginning of a [high, low] surrogate pair,
237 // add the next two characters, otherwise escape
238 if (code <= 0xdbff && (next >= 0xdc00 && next <= 0xdfff)) {
239 result += char + str[++i];
240 }
241 else {
242 result += "\\u" + code.toString(16).toUpperCase();
243 }
244 }
245 else {
246 result += char;
247 }
248 }
249 result += '"';
250 return result;
251}
252
253export default devalue;