|  | import { | 
					
						
						|  | VOID, PRIMITIVE, | 
					
						
						|  | ARRAY, OBJECT, | 
					
						
						|  | DATE, REGEXP, MAP, SET, | 
					
						
						|  | ERROR, BIGINT | 
					
						
						|  | } from './types.js'; | 
					
						
						|  |  | 
					
						
						|  | const EMPTY = ''; | 
					
						
						|  |  | 
					
						
						|  | const {toString} = {}; | 
					
						
						|  | const {keys} = Object; | 
					
						
						|  |  | 
					
						
						|  | const typeOf = value => { | 
					
						
						|  | const type = typeof value; | 
					
						
						|  | if (type !== 'object' || !value) | 
					
						
						|  | return [PRIMITIVE, type]; | 
					
						
						|  |  | 
					
						
						|  | const asString = toString.call(value).slice(8, -1); | 
					
						
						|  | switch (asString) { | 
					
						
						|  | case 'Array': | 
					
						
						|  | return [ARRAY, EMPTY]; | 
					
						
						|  | case 'Object': | 
					
						
						|  | return [OBJECT, EMPTY]; | 
					
						
						|  | case 'Date': | 
					
						
						|  | return [DATE, EMPTY]; | 
					
						
						|  | case 'RegExp': | 
					
						
						|  | return [REGEXP, EMPTY]; | 
					
						
						|  | case 'Map': | 
					
						
						|  | return [MAP, EMPTY]; | 
					
						
						|  | case 'Set': | 
					
						
						|  | return [SET, EMPTY]; | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | if (asString.includes('Array')) | 
					
						
						|  | return [ARRAY, asString]; | 
					
						
						|  |  | 
					
						
						|  | if (asString.includes('Error')) | 
					
						
						|  | return [ERROR, asString]; | 
					
						
						|  |  | 
					
						
						|  | return [OBJECT, asString]; | 
					
						
						|  | }; | 
					
						
						|  |  | 
					
						
						|  | const shouldSkip = ([TYPE, type]) => ( | 
					
						
						|  | TYPE === PRIMITIVE && | 
					
						
						|  | (type === 'function' || type === 'symbol') | 
					
						
						|  | ); | 
					
						
						|  |  | 
					
						
						|  | const serializer = (strict, json, $, _) => { | 
					
						
						|  |  | 
					
						
						|  | const as = (out, value) => { | 
					
						
						|  | const index = _.push(out) - 1; | 
					
						
						|  | $.set(value, index); | 
					
						
						|  | return index; | 
					
						
						|  | }; | 
					
						
						|  |  | 
					
						
						|  | const pair = value => { | 
					
						
						|  | if ($.has(value)) | 
					
						
						|  | return $.get(value); | 
					
						
						|  |  | 
					
						
						|  | let [TYPE, type] = typeOf(value); | 
					
						
						|  | switch (TYPE) { | 
					
						
						|  | case PRIMITIVE: { | 
					
						
						|  | let entry = value; | 
					
						
						|  | switch (type) { | 
					
						
						|  | case 'bigint': | 
					
						
						|  | TYPE = BIGINT; | 
					
						
						|  | entry = value.toString(); | 
					
						
						|  | break; | 
					
						
						|  | case 'function': | 
					
						
						|  | case 'symbol': | 
					
						
						|  | if (strict) | 
					
						
						|  | throw new TypeError('unable to serialize ' + type); | 
					
						
						|  | entry = null; | 
					
						
						|  | break; | 
					
						
						|  | case 'undefined': | 
					
						
						|  | return as([VOID], value); | 
					
						
						|  | } | 
					
						
						|  | return as([TYPE, entry], value); | 
					
						
						|  | } | 
					
						
						|  | case ARRAY: { | 
					
						
						|  | if (type) | 
					
						
						|  | return as([type, [...value]], value); | 
					
						
						|  |  | 
					
						
						|  | const arr = []; | 
					
						
						|  | const index = as([TYPE, arr], value); | 
					
						
						|  | for (const entry of value) | 
					
						
						|  | arr.push(pair(entry)); | 
					
						
						|  | return index; | 
					
						
						|  | } | 
					
						
						|  | case OBJECT: { | 
					
						
						|  | if (type) { | 
					
						
						|  | switch (type) { | 
					
						
						|  | case 'BigInt': | 
					
						
						|  | return as([type, value.toString()], value); | 
					
						
						|  | case 'Boolean': | 
					
						
						|  | case 'Number': | 
					
						
						|  | case 'String': | 
					
						
						|  | return as([type, value.valueOf()], value); | 
					
						
						|  | } | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | if (json && ('toJSON' in value)) | 
					
						
						|  | return pair(value.toJSON()); | 
					
						
						|  |  | 
					
						
						|  | const entries = []; | 
					
						
						|  | const index = as([TYPE, entries], value); | 
					
						
						|  | for (const key of keys(value)) { | 
					
						
						|  | if (strict || !shouldSkip(typeOf(value[key]))) | 
					
						
						|  | entries.push([pair(key), pair(value[key])]); | 
					
						
						|  | } | 
					
						
						|  | return index; | 
					
						
						|  | } | 
					
						
						|  | case DATE: | 
					
						
						|  | return as([TYPE, value.toISOString()], value); | 
					
						
						|  | case REGEXP: { | 
					
						
						|  | const {source, flags} = value; | 
					
						
						|  | return as([TYPE, {source, flags}], value); | 
					
						
						|  | } | 
					
						
						|  | case MAP: { | 
					
						
						|  | const entries = []; | 
					
						
						|  | const index = as([TYPE, entries], value); | 
					
						
						|  | for (const [key, entry] of value) { | 
					
						
						|  | if (strict || !(shouldSkip(typeOf(key)) || shouldSkip(typeOf(entry)))) | 
					
						
						|  | entries.push([pair(key), pair(entry)]); | 
					
						
						|  | } | 
					
						
						|  | return index; | 
					
						
						|  | } | 
					
						
						|  | case SET: { | 
					
						
						|  | const entries = []; | 
					
						
						|  | const index = as([TYPE, entries], value); | 
					
						
						|  | for (const entry of value) { | 
					
						
						|  | if (strict || !shouldSkip(typeOf(entry))) | 
					
						
						|  | entries.push(pair(entry)); | 
					
						
						|  | } | 
					
						
						|  | return index; | 
					
						
						|  | } | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | const {message} = value; | 
					
						
						|  | return as([TYPE, {name: type, message}], value); | 
					
						
						|  | }; | 
					
						
						|  |  | 
					
						
						|  | return pair; | 
					
						
						|  | }; | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  |  | 
					
						
						|  | export const serialize = (value, {json, lossy} = {}) => { | 
					
						
						|  | const _ = []; | 
					
						
						|  | return serializer(!(json || lossy), !!json, new Map, _)(value), _; | 
					
						
						|  | }; | 
					
						
						|  |  |