source: frontend/node_modules/terser-webpack-plugin/dist/serialize-javascript.js@ cdcff72

Last change on this file since cdcff72 was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 9.7 KB
Line 
1"use strict";
2
3// @ts-nocheck
4
5var g = typeof globalThis !== 'undefined' ? globalThis : global;
6var crypto = g.crypto || {};
7if (typeof crypto.getRandomValues !== 'function') {
8 var nodeCrypto = require('crypto');
9 crypto.getRandomValues = function (typedArray) {
10 var bytes = nodeCrypto.randomBytes(typedArray.byteLength);
11 new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength).set(bytes);
12 return typedArray;
13 };
14}
15/*
16Copyright (c) 2014, Yahoo! Inc. All rights reserved.
17Copyrights licensed under the New BSD License.
18See the accompanying LICENSE file for terms.
19*/
20
21'use strict';
22
23// Generate an internal UID to make the regexp pattern harder to guess.
24var UID_LENGTH = 16;
25var UID = generateUID();
26var PLACE_HOLDER_REGEXP = new RegExp('(\\\\)?"@__(F|R|D|M|S|A|U|I|B|L)-' + UID + '-(\\d+)__@"', 'g');
27var IS_NATIVE_CODE_REGEXP = /\{\s*\[native code\]\s*\}/g;
28var IS_PURE_FUNCTION = /function.*?\(/;
29var IS_ARROW_FUNCTION = /.*?=>.*?/;
30var UNSAFE_CHARS_REGEXP = /[<>\/\u2028\u2029]/g;
31// Regex to match </script> and variations (case-insensitive) for XSS protection
32// Matches </script followed by optional whitespace/attributes and >
33var SCRIPT_CLOSE_REGEXP = /<\/script[^>]*>/gi;
34var RESERVED_SYMBOLS = ['*', 'async'];
35
36// Mapping of unsafe HTML and invalid JavaScript line terminator chars to their
37// Unicode char counterparts which are safe to use in JavaScript strings.
38var ESCAPED_CHARS = {
39 '<': '\\u003C',
40 '>': '\\u003E',
41 '/': '\\u002F',
42 '\u2028': '\\u2028',
43 '\u2029': '\\u2029'
44};
45function escapeUnsafeChars(unsafeChar) {
46 return ESCAPED_CHARS[unsafeChar];
47}
48
49// Escape function body for XSS protection while preserving arrow function syntax
50function escapeFunctionBody(str) {
51 // Escape </script> sequences and variations (case-insensitive) - the main XSS risk
52 // Matches </script followed by optional whitespace/attributes and >
53 // This must be done first before other replacements
54 str = str.replace(SCRIPT_CLOSE_REGEXP, function (match) {
55 // Escape all <, /, and > characters in the closing script tag
56 return match.replace(/</g, '\\u003C').replace(/\//g, '\\u002F').replace(/>/g, '\\u003E');
57 });
58 // Escape line terminators (these are always unsafe)
59 str = str.replace(/\u2028/g, '\\u2028');
60 str = str.replace(/\u2029/g, '\\u2029');
61 return str;
62}
63function generateUID() {
64 var bytes = crypto.getRandomValues(new Uint8Array(UID_LENGTH));
65 var result = '';
66 for (var i = 0; i < UID_LENGTH; ++i) {
67 result += bytes[i].toString(16);
68 }
69 return result;
70}
71function deleteFunctions(obj) {
72 var functionKeys = [];
73 for (var key in obj) {
74 if (typeof obj[key] === "function") {
75 functionKeys.push(key);
76 }
77 }
78 for (var i = 0; i < functionKeys.length; i++) {
79 delete obj[functionKeys[i]];
80 }
81}
82module.exports = function serialize(obj, options) {
83 options || (options = {});
84
85 // Backwards-compatibility for `space` as the second argument.
86 if (typeof options === 'number' || typeof options === 'string') {
87 options = {
88 space: options
89 };
90 }
91 var functions = [];
92 var regexps = [];
93 var dates = [];
94 var maps = [];
95 var sets = [];
96 var arrays = [];
97 var undefs = [];
98 var infinities = [];
99 var bigInts = [];
100 var urls = [];
101
102 // Returns placeholders for functions and regexps (identified by index)
103 // which are later replaced by their string representation.
104 function replacer(key, value) {
105 // For nested function
106 if (options.ignoreFunction) {
107 deleteFunctions(value);
108 }
109 if (!value && value !== undefined && value !== BigInt(0)) {
110 return value;
111 }
112
113 // If the value is an object w/ a toJSON method, toJSON is called before
114 // the replacer runs, so we use this[key] to get the non-toJSONed value.
115 var origValue = this[key];
116 var type = typeof origValue;
117 if (type === 'object') {
118 if (origValue instanceof RegExp) {
119 return '@__R-' + UID + '-' + (regexps.push(origValue) - 1) + '__@';
120 }
121 if (origValue instanceof Date) {
122 return '@__D-' + UID + '-' + (dates.push(origValue) - 1) + '__@';
123 }
124 if (origValue instanceof Map) {
125 return '@__M-' + UID + '-' + (maps.push(origValue) - 1) + '__@';
126 }
127 if (origValue instanceof Set) {
128 return '@__S-' + UID + '-' + (sets.push(origValue) - 1) + '__@';
129 }
130 if (Array.isArray(origValue)) {
131 var isSparse = Object.keys(origValue).length !== origValue.length;
132 if (isSparse) {
133 return '@__A-' + UID + '-' + (arrays.push(origValue) - 1) + '__@';
134 }
135 }
136 if (origValue instanceof URL) {
137 return '@__L-' + UID + '-' + (urls.push(origValue) - 1) + '__@';
138 }
139 }
140 if (type === 'function') {
141 return '@__F-' + UID + '-' + (functions.push(origValue) - 1) + '__@';
142 }
143 if (type === 'undefined') {
144 return '@__U-' + UID + '-' + (undefs.push(origValue) - 1) + '__@';
145 }
146 if (type === 'number' && !isNaN(origValue) && !isFinite(origValue)) {
147 return '@__I-' + UID + '-' + (infinities.push(origValue) - 1) + '__@';
148 }
149 if (type === 'bigint') {
150 return '@__B-' + UID + '-' + (bigInts.push(origValue) - 1) + '__@';
151 }
152 return value;
153 }
154 function serializeFunc(fn, options) {
155 var serializedFn = fn.toString();
156 if (IS_NATIVE_CODE_REGEXP.test(serializedFn)) {
157 throw new TypeError('Serializing native function: ' + fn.name);
158 }
159
160 // Escape unsafe HTML characters in function body for XSS protection
161 // This must preserve arrow function syntax (=>) while escaping </script>
162 if (options && options.unsafe !== true) {
163 serializedFn = escapeFunctionBody(serializedFn);
164 }
165
166 // pure functions, example: {key: function() {}}
167 if (IS_PURE_FUNCTION.test(serializedFn)) {
168 return serializedFn;
169 }
170
171 // arrow functions, example: arg1 => arg1+5
172 if (IS_ARROW_FUNCTION.test(serializedFn)) {
173 return serializedFn;
174 }
175 var argsStartsAt = serializedFn.indexOf('(');
176 var def = serializedFn.substr(0, argsStartsAt).trim().split(' ').filter(function (val) {
177 return val.length > 0;
178 });
179 var nonReservedSymbols = def.filter(function (val) {
180 return RESERVED_SYMBOLS.indexOf(val) === -1;
181 });
182
183 // enhanced literal objects, example: {key() {}}
184 if (nonReservedSymbols.length > 0) {
185 return (def.indexOf('async') > -1 ? 'async ' : '') + 'function' + (def.join('').indexOf('*') > -1 ? '*' : '') + serializedFn.substr(argsStartsAt);
186 }
187
188 // arrow functions
189 return serializedFn;
190 }
191
192 // Check if the parameter is function
193 if (options.ignoreFunction && typeof obj === "function") {
194 obj = undefined;
195 }
196 // Protects against `JSON.stringify()` returning `undefined`, by serializing
197 // to the literal string: "undefined".
198 if (obj === undefined) {
199 return String(obj);
200 }
201 var str;
202
203 // Creates a JSON string representation of the value.
204 // NOTE: Node 0.12 goes into slow mode with extra JSON.stringify() args.
205 if (options.isJSON && !options.space) {
206 str = JSON.stringify(obj);
207 } else {
208 str = JSON.stringify(obj, options.isJSON ? null : replacer, options.space);
209 }
210
211 // Protects against `JSON.stringify()` returning `undefined`, by serializing
212 // to the literal string: "undefined".
213 if (typeof str !== 'string') {
214 return String(str);
215 }
216
217 // Replace unsafe HTML and invalid JavaScript line terminator chars with
218 // their safe Unicode char counterpart. This _must_ happen before the
219 // regexps and functions are serialized and added back to the string.
220 if (options.unsafe !== true) {
221 str = str.replace(UNSAFE_CHARS_REGEXP, escapeUnsafeChars);
222 }
223 if (functions.length === 0 && regexps.length === 0 && dates.length === 0 && maps.length === 0 && sets.length === 0 && arrays.length === 0 && undefs.length === 0 && infinities.length === 0 && bigInts.length === 0 && urls.length === 0) {
224 return str;
225 }
226
227 // Replaces all occurrences of function, regexp, date, map and set placeholders in the
228 // JSON string with their string representations. If the original value can
229 // not be found, then `undefined` is used.
230 return str.replace(PLACE_HOLDER_REGEXP, function (match, backSlash, type, valueIndex) {
231 // The placeholder may not be preceded by a backslash. This is to prevent
232 // replacing things like `"a\"@__R-<UID>-0__@"` and thus outputting
233 // invalid JS.
234 if (backSlash) {
235 return match;
236 }
237 if (type === 'D') {
238 // Validate ISO string format to prevent code injection via spoofed toISOString()
239 var isoStr = String(dates[valueIndex].toISOString());
240 if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z$/.test(isoStr)) {
241 throw new TypeError('Invalid Date ISO string');
242 }
243 return "new Date(\"" + isoStr + "\")";
244 }
245 if (type === 'R') {
246 // Sanitize flags to prevent code injection (only allow valid RegExp flag characters)
247 var flags = String(regexps[valueIndex].flags).replace(/[^gimsuydv]/g, '');
248 return "new RegExp(" + serialize(regexps[valueIndex].source) + ", \"" + flags + "\")";
249 }
250 if (type === 'M') {
251 return "new Map(" + serialize(Array.from(maps[valueIndex].entries()), options) + ")";
252 }
253 if (type === 'S') {
254 return "new Set(" + serialize(Array.from(sets[valueIndex].values()), options) + ")";
255 }
256 if (type === 'A') {
257 return "Array.prototype.slice.call(" + serialize(Object.assign({
258 length: arrays[valueIndex].length
259 }, arrays[valueIndex]), options) + ")";
260 }
261 if (type === 'U') {
262 return 'undefined';
263 }
264 if (type === 'I') {
265 return infinities[valueIndex];
266 }
267 if (type === 'B') {
268 return "BigInt(\"" + bigInts[valueIndex] + "\")";
269 }
270 if (type === 'L') {
271 return "new URL(" + serialize(urls[valueIndex].toString(), options) + ")";
272 }
273 var fn = functions[valueIndex];
274 return serializeFunc(fn, options);
275 });
276};
Note: See TracBrowser for help on using the repository browser.