Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@discoveryjs/json-ext

Package Overview
Dependencies
Maintainers
3
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@discoveryjs/json-ext - npm Package Compare versions

Comparing version 0.6.1 to 0.6.2

102

dist/json-ext.js

@@ -89,2 +89,23 @@ (function (global, factory) {

}
function normalizeStringifyOptions(optionsOrReplacer, space) {
if (optionsOrReplacer === null || Array.isArray(optionsOrReplacer) || typeof optionsOrReplacer !== "object") {
optionsOrReplacer = {
replacer: optionsOrReplacer,
space
};
}
let replacer = normalizeReplacer(optionsOrReplacer.replacer);
let getKeys = Object.keys;
if (Array.isArray(replacer)) {
const allowlist = replacer;
getKeys = () => allowlist;
replacer = null;
}
return {
...optionsOrReplacer,
replacer,
getKeys,
space: normalizeSpace(optionsOrReplacer.space)
};
}

@@ -294,2 +315,3 @@ // src/parse-chunked.js

case 93:
/* ] */
case 125:

@@ -304,4 +326,7 @@ flushPoint = i + 1;

case 9:
/* \t */
case 10:
/* \n */
case 13:
/* \r */
case 32:

@@ -345,14 +370,7 @@ if (lastFlushPoint === i) {

}
function* stringifyChunked(value, optionsOrReplacer, space) {
if (optionsOrReplacer === null || Array.isArray(optionsOrReplacer) || typeof optionsOrReplacer !== "object") {
optionsOrReplacer = {
replacer: optionsOrReplacer,
space
};
}
const highWaterMark = Number(optionsOrReplacer.highWaterMark) || 16384;
let replacer = normalizeReplacer(optionsOrReplacer.replacer);
space = normalizeSpace(optionsOrReplacer.space);
function* stringifyChunked(value, ...args) {
const { replacer, getKeys, space, ...options } = normalizeStringifyOptions(...args);
const highWaterMark = Number(options.highWaterMark) || 16384;
const keyStrings = /* @__PURE__ */ new Map();
const visited = [];
const stack = [];
const rootValue = { "": value };

@@ -366,8 +384,2 @@ let prevState = null;

let buffer = "";
let getKeys = Object.keys;
if (Array.isArray(replacer)) {
const allowlist = replacer;
getKeys = () => allowlist;
replacer = null;
}
while (true) {

@@ -390,3 +402,3 @@ state();

buffer += space && !stateEmpty ? `
${space.repeat(visited.length - 1)}}` : "}";
${space.repeat(stack.length - 1)}}` : "}";
popState();

@@ -404,3 +416,3 @@ return;

buffer += space && !stateEmpty ? `
${space.repeat(visited.length - 1)}]` : "]";
${space.repeat(stack.length - 1)}]` : "]";
popState();

@@ -419,3 +431,3 @@ return;

buffer += `
${space.repeat(visited.length)}`;
${space.repeat(stack.length)}`;
}

@@ -438,7 +450,7 @@ if (state === printObject) {

} else {
if (visited.includes(value2)) {
if (stack.includes(value2)) {
throw new TypeError("Converting circular structure to JSON");
}
printEntryPrelude(key);
visited.push(value2);
stack.push(value2);
pushState();

@@ -478,4 +490,4 @@ state = Array.isArray(value2) ? printArray : printObject;

function popState() {
visited.pop();
const value2 = visited.length > 0 ? visited[visited.length - 1] : rootValue;
stack.pop();
const value2 = stack.length > 0 ? stack[stack.length - 1] : rootValue;
state = Array.isArray(value2) ? printArray : printObject;

@@ -569,2 +581,3 @@ stateValue = value2;

return 4;
/* null */
default:

@@ -574,29 +587,14 @@ return 0;

}
function spaceLength(space) {
space = normalizeSpace(space);
return typeof space === "string" ? space.length : 0;
}
function stringifyInfo(value, optionsOrReplacer, space) {
if (optionsOrReplacer === null || Array.isArray(optionsOrReplacer) || typeof optionsOrReplacer !== "object") {
optionsOrReplacer = {
replacer: optionsOrReplacer,
space
};
}
const continueOnCircular = Boolean(optionsOrReplacer.continueOnCircular);
let replacer = normalizeReplacer(optionsOrReplacer.replacer);
let getKeys = Object.keys;
if (Array.isArray(replacer)) {
const allowlist = replacer;
getKeys = () => allowlist;
replacer = null;
}
space = spaceLength(space);
function stringifyInfo(value, ...args) {
const { replacer, getKeys, ...options } = normalizeStringifyOptions(...args);
const continueOnCircular = Boolean(options.continueOnCircular);
const space = options.space?.length || 0;
const keysLength = /* @__PURE__ */ new Map();
const visited = /* @__PURE__ */ new Map();
const circular = /* @__PURE__ */ new Set();
const stack = [];
const circular = /* @__PURE__ */ new Set();
const root = { "": value };
let stop = false;
let bytes = 0;
let spaceBytes = 0;
let objects = 0;

@@ -608,3 +606,4 @@ walk(root, "", value);

return {
bytes: isNaN(bytes) ? Infinity : bytes,
bytes: isNaN(bytes) ? Infinity : bytes + spaceBytes,
spaceBytes: space > 0 && isNaN(bytes) ? Infinity : spaceBytes,
circular: [...circular]

@@ -651,3 +650,3 @@ };

if (keyLen === void 0) {
keysLength.set(key2, keyLen = stringLength(key2) + (space > 0 ? 2 : 1));
keysLength.set(key2, keyLen = stringLength(key2) + 1);
}

@@ -662,4 +661,9 @@ bytes += keyLen;

if (space > 0 && valueLength > 0) {
bytes += (1 + stack.length * space) * valueLength + // for each key-value: \n{space}
1 + (stack.length - 1) * space;
spaceBytes += // a space between ":" and a value for each object entry
(Array.isArray(value2) ? 0 : valueLength) + // the formula results from folding the following components:
// - for each key-value or element: ident + newline
// (1 + stack.length * space) * valueLength
// - ident (one space less) before "}" or "]" + newline
// (stack.length - 1) * space + 1
(1 + stack.length * space) * (valueLength + 1) - space;
}

@@ -666,0 +670,0 @@ stack.pop();

@@ -6,6 +6,6 @@ (function (global, factory) {

}(typeof globalThis != 'undefined' ? globalThis : typeof window != 'undefined' ? window : typeof global != 'undefined' ? global : typeof self != 'undefined' ? self : this, (function () {
var exports=(()=>{var L=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var W=Object.prototype.hasOwnProperty;var K=(e,t)=>{for(var n in t)L(e,n,{get:t[n],enumerable:!0})},_=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of V(t))!W.call(e,i)&&i!==n&&L(e,i,{get:()=>t[i],enumerable:!(r=M(t,i))||r.enumerable});return e};var $=e=>_(L({},"__esModule",{value:!0}),e);var it={};K(it,{createStringifyWebStream:()=>z,parseChunked:()=>I,parseFromWebStream:()=>J,stringifyChunked:()=>m,stringifyInfo:()=>q});function O(e){return typeof e=="object"&&e!==null&&(typeof e[Symbol.iterator]=="function"||typeof e[Symbol.asyncIterator]=="function")}function F(e,t,n,r){switch(n&&typeof n.toJSON=="function"&&(n=n.toJSON()),r!==null&&(n=r.call(e,String(t),n)),typeof n){case"function":case"symbol":n=void 0;break;case"object":if(n!==null){let i=n.constructor;(i===String||i===Number||i===Boolean)&&(n=n.valueOf())}break}return n}function B(e){return typeof e=="function"?e:Array.isArray(e)?[...new Set(e.map(n=>{let r=n&&n.constructor;return r===String||r===Number?String(n):null}).filter(n=>typeof n=="string"))]:null}function N(e){return typeof e=="number"?!Number.isFinite(e)||e<1?!1:" ".repeat(Math.min(e,10)):typeof e=="string"&&e.slice(0,10)||!1}var C=1,U=2,Y=new TextDecoder;function G(e,t){return e.name==="SyntaxError"&&t.jsonParseOffset&&(e.message=e.message.replace(/at position (\d+)/,(n,r)=>"at position "+(Number(r)+t.jsonParseOffset))),e}function H(e,t){let n=e.length;e.length+=t.length;for(let r=0;r<t.length;r++)e[n+r]=t[r]}async function I(e){let t=typeof e=="function"?e():e;if(O(t)){let n=new P;try{for await(let r of t){if(typeof r!="string"&&!ArrayBuffer.isView(r))throw new TypeError("Invalid chunk: Expected string, TypedArray or Buffer");n.push(r)}return n.finish()}catch(r){throw G(r,n)}}throw new TypeError("Invalid chunk emitter: Expected an Iterable, AsyncIterable, generator, async generator, or a function returning an Iterable or AsyncIterable")}var P=class{constructor(){this.value=void 0,this.valueStack=null,this.stack=new Array(100),this.lastFlushDepth=0,this.flushDepth=0,this.stateString=!1,this.stateStringEscape=!1,this.pendingByteSeq=null,this.pendingChunk=null,this.chunkOffset=0,this.jsonParseOffset=0}parseAndAppend(t,n){this.stack[this.lastFlushDepth-1]===C?(n&&(this.jsonParseOffset--,t="{"+t+"}"),Object.assign(this.valueStack.value,JSON.parse(t))):(n&&(this.jsonParseOffset--,t="["+t+"]"),H(this.valueStack.value,JSON.parse(t)))}prepareAddition(t){let{value:n}=this.valueStack;if(Array.isArray(n)?n.length!==0:Object.keys(n).length!==0){if(t[0]===",")return this.jsonParseOffset++,t.slice(1);if(t[0]!=="}"&&t[0]!=="]")return this.jsonParseOffset-=3,"[[]"+t}return t}flush(t,n,r){let i=t.slice(n,r);if(this.jsonParseOffset=this.chunkOffset+n,this.pendingChunk!==null&&(i=this.pendingChunk+i,this.jsonParseOffset-=this.pendingChunk.length,this.pendingChunk=null),this.flushDepth===this.lastFlushDepth)this.flushDepth>0?this.parseAndAppend(this.prepareAddition(i),!0):(this.value=JSON.parse(i),this.valueStack={value:this.value,prev:null});else if(this.flushDepth>this.lastFlushDepth){for(let s=this.flushDepth-1;s>=this.lastFlushDepth;s--)i+=this.stack[s]===C?"}":"]";this.lastFlushDepth===0?(this.value=JSON.parse(i),this.valueStack={value:this.value,prev:null}):this.parseAndAppend(this.prepareAddition(i),!0);for(let s=this.lastFlushDepth||1;s<this.flushDepth;s++){let l=this.valueStack.value;if(this.stack[s-1]===C){let g;for(g in l);l=l[g]}else l=l[l.length-1];this.valueStack={value:l,prev:this.valueStack}}}else{i=this.prepareAddition(i);for(let s=this.lastFlushDepth-1;s>=this.flushDepth;s--)this.jsonParseOffset--,i=(this.stack[s]===C?"{":"[")+i;this.parseAndAppend(i,!1);for(let s=this.lastFlushDepth-1;s>=this.flushDepth;s--)this.valueStack=this.valueStack.prev}this.lastFlushDepth=this.flushDepth}push(t){if(typeof t!="string"){if(this.pendingByteSeq!==null){let s=t;t=new Uint8Array(this.pendingByteSeq.length+s.length),t.set(this.pendingByteSeq),t.set(s,this.pendingByteSeq.length),this.pendingByteSeq=null}if(t[t.length-1]>127)for(let s=0;s<t.length;s++){let l=t[t.length-1-s];if(l>>6===3){s++,(s!==4&&l>>3===30||s!==3&&l>>4===14||s!==2&&l>>5===6)&&(this.pendingByteSeq=t.slice(t.length-s),t=t.slice(0,-s));break}}t=Y.decode(t)}let n=t.length,r=0,i=0;t:for(let s=0;s<n;s++){if(this.stateString){for(;s<n;s++)if(this.stateStringEscape)this.stateStringEscape=!1;else switch(t.charCodeAt(s)){case 34:this.stateString=!1;continue t;case 92:this.stateStringEscape=!0}break}switch(t.charCodeAt(s)){case 34:this.stateString=!0,this.stateStringEscape=!1;break;case 44:i=s;break;case 123:i=s+1,this.stack[this.flushDepth++]=C;break;case 91:i=s+1,this.stack[this.flushDepth++]=U;break;case 93:case 125:i=s+1,this.flushDepth--,this.flushDepth<this.lastFlushDepth&&(this.flush(t,r,i),r=i);break;case 9:case 10:case 13:case 32:r===s&&r++,i===s&&i++;break}}i>r&&this.flush(t,r,i),i<n&&(this.pendingChunk!==null?this.pendingChunk+=t:this.pendingChunk=t.slice(i,n)),this.chunkOffset+=n}finish(){return this.pendingChunk!==null&&(this.flush("",0,0),this.pendingChunk=null),this.value}};function E(e){return/[^\x20\x21\x23-\x5B\x5D-\uD799]/.test(e)?JSON.stringify(e):'"'+e+'"'}function*m(e,t,n){(t===null||Array.isArray(t)||typeof t!="object")&&(t={replacer:t,space:n});let r=Number(t.highWaterMark)||16384,i=B(t.replacer);n=N(t.space);let s=new Map,l=[],g={"":e},u=null,x=()=>D("",e),y=g,d=!0,h=[""],c=0,a="",k=Object.keys;if(Array.isArray(i)){let f=i;k=()=>f,i=null}for(;x(),!((a.length>=r||u===null)&&(yield a,a="",u===null)););function w(){if(c===0&&(h=k(y),a+="{"),c===h.length){a+=n&&!d?`
${n.repeat(l.length-1)}}`:"}",A();return}let f=h[c++];D(f,y[f])}function o(){if(c===0&&(a+="["),c===y.length){a+=n&&!d?`
${n.repeat(l.length-1)}]`:"]",A();return}D(c,y[c++])}function j(f){if(d?d=!1:a+=",",n&&u!==null&&(a+=`
${n.repeat(l.length)}`),x===w){let p=s.get(f);p===void 0&&s.set(f,p=E(f)+(n?": ":":")),a+=p}}function D(f,p){if(p=F(y,f,p,i),p===null||typeof p!="object")(x!==w||p!==void 0)&&(j(f),b(p));else{if(l.includes(p))throw new TypeError("Converting circular structure to JSON");j(f),l.push(p),S(),x=Array.isArray(p)?o:w,y=p,d=!0,c=0}}function b(f){switch(typeof f){case"string":a+=E(f);break;case"number":a+=Number.isFinite(f)?String(f):"null";break;case"boolean":a+=f?"true":"false";break;case"undefined":case"object":a+="null";break;default:throw new TypeError(`Do not know how to serialize a ${f.constructor?.name||typeof f}`)}}function S(){u={keys:h,index:c,prev:u}}function A(){l.pop();let f=l.length>0?l[l.length-1]:g;x=Array.isArray(f)?o:w,y=f,d=!1,h=u.keys,c=u.index,u=u.prev}}var Q=typeof Object.hasOwn=="function"?Object.hasOwn:(e,t)=>Object.hasOwnProperty.call(e,t),X={8:"\\b",9:"\\t",10:"\\n",12:"\\f",13:"\\r",34:'\\"',92:"\\\\"},Z=Uint8Array.from({length:2048},(e,t)=>Q(X,t)?2:t<32?6:t<128?1:2);function R(e){return e>=55296&&e<=56319}function v(e){return e>=56320&&e<=57343}function T(e){if(!/[^\x20\x21\x23-\x5B\x5D-\x7F]/.test(e))return e.length+2;let t=0,n=!1;for(let r=0;r<e.length;r++){let i=e.charCodeAt(r);if(i<2048)t+=Z[i];else if(R(i)){t+=6,n=!0;continue}else v(i)?t=n?t-2:t+6:t+=3;n=!1}return t+2}function tt(e){let t=0;return e<0&&(t=1,e=-e),e>=1e9&&(t+=9,e=(e-e%1e9)/1e9),e>=1e4?e>=1e6?t+(e>=1e8?9:e>=1e7?8:7):t+(e>=1e5?6:5):t+(e>=100?e>=1e3?4:3:e>=10?2:1)}function et(e){switch(typeof e){case"string":return T(e);case"number":return Number.isFinite(e)?Number.isInteger(e)?tt(e):String(e).length:4;case"boolean":return e?4:5;case"undefined":case"object":return 4;default:return 0}}function nt(e){return e=N(e),typeof e=="string"?e.length:0}function q(e,t,n){(t===null||Array.isArray(t)||typeof t!="object")&&(t={replacer:t,space:n});let r=!!t.continueOnCircular,i=B(t.replacer),s=Object.keys;if(Array.isArray(i)){let k=i;s=()=>k,i=null}n=nt(n);let l=new Map,g=new Map,u=[],x=new Set,y={"":e},d=!1,h=0,c=0;return a(y,"",e),h===0&&(h+=9),{bytes:isNaN(h)?1/0:h,circular:[...x]};function a(k,w,o){if(!d)if(o=F(k,w,o,i),o===null||typeof o!="object")(o!==void 0||Array.isArray(k))&&(h+=et(o));else{if(u.includes(o)){x.add(o),h+=4,r||(d=!0);return}if(g.has(o)){h+=g.get(o);return}c++;let j=c,D=h,b=0;if(u.push(o),Array.isArray(o)){b=o.length;for(let S=0;S<b;S++)a(o,S,o[S])}else{let S=h;for(let A of s(o))if(a(o,A,o[A]),S!==h){let f=l.get(A);f===void 0&&l.set(A,f=T(A)+(n>0?2:1)),h+=f,b++,S=h}}h+=b===0?2:1+b,n>0&&b>0&&(h+=(1+u.length*n)*b+1+(u.length-1)*n),u.pop(),j!==c&&g.set(o,h-D)}}}function J(e){return I(O(e)?e:async function*(){let t=e.getReader();try{for(;;){let{value:n,done:r}=await t.read();if(r)break;yield n}}finally{t.releaseLock()}})}function z(e,t,n){return typeof ReadableStream.from=="function"?ReadableStream.from(m(e,t,n)):new ReadableStream({start(){this.generator=m(e,t,n)},pull(r){let{value:i,done:s}=this.generator.next();s?r.close():r.enqueue(i)},cancel(){this.generator=null}})}return $(it);})();
var exports=(()=>{var P=Object.defineProperty;var K=Object.getOwnPropertyDescriptor;var M=Object.getOwnPropertyNames;var V=Object.prototype.hasOwnProperty;var W=(t,e)=>{for(var n in e)P(t,n,{get:e[n],enumerable:!0})},_=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of M(e))!V.call(t,i)&&i!==n&&P(t,i,{get:()=>e[i],enumerable:!(s=K(e,i))||s.enumerable});return t};var $=t=>_(P({},"__esModule",{value:!0}),t);var st={};W(st,{createStringifyWebStream:()=>z,parseChunked:()=>N,parseFromWebStream:()=>J,stringifyChunked:()=>C,stringifyInfo:()=>q});function j(t){return typeof t=="object"&&t!==null&&(typeof t[Symbol.iterator]=="function"||typeof t[Symbol.asyncIterator]=="function")}function F(t,e,n,s){switch(n&&typeof n.toJSON=="function"&&(n=n.toJSON()),s!==null&&(n=s.call(t,String(e),n)),typeof n){case"function":case"symbol":n=void 0;break;case"object":if(n!==null){let i=n.constructor;(i===String||i===Number||i===Boolean)&&(n=n.valueOf())}break}return n}function U(t){return typeof t=="function"?t:Array.isArray(t)?[...new Set(t.map(n=>{let s=n&&n.constructor;return s===String||s===Number?String(n):null}).filter(n=>typeof n=="string"))]:null}function R(t){return typeof t=="number"?!Number.isFinite(t)||t<1?!1:" ".repeat(Math.min(t,10)):typeof t=="string"&&t.slice(0,10)||!1}function B(t,e){(t===null||Array.isArray(t)||typeof t!="object")&&(t={replacer:t,space:e});let n=U(t.replacer),s=Object.keys;if(Array.isArray(n)){let i=n;s=()=>i,n=null}return{...t,replacer:n,getKeys:s,space:R(t.space)}}var O=1,Y=2,G=new TextDecoder;function H(t,e){return t.name==="SyntaxError"&&e.jsonParseOffset&&(t.message=t.message.replace(/at position (\d+)/,(n,s)=>"at position "+(Number(s)+e.jsonParseOffset))),t}function Q(t,e){let n=t.length;t.length+=e.length;for(let s=0;s<e.length;s++)t[n+s]=e[s]}async function N(t){let e=typeof t=="function"?t():t;if(j(e)){let n=new E;try{for await(let s of e){if(typeof s!="string"&&!ArrayBuffer.isView(s))throw new TypeError("Invalid chunk: Expected string, TypedArray or Buffer");n.push(s)}return n.finish()}catch(s){throw H(s,n)}}throw new TypeError("Invalid chunk emitter: Expected an Iterable, AsyncIterable, generator, async generator, or a function returning an Iterable or AsyncIterable")}var E=class{constructor(){this.value=void 0,this.valueStack=null,this.stack=new Array(100),this.lastFlushDepth=0,this.flushDepth=0,this.stateString=!1,this.stateStringEscape=!1,this.pendingByteSeq=null,this.pendingChunk=null,this.chunkOffset=0,this.jsonParseOffset=0}parseAndAppend(e,n){this.stack[this.lastFlushDepth-1]===O?(n&&(this.jsonParseOffset--,e="{"+e+"}"),Object.assign(this.valueStack.value,JSON.parse(e))):(n&&(this.jsonParseOffset--,e="["+e+"]"),Q(this.valueStack.value,JSON.parse(e)))}prepareAddition(e){let{value:n}=this.valueStack;if(Array.isArray(n)?n.length!==0:Object.keys(n).length!==0){if(e[0]===",")return this.jsonParseOffset++,e.slice(1);if(e[0]!=="}"&&e[0]!=="]")return this.jsonParseOffset-=3,"[[]"+e}return e}flush(e,n,s){let i=e.slice(n,s);if(this.jsonParseOffset=this.chunkOffset+n,this.pendingChunk!==null&&(i=this.pendingChunk+i,this.jsonParseOffset-=this.pendingChunk.length,this.pendingChunk=null),this.flushDepth===this.lastFlushDepth)this.flushDepth>0?this.parseAndAppend(this.prepareAddition(i),!0):(this.value=JSON.parse(i),this.valueStack={value:this.value,prev:null});else if(this.flushDepth>this.lastFlushDepth){for(let r=this.flushDepth-1;r>=this.lastFlushDepth;r--)i+=this.stack[r]===O?"}":"]";this.lastFlushDepth===0?(this.value=JSON.parse(i),this.valueStack={value:this.value,prev:null}):this.parseAndAppend(this.prepareAddition(i),!0);for(let r=this.lastFlushDepth||1;r<this.flushDepth;r++){let l=this.valueStack.value;if(this.stack[r-1]===O){let x;for(x in l);l=l[x]}else l=l[l.length-1];this.valueStack={value:l,prev:this.valueStack}}}else{i=this.prepareAddition(i);for(let r=this.lastFlushDepth-1;r>=this.flushDepth;r--)this.jsonParseOffset--,i=(this.stack[r]===O?"{":"[")+i;this.parseAndAppend(i,!1);for(let r=this.lastFlushDepth-1;r>=this.flushDepth;r--)this.valueStack=this.valueStack.prev}this.lastFlushDepth=this.flushDepth}push(e){if(typeof e!="string"){if(this.pendingByteSeq!==null){let r=e;e=new Uint8Array(this.pendingByteSeq.length+r.length),e.set(this.pendingByteSeq),e.set(r,this.pendingByteSeq.length),this.pendingByteSeq=null}if(e[e.length-1]>127)for(let r=0;r<e.length;r++){let l=e[e.length-1-r];if(l>>6===3){r++,(r!==4&&l>>3===30||r!==3&&l>>4===14||r!==2&&l>>5===6)&&(this.pendingByteSeq=e.slice(e.length-r),e=e.slice(0,-r));break}}e=G.decode(e)}let n=e.length,s=0,i=0;t:for(let r=0;r<n;r++){if(this.stateString){for(;r<n;r++)if(this.stateStringEscape)this.stateStringEscape=!1;else switch(e.charCodeAt(r)){case 34:this.stateString=!1;continue t;case 92:this.stateStringEscape=!0}break}switch(e.charCodeAt(r)){case 34:this.stateString=!0,this.stateStringEscape=!1;break;case 44:i=r;break;case 123:i=r+1,this.stack[this.flushDepth++]=O;break;case 91:i=r+1,this.stack[this.flushDepth++]=Y;break;case 93:case 125:i=r+1,this.flushDepth--,this.flushDepth<this.lastFlushDepth&&(this.flush(e,s,i),s=i);break;case 9:case 10:case 13:case 32:s===r&&s++,i===r&&i++;break}}i>s&&this.flush(e,s,i),i<n&&(this.pendingChunk!==null?this.pendingChunk+=e:this.pendingChunk=e.slice(i,n)),this.chunkOffset+=n}finish(){return this.pendingChunk!==null&&(this.flush("",0,0),this.pendingChunk=null),this.value}};function L(t){return/[^\x20\x21\x23-\x5B\x5D-\uD799]/.test(t)?JSON.stringify(t):'"'+t+'"'}function*C(t,...e){let{replacer:n,getKeys:s,space:i,...r}=B(...e),l=Number(r.highWaterMark)||16384,x=new Map,g=[],w={"":t},u=null,k=()=>D("",t),y=w,a=!0,S=[""],p=0,h="";for(;k(),!((h.length>=l||u===null)&&(yield h,h="",u===null)););function A(){if(p===0&&(S=s(y),h+="{"),p===S.length){h+=i&&!a?`
${i.repeat(g.length-1)}}`:"}",b();return}let f=S[p++];D(f,y[f])}function m(){if(p===0&&(h+="["),p===y.length){h+=i&&!a?`
${i.repeat(g.length-1)}]`:"]",b();return}D(p,y[p++])}function o(f){if(a?a=!1:h+=",",i&&u!==null&&(h+=`
${i.repeat(g.length)}`),k===A){let c=x.get(f);c===void 0&&x.set(f,c=L(f)+(i?": ":":")),h+=c}}function D(f,c){if(c=F(y,f,c,n),c===null||typeof c!="object")(k!==A||c!==void 0)&&(o(f),I(c));else{if(g.includes(c))throw new TypeError("Converting circular structure to JSON");o(f),g.push(c),d(),k=Array.isArray(c)?m:A,y=c,a=!0,p=0}}function I(f){switch(typeof f){case"string":h+=L(f);break;case"number":h+=Number.isFinite(f)?String(f):"null";break;case"boolean":h+=f?"true":"false";break;case"undefined":case"object":h+="null";break;default:throw new TypeError(`Do not know how to serialize a ${f.constructor?.name||typeof f}`)}}function d(){u={keys:S,index:p,prev:u}}function b(){g.pop();let f=g.length>0?g[g.length-1]:w;k=Array.isArray(f)?m:A,y=f,a=!1,S=u.keys,p=u.index,u=u.prev}}var X=typeof Object.hasOwn=="function"?Object.hasOwn:(t,e)=>Object.hasOwnProperty.call(t,e),Z={8:"\\b",9:"\\t",10:"\\n",12:"\\f",13:"\\r",34:'\\"',92:"\\\\"},v=Uint8Array.from({length:2048},(t,e)=>X(Z,e)?2:e<32?6:e<128?1:2);function tt(t){return t>=55296&&t<=56319}function et(t){return t>=56320&&t<=57343}function T(t){if(!/[^\x20\x21\x23-\x5B\x5D-\x7F]/.test(t))return t.length+2;let e=0,n=!1;for(let s=0;s<t.length;s++){let i=t.charCodeAt(s);if(i<2048)e+=v[i];else if(tt(i)){e+=6,n=!0;continue}else et(i)?e=n?e-2:e+6:e+=3;n=!1}return e+2}function nt(t){let e=0;return t<0&&(e=1,t=-t),t>=1e9&&(e+=9,t=(t-t%1e9)/1e9),t>=1e4?t>=1e6?e+(t>=1e8?9:t>=1e7?8:7):e+(t>=1e5?6:5):e+(t>=100?t>=1e3?4:3:t>=10?2:1)}function it(t){switch(typeof t){case"string":return T(t);case"number":return Number.isFinite(t)?Number.isInteger(t)?nt(t):String(t).length:4;case"boolean":return t?4:5;case"undefined":case"object":return 4;default:return 0}}function q(t,...e){let{replacer:n,getKeys:s,...i}=B(...e),r=!!i.continueOnCircular,l=i.space?.length||0,x=new Map,g=new Map,w=new Set,u=[],k={"":t},y=!1,a=0,S=0,p=0;return h(k,"",t),a===0&&(a+=9),{bytes:isNaN(a)?1/0:a+S,spaceBytes:l>0&&isNaN(a)?1/0:S,circular:[...w]};function h(A,m,o){if(!y)if(o=F(A,m,o,n),o===null||typeof o!="object")(o!==void 0||Array.isArray(A))&&(a+=it(o));else{if(u.includes(o)){w.add(o),a+=4,r||(y=!0);return}if(g.has(o)){a+=g.get(o);return}p++;let D=p,I=a,d=0;if(u.push(o),Array.isArray(o)){d=o.length;for(let b=0;b<d;b++)h(o,b,o[b])}else{let b=a;for(let f of s(o))if(h(o,f,o[f]),b!==a){let c=x.get(f);c===void 0&&x.set(f,c=T(f)+1),a+=c,d++,b=a}}a+=d===0?2:1+d,l>0&&d>0&&(S+=(Array.isArray(o)?0:d)+(1+u.length*l)*(d+1)-l),u.pop(),D!==p&&g.set(o,a-I)}}}function J(t){return N(j(t)?t:async function*(){let e=t.getReader();try{for(;;){let{value:n,done:s}=await e.read();if(s)break;yield n}}finally{e.releaseLock()}})}function z(t,e,n){return typeof ReadableStream.from=="function"?ReadableStream.from(C(t,e,n)):new ReadableStream({start(){this.generator=C(t,e,n)},pull(s){let{value:i,done:r}=this.generator.next();r?s.close():s.enqueue(i)},cancel(){this.generator=null}})}return $(st);})();

@@ -12,0 +12,0 @@ return exports;

@@ -20,3 +20,4 @@ declare module '@discoveryjs/json-ext' {

bytes: number;
circular: Object[];
spaceBytes: number;
circular: object[];
};

@@ -23,0 +24,0 @@

{
"name": "@discoveryjs/json-ext",
"version": "0.6.1",
"version": "0.6.2",
"description": "A set of utilities that extend the use of JSON",

@@ -30,4 +30,3 @@ "keywords": [

"require": "./cjs/index.cjs",
"import": "./src/index.js",
"types": "./index.d.ts"
"import": "./src/index.js"
},

@@ -56,6 +55,6 @@ "./dist/*": "./dist/*",

"chalk": "^4.1.0",
"esbuild": "^0.21.5",
"esbuild": "^0.24.0",
"eslint": "^8.57.0",
"mocha": "^9.2.2",
"rollup": "^2.67.3"
"rollup": "^2.79.2"
},

@@ -62,0 +61,0 @@ "files": [

@@ -8,24 +8,26 @@ # json-ext

A set of utilities that extend the use of JSON:
A set of utilities designed to extend JSON's capabilities, especially for handling large JSON data (over 100MB) efficiently:
- [parseChunked()](#parsechunked) – functions like [`JSON.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse) but iterates over chunks, reconstructing the result object.
- [stringifyChunked()](#stringifychunked) – functions like [`JSON.stringify()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify), but returns a generator yielding strings instead of a single string.
- [stringifyInfo()](#stringifyinfo) – returns an object with the expected overall size of the stringify operation and any circular references.
- [parseFromWebStream()](#parsefromwebstream) – a helper function to consume chunks from a Web Stream.
- [createStringifyWebStream()](#createstringifywebstream) – a helper to create a Web Stream.
- [parseChunked()](#parsechunked) – Parses JSON incrementally; similar to [`JSON.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse), but processing JSON data in chunks.
- [stringifyChunked()](#stringifychunked) – Converts JavaScript objects to JSON incrementally; similar to [`JSON.stringify()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify), but returns a generator that yields JSON strings in parts.
- [stringifyInfo()](#stringifyinfo) – Estimates the size of the `JSON.stringify()` result and identifies circular references without generating the JSON.
- [parseFromWebStream()](#parsefromwebstream) – A helper function to parse JSON chunks directly from a Web Stream.
- [createStringifyWebStream()](#createstringifywebstream) – A helper function to generate JSON data as a Web Stream.
Features:
### Key Features
- Fast and memory-efficient
- Compatible with browsers, Node.js, Deno, Bun
- Supports Node.js and Web streams
- Dual package: ESM and CommonJS
- No dependencies
- Size: 9.4Kb (minified), 3.6Kb (min+gzip)
- Optimized to handle large JSON data with minimal resource usage (see [benchmarks](./benchmarks/README.md))
- Works seamlessly with browsers, Node.js, Deno, and Bun
- Supports both Node.js and Web streams
- Available in both ESM and CommonJS
- TypeScript typings included
- No external dependencies
- Compact size: 9.4Kb (minified), 3.8Kb (min+gzip)
## Why?
### Why json-ext?
- Prevents main thread freezing during large JSON parsing by distributing the process over time.
- Handles large JSON processing (e.g., V8 has a limitation for strings ~500MB, making JSON larger than 500MB unmanageable).
- Reduces memory pressure. `JSON.parse()` and `JSON.stringify()` require the entire JSON content before processing. `parseChunked()` and `stringifyChunked()` allow processing and sending data incrementally, avoiding large memory consumption at a single time point and reducing GC pressure.
- **Handles large JSON files**: Overcomes the limitations of V8 for strings larger than ~500MB, enabling the processing of huge JSON data.
- **Prevents main thread blocking**: Distributes parsing and stringifying over time, ensuring the main thread remains responsive during heavy JSON operations.
- **Reduces memory usage**: Traditional `JSON.parse()` and `JSON.stringify()` require loading entire data into memory, leading to high memory consumption and increased garbage collection pressure. `parseChunked()` and `stringifyChunked()` process data incrementally, optimizing memory usage.
- **Size estimation**: `stringifyInfo()` allows estimating the size of resulting JSON before generating it, enabling better decision-making for JSON generation strategies.

@@ -130,23 +132,36 @@ ## Install

```js
import { stringifyChunked } from '@discoveryjs/json-ext';
- Getting an array of chunks:
```js
const chunks = [...stringifyChunked(data)];
```
- Iterating over chunks:
```js
for (const chunk of stringifyChunked(data)) {
console.log(chunk);
}
```
- Specifying the minimum size of a chunk with `highWaterMark` option:
```js
const data = [1, "hello world", 42];
const chunks = [...stringifyChunked(data)];
// or
for (const chunk of stringifyChunked(data)) {
console.log(chunk);
}
```
console.log([...stringifyChunked(data)]); // default 16kB
// ['[1,"hello world",42]']
Examples:
console.log([...stringifyChunked(data, { highWaterMark: 16 })]);
// ['[1,"hello world"', ',42]']
- Streaming into a file (Node.js):
console.log([...stringifyChunked(data, { highWaterMark: 1 })]);
// ['[1', ',"hello world"', ',42', ']']
```
- Streaming into a stream with a `Promise` (modern Node.js):
```js
import { pipeline } from 'node:stream/promises';
import fs from 'node:fs';
import { Readable } from 'node:stream';
Readable.from(stringifyChunked(data))
.pipe(fs.createWriteStream('path/to/file.json'));
await pipeline(
stringifyChunked(data),
fs.createWriteStream('path/to/file.json')
);
```
- Wrapping into a `Promise` for piping into a writable Node.js stream:
- Wrapping into a `Promise` streaming into a stream (legacy Node.js):
```js

@@ -163,3 +178,3 @@ import { Readable } from 'node:stream';

```
- Write into a file synchronously:
- Writing into a file synchronously:
> Note: Slower than `JSON.stringify()` but uses much less heap space and has no limitation on string length

@@ -222,4 +237,5 @@ ```js

type StringifyInfoResult = {
minLength: number;
circular: Object[]; // list of circular references
bytes: number; // size of JSON in bytes
spaceBytes: number; // size of white spaces in bytes (when space option used)
circular: object[]; // list of circular references
};

@@ -235,5 +251,6 @@ ```

console.log(stringifyInfo({ test: true }));
console.log(stringifyInfo({ test: true }, null, 4));
// {
// bytes: 13, // Buffer.byteLength('{"test":true}')
// bytes: 20, // Buffer.byteLength('{\n "test": true\n}')
// spaceBytes: 7,
// circular: []

@@ -240,0 +257,0 @@ // }

@@ -1,6 +0,2 @@

import {
normalizeReplacer,
normalizeSpace,
replaceValue
} from './utils.js';
import { normalizeStringifyOptions, replaceValue } from './utils.js';

@@ -15,16 +11,8 @@ function encodeString(value) {

export function* stringifyChunked(value, optionsOrReplacer, space) {
if (optionsOrReplacer === null || Array.isArray(optionsOrReplacer) || typeof optionsOrReplacer !== 'object') {
optionsOrReplacer = {
replacer: optionsOrReplacer,
space
};
}
export function* stringifyChunked(value, ...args) {
const { replacer, getKeys, space, ...options } = normalizeStringifyOptions(...args);
const highWaterMark = Number(options.highWaterMark) || 0x4000; // 16kb by default
const highWaterMark = Number(optionsOrReplacer.highWaterMark) || 0x4000; // 16kb by default
let replacer = normalizeReplacer(optionsOrReplacer.replacer);
space = normalizeSpace(optionsOrReplacer.space);
const keyStrings = new Map();
const visited = [];
const stack = [];
const rootValue = { '': value };

@@ -38,11 +26,3 @@ let prevState = null;

let buffer = '';
let getKeys = Object.keys;
if (Array.isArray(replacer)) {
const allowlist = replacer;
getKeys = () => allowlist;
replacer = null;
}
while (true) {

@@ -71,3 +51,3 @@ state();

buffer += space && !stateEmpty
? `\n${space.repeat(visited.length - 1)}}`
? `\n${space.repeat(stack.length - 1)}}`
: '}';

@@ -90,3 +70,3 @@

buffer += space && !stateEmpty
? `\n${space.repeat(visited.length - 1)}]`
? `\n${space.repeat(stack.length - 1)}]`
: ']';

@@ -109,3 +89,3 @@

if (space && prevState !== null) {
buffer += `\n${space.repeat(visited.length)}`;
buffer += `\n${space.repeat(stack.length)}`;
}

@@ -135,3 +115,3 @@

// If the visited set does not change after adding a value, then it is already in the set
if (visited.includes(value)) {
if (stack.includes(value)) {
throw new TypeError('Converting circular structure to JSON');

@@ -141,3 +121,3 @@ }

printEntryPrelude(key);
visited.push(value);
stack.push(value);

@@ -185,4 +165,4 @@ pushState();

function popState() {
visited.pop();
const value = visited.length > 0 ? visited[visited.length - 1] : rootValue;
stack.pop();
const value = stack.length > 0 ? stack[stack.length - 1] : rootValue;

@@ -189,0 +169,0 @@ // restore state

@@ -1,6 +0,2 @@

import {
normalizeReplacer,
normalizeSpace,
replaceValue
} from './utils.js';
import { normalizeStringifyOptions, replaceValue } from './utils.js';

@@ -128,35 +124,15 @@ const hasOwn = typeof Object.hasOwn === 'function'

function spaceLength(space) {
space = normalizeSpace(space);
return typeof space === 'string' ? space.length : 0;
}
export function stringifyInfo(value, ...args) {
const { replacer, getKeys, ...options } = normalizeStringifyOptions(...args);
const continueOnCircular = Boolean(options.continueOnCircular);
const space = options.space?.length || 0;
export function stringifyInfo(value, optionsOrReplacer, space) {
if (optionsOrReplacer === null || Array.isArray(optionsOrReplacer) || typeof optionsOrReplacer !== 'object') {
optionsOrReplacer = {
replacer: optionsOrReplacer,
space
};
}
const continueOnCircular = Boolean(optionsOrReplacer.continueOnCircular);
let replacer = normalizeReplacer(optionsOrReplacer.replacer);
let getKeys = Object.keys;
if (Array.isArray(replacer)) {
const allowlist = replacer;
getKeys = () => allowlist;
replacer = null;
}
space = spaceLength(space);
const keysLength = new Map();
const visited = new Map();
const circular = new Set();
const stack = [];
const circular = new Set();
const root = { '': value };
let stop = false;
let bytes = 0;
let spaceBytes = 0;
let objects = 0;

@@ -172,3 +148,4 @@

return {
bytes: isNaN(bytes) ? Infinity : bytes,
bytes: isNaN(bytes) ? Infinity : bytes + spaceBytes,
spaceBytes: space > 0 && isNaN(bytes) ? Infinity : spaceBytes,
circular: [...circular]

@@ -237,3 +214,3 @@ };

if (keyLen === undefined) {
keysLength.set(key, keyLen = stringLength(key) + (space > 0 ? 2 : 1)); // "key":
keysLength.set(key, keyLen = stringLength(key) + 1); // "key":
}

@@ -254,5 +231,11 @@

if (space > 0 && valueLength > 0) {
bytes +=
(1 + stack.length * space) * valueLength + // for each key-value: \n{space}
1 + (stack.length - 1) * space; // for }
spaceBytes +=
// a space between ":" and a value for each object entry
(Array.isArray(value) ? 0 : valueLength) +
// the formula results from folding the following components:
// - for each key-value or element: ident + newline
// (1 + stack.length * space) * valueLength
// - ident (one space less) before "}" or "]" + newline
// (stack.length - 1) * space + 1
(1 + stack.length * space) * (valueLength + 1) - space;
}

@@ -259,0 +242,0 @@

@@ -75,1 +75,27 @@ export function isIterable(value) {

}
export function normalizeStringifyOptions(optionsOrReplacer, space) {
if (optionsOrReplacer === null || Array.isArray(optionsOrReplacer) || typeof optionsOrReplacer !== 'object') {
optionsOrReplacer = {
replacer: optionsOrReplacer,
space
};
}
let replacer = normalizeReplacer(optionsOrReplacer.replacer);
let getKeys = Object.keys;
if (Array.isArray(replacer)) {
const allowlist = replacer;
getKeys = () => allowlist;
replacer = null;
}
return {
...optionsOrReplacer,
replacer,
getKeys,
space: normalizeSpace(optionsOrReplacer.space)
};
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc