json-6
Version:
JSON for the ES6 era.
1,619 lines (1,344 loc) • 77.7 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = global || self, global.JSON5 = factory());
}(this, (function () { 'use strict';
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
var check = function (it) {
return it && it.Math == Math && it;
}; // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
var global_1 = // eslint-disable-next-line no-undef
check(typeof globalThis == 'object' && globalThis) || check(typeof window == 'object' && window) || check(typeof self == 'object' && self) || check(typeof commonjsGlobal == 'object' && commonjsGlobal) || // eslint-disable-next-line no-new-func
Function('return this')();
var fails = function (exec) {
try {
return !!exec();
} catch (error) {
return true;
}
};
var descriptors = !fails(function () {
return Object.defineProperty({}, 1, {
get: function () {
return 7;
}
})[1] != 7;
});
var nativePropertyIsEnumerable = {}.propertyIsEnumerable;
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; // Nashorn ~ JDK8 bug
var NASHORN_BUG = getOwnPropertyDescriptor && !nativePropertyIsEnumerable.call({
1: 2
}, 1); // `Object.prototype.propertyIsEnumerable` method implementation
// https://tc39.github.io/ecma262/#sec-object.prototype.propertyisenumerable
var f = NASHORN_BUG ? function propertyIsEnumerable(V) {
var descriptor = getOwnPropertyDescriptor(this, V);
return !!descriptor && descriptor.enumerable;
} : nativePropertyIsEnumerable;
var objectPropertyIsEnumerable = {
f: f
};
var createPropertyDescriptor = function (bitmap, value) {
return {
enumerable: !(bitmap & 1),
configurable: !(bitmap & 2),
writable: !(bitmap & 4),
value: value
};
};
var toString = {}.toString;
var classofRaw = function (it) {
return toString.call(it).slice(8, -1);
};
var split = ''.split; // fallback for non-array-like ES3 and non-enumerable old V8 strings
var indexedObject = fails(function () {
// throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
// eslint-disable-next-line no-prototype-builtins
return !Object('z').propertyIsEnumerable(0);
}) ? function (it) {
return classofRaw(it) == 'String' ? split.call(it, '') : Object(it);
} : Object;
// `RequireObjectCoercible` abstract operation
// https://tc39.github.io/ecma262/#sec-requireobjectcoercible
var requireObjectCoercible = function (it) {
if (it == undefined) throw TypeError("Can't call method on " + it);
return it;
};
var toIndexedObject = function (it) {
return indexedObject(requireObjectCoercible(it));
};
var isObject = function (it) {
return typeof it === 'object' ? it !== null : typeof it === 'function';
};
// https://tc39.github.io/ecma262/#sec-toprimitive
// instead of the ES6 spec version, we didn't implement @@toPrimitive case
// and the second argument - flag - preferred type is a string
var toPrimitive = function (input, PREFERRED_STRING) {
if (!isObject(input)) return input;
var fn, val;
if (PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val;
if (typeof (fn = input.valueOf) == 'function' && !isObject(val = fn.call(input))) return val;
if (!PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val;
throw TypeError("Can't convert object to primitive value");
};
var hasOwnProperty = {}.hasOwnProperty;
var has = function (it, key) {
return hasOwnProperty.call(it, key);
};
var document = global_1.document; // typeof document.createElement is 'object' in old IE
var EXISTS = isObject(document) && isObject(document.createElement);
var documentCreateElement = function (it) {
return EXISTS ? document.createElement(it) : {};
};
var ie8DomDefine = !descriptors && !fails(function () {
return Object.defineProperty(documentCreateElement('div'), 'a', {
get: function () {
return 7;
}
}).a != 7;
});
var nativeGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; // `Object.getOwnPropertyDescriptor` method
// https://tc39.github.io/ecma262/#sec-object.getownpropertydescriptor
var f$1 = descriptors ? nativeGetOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) {
O = toIndexedObject(O);
P = toPrimitive(P, true);
if (ie8DomDefine) try {
return nativeGetOwnPropertyDescriptor(O, P);
} catch (error) {
/* empty */
}
if (has(O, P)) return createPropertyDescriptor(!objectPropertyIsEnumerable.f.call(O, P), O[P]);
};
var objectGetOwnPropertyDescriptor = {
f: f$1
};
var anObject = function (it) {
if (!isObject(it)) {
throw TypeError(String(it) + ' is not an object');
}
return it;
};
var nativeDefineProperty = Object.defineProperty; // `Object.defineProperty` method
// https://tc39.github.io/ecma262/#sec-object.defineproperty
var f$2 = descriptors ? nativeDefineProperty : function defineProperty(O, P, Attributes) {
anObject(O);
P = toPrimitive(P, true);
anObject(Attributes);
if (ie8DomDefine) try {
return nativeDefineProperty(O, P, Attributes);
} catch (error) {
/* empty */
}
if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported');
if ('value' in Attributes) O[P] = Attributes.value;
return O;
};
var objectDefineProperty = {
f: f$2
};
var createNonEnumerableProperty = descriptors ? function (object, key, value) {
return objectDefineProperty.f(object, key, createPropertyDescriptor(1, value));
} : function (object, key, value) {
object[key] = value;
return object;
};
var setGlobal = function (key, value) {
try {
createNonEnumerableProperty(global_1, key, value);
} catch (error) {
global_1[key] = value;
}
return value;
};
var SHARED = '__core-js_shared__';
var store = global_1[SHARED] || setGlobal(SHARED, {});
var sharedStore = store;
var functionToString = Function.toString; // this helper broken in `3.4.1-3.4.4`, so we can't use `shared` helper
if (typeof sharedStore.inspectSource != 'function') {
sharedStore.inspectSource = function (it) {
return functionToString.call(it);
};
}
var inspectSource = sharedStore.inspectSource;
var WeakMap = global_1.WeakMap;
var nativeWeakMap = typeof WeakMap === 'function' && /native code/.test(inspectSource(WeakMap));
var shared = createCommonjsModule(function (module) {
(module.exports = function (key, value) {
return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {});
})('versions', []).push({
version: '3.6.4',
mode: 'global',
copyright: '© 2020 Denis Pushkarev (zloirock.ru)'
});
});
var id = 0;
var postfix = Math.random();
var uid = function (key) {
return 'Symbol(' + String(key === undefined ? '' : key) + ')_' + (++id + postfix).toString(36);
};
var keys = shared('keys');
var sharedKey = function (key) {
return keys[key] || (keys[key] = uid(key));
};
var hiddenKeys = {};
var WeakMap$1 = global_1.WeakMap;
var set, get, has$1;
var enforce = function (it) {
return has$1(it) ? get(it) : set(it, {});
};
var getterFor = function (TYPE) {
return function (it) {
var state;
if (!isObject(it) || (state = get(it)).type !== TYPE) {
throw TypeError('Incompatible receiver, ' + TYPE + ' required');
}
return state;
};
};
if (nativeWeakMap) {
var store$1 = new WeakMap$1();
var wmget = store$1.get;
var wmhas = store$1.has;
var wmset = store$1.set;
set = function (it, metadata) {
wmset.call(store$1, it, metadata);
return metadata;
};
get = function (it) {
return wmget.call(store$1, it) || {};
};
has$1 = function (it) {
return wmhas.call(store$1, it);
};
} else {
var STATE = sharedKey('state');
hiddenKeys[STATE] = true;
set = function (it, metadata) {
createNonEnumerableProperty(it, STATE, metadata);
return metadata;
};
get = function (it) {
return has(it, STATE) ? it[STATE] : {};
};
has$1 = function (it) {
return has(it, STATE);
};
}
var internalState = {
set: set,
get: get,
has: has$1,
enforce: enforce,
getterFor: getterFor
};
var redefine = createCommonjsModule(function (module) {
var getInternalState = internalState.get;
var enforceInternalState = internalState.enforce;
var TEMPLATE = String(String).split('String');
(module.exports = function (O, key, value, options) {
var unsafe = options ? !!options.unsafe : false;
var simple = options ? !!options.enumerable : false;
var noTargetGet = options ? !!options.noTargetGet : false;
if (typeof value == 'function') {
if (typeof key == 'string' && !has(value, 'name')) createNonEnumerableProperty(value, 'name', key);
enforceInternalState(value).source = TEMPLATE.join(typeof key == 'string' ? key : '');
}
if (O === global_1) {
if (simple) O[key] = value;else setGlobal(key, value);
return;
} else if (!unsafe) {
delete O[key];
} else if (!noTargetGet && O[key]) {
simple = true;
}
if (simple) O[key] = value;else createNonEnumerableProperty(O, key, value); // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
})(Function.prototype, 'toString', function toString() {
return typeof this == 'function' && getInternalState(this).source || inspectSource(this);
});
});
var path = global_1;
var aFunction = function (variable) {
return typeof variable == 'function' ? variable : undefined;
};
var getBuiltIn = function (namespace, method) {
return arguments.length < 2 ? aFunction(path[namespace]) || aFunction(global_1[namespace]) : path[namespace] && path[namespace][method] || global_1[namespace] && global_1[namespace][method];
};
var ceil = Math.ceil;
var floor = Math.floor; // `ToInteger` abstract operation
// https://tc39.github.io/ecma262/#sec-tointeger
var toInteger = function (argument) {
return isNaN(argument = +argument) ? 0 : (argument > 0 ? floor : ceil)(argument);
};
var min = Math.min; // `ToLength` abstract operation
// https://tc39.github.io/ecma262/#sec-tolength
var toLength = function (argument) {
return argument > 0 ? min(toInteger(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991
};
var max = Math.max;
var min$1 = Math.min; // Helper for a popular repeating case of the spec:
// Let integer be ? ToInteger(index).
// If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length).
var toAbsoluteIndex = function (index, length) {
var integer = toInteger(index);
return integer < 0 ? max(integer + length, 0) : min$1(integer, length);
};
var createMethod = function (IS_INCLUDES) {
return function ($this, el, fromIndex) {
var O = toIndexedObject($this);
var length = toLength(O.length);
var index = toAbsoluteIndex(fromIndex, length);
var value; // Array#includes uses SameValueZero equality algorithm
// eslint-disable-next-line no-self-compare
if (IS_INCLUDES && el != el) while (length > index) {
value = O[index++]; // eslint-disable-next-line no-self-compare
if (value != value) return true; // Array#indexOf ignores holes, Array#includes - not
} else for (; length > index; index++) {
if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
}
return !IS_INCLUDES && -1;
};
};
var arrayIncludes = {
// `Array.prototype.includes` method
// https://tc39.github.io/ecma262/#sec-array.prototype.includes
includes: createMethod(true),
// `Array.prototype.indexOf` method
// https://tc39.github.io/ecma262/#sec-array.prototype.indexof
indexOf: createMethod(false)
};
var indexOf = arrayIncludes.indexOf;
var objectKeysInternal = function (object, names) {
var O = toIndexedObject(object);
var i = 0;
var result = [];
var key;
for (key in O) !has(hiddenKeys, key) && has(O, key) && result.push(key); // Don't enum bug & hidden keys
while (names.length > i) if (has(O, key = names[i++])) {
~indexOf(result, key) || result.push(key);
}
return result;
};
// IE8- don't enum bug keys
var enumBugKeys = ['constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf'];
var hiddenKeys$1 = enumBugKeys.concat('length', 'prototype'); // `Object.getOwnPropertyNames` method
// https://tc39.github.io/ecma262/#sec-object.getownpropertynames
var f$3 = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
return objectKeysInternal(O, hiddenKeys$1);
};
var objectGetOwnPropertyNames = {
f: f$3
};
var f$4 = Object.getOwnPropertySymbols;
var objectGetOwnPropertySymbols = {
f: f$4
};
var ownKeys = getBuiltIn('Reflect', 'ownKeys') || function ownKeys(it) {
var keys = objectGetOwnPropertyNames.f(anObject(it));
var getOwnPropertySymbols = objectGetOwnPropertySymbols.f;
return getOwnPropertySymbols ? keys.concat(getOwnPropertySymbols(it)) : keys;
};
var copyConstructorProperties = function (target, source) {
var keys = ownKeys(source);
var defineProperty = objectDefineProperty.f;
var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f;
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (!has(target, key)) defineProperty(target, key, getOwnPropertyDescriptor(source, key));
}
};
var replacement = /#|\.prototype\./;
var isForced = function (feature, detection) {
var value = data[normalize(feature)];
return value == POLYFILL ? true : value == NATIVE ? false : typeof detection == 'function' ? fails(detection) : !!detection;
};
var normalize = isForced.normalize = function (string) {
return String(string).replace(replacement, '.').toLowerCase();
};
var data = isForced.data = {};
var NATIVE = isForced.NATIVE = 'N';
var POLYFILL = isForced.POLYFILL = 'P';
var isForced_1 = isForced;
var getOwnPropertyDescriptor$1 = objectGetOwnPropertyDescriptor.f;
/*
options.target - name of the target object
options.global - target is the global object
options.stat - export as static methods of target
options.proto - export as prototype methods of target
options.real - real prototype method for the `pure` version
options.forced - export even if the native feature is available
options.bind - bind methods to the target, required for the `pure` version
options.wrap - wrap constructors to preventing global pollution, required for the `pure` version
options.unsafe - use the simple assignment of property instead of delete + defineProperty
options.sham - add a flag to not completely full polyfills
options.enumerable - export as enumerable property
options.noTargetGet - prevent calling a getter on target
*/
var _export = function (options, source) {
var TARGET = options.target;
var GLOBAL = options.global;
var STATIC = options.stat;
var FORCED, target, key, targetProperty, sourceProperty, descriptor;
if (GLOBAL) {
target = global_1;
} else if (STATIC) {
target = global_1[TARGET] || setGlobal(TARGET, {});
} else {
target = (global_1[TARGET] || {}).prototype;
}
if (target) for (key in source) {
sourceProperty = source[key];
if (options.noTargetGet) {
descriptor = getOwnPropertyDescriptor$1(target, key);
targetProperty = descriptor && descriptor.value;
} else targetProperty = target[key];
FORCED = isForced_1(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced); // contained in target
if (!FORCED && targetProperty !== undefined) {
if (typeof sourceProperty === typeof targetProperty) continue;
copyConstructorProperties(sourceProperty, targetProperty);
} // add a flag to not completely full polyfills
if (options.sham || targetProperty && targetProperty.sham) {
createNonEnumerableProperty(sourceProperty, 'sham', true);
} // extend global
redefine(target, key, sourceProperty, options);
}
};
var createMethod$1 = function (CONVERT_TO_STRING) {
return function ($this, pos) {
var S = String(requireObjectCoercible($this));
var position = toInteger(pos);
var size = S.length;
var first, second;
if (position < 0 || position >= size) return CONVERT_TO_STRING ? '' : undefined;
first = S.charCodeAt(position);
return first < 0xD800 || first > 0xDBFF || position + 1 === size || (second = S.charCodeAt(position + 1)) < 0xDC00 || second > 0xDFFF ? CONVERT_TO_STRING ? S.charAt(position) : first : CONVERT_TO_STRING ? S.slice(position, position + 2) : (first - 0xD800 << 10) + (second - 0xDC00) + 0x10000;
};
};
var stringMultibyte = {
// `String.prototype.codePointAt` method
// https://tc39.github.io/ecma262/#sec-string.prototype.codepointat
codeAt: createMethod$1(false),
// `String.prototype.at` method
// https://github.com/mathiasbynens/String.prototype.at
charAt: createMethod$1(true)
};
var codeAt = stringMultibyte.codeAt; // `String.prototype.codePointAt` method
// https://tc39.github.io/ecma262/#sec-string.prototype.codepointat
_export({
target: 'String',
proto: true
}, {
codePointAt: function codePointAt(pos) {
return codeAt(this, pos);
}
});
var aFunction$1 = function (it) {
if (typeof it != 'function') {
throw TypeError(String(it) + ' is not a function');
}
return it;
};
var functionBindContext = function (fn, that, length) {
aFunction$1(fn);
if (that === undefined) return fn;
switch (length) {
case 0:
return function () {
return fn.call(that);
};
case 1:
return function (a) {
return fn.call(that, a);
};
case 2:
return function (a, b) {
return fn.call(that, a, b);
};
case 3:
return function (a, b, c) {
return fn.call(that, a, b, c);
};
}
return function ()
/* ...args */
{
return fn.apply(that, arguments);
};
};
var call = Function.call;
var entryUnbind = function (CONSTRUCTOR, METHOD, length) {
return functionBindContext(call, global_1[CONSTRUCTOR].prototype[METHOD], length);
};
var codePointAt = entryUnbind('String', 'codePointAt');
var fromCharCode = String.fromCharCode;
var nativeFromCodePoint = String.fromCodePoint; // length should be 1, old FF problem
var INCORRECT_LENGTH = !!nativeFromCodePoint && nativeFromCodePoint.length != 1; // `String.fromCodePoint` method
// https://tc39.github.io/ecma262/#sec-string.fromcodepoint
_export({
target: 'String',
stat: true,
forced: INCORRECT_LENGTH
}, {
fromCodePoint: function fromCodePoint(x) {
// eslint-disable-line no-unused-vars
var elements = [];
var length = arguments.length;
var i = 0;
var code;
while (length > i) {
code = +arguments[i++];
if (toAbsoluteIndex(code, 0x10FFFF) !== code) throw RangeError(code + ' is not a valid code point');
elements.push(code < 0x10000 ? fromCharCode(code) : fromCharCode(((code -= 0x10000) >> 10) + 0xD800, code % 0x400 + 0xDC00));
}
return elements.join('');
}
});
var fromCodePoint = path.String.fromCodePoint;
var json6 = createCommonjsModule(function (module, exports) {
const version = "1.1.1";
const VALUE_UNDEFINED = -1;
const VALUE_UNSET = 0;
const VALUE_NULL = 1;
const VALUE_TRUE = 2;
const VALUE_FALSE = 3;
const VALUE_STRING = 4;
const VALUE_NUMBER = 5;
const VALUE_OBJECT = 6;
const VALUE_ARRAY = 7;
const VALUE_NEG_NAN = 8;
const VALUE_NAN = 9;
const VALUE_NEG_INFINITY = 10;
const VALUE_INFINITY = 11; // const VALUE_DATE = 12 // unused yet
const VALUE_EMPTY = 13; // [,] makes an array with 'empty item'
const WORD_POS_RESET = 0;
const WORD_POS_TRUE_1 = 1;
const WORD_POS_TRUE_2 = 2;
const WORD_POS_TRUE_3 = 3;
const WORD_POS_FALSE_1 = 5;
const WORD_POS_FALSE_2 = 6;
const WORD_POS_FALSE_3 = 7;
const WORD_POS_FALSE_4 = 8;
const WORD_POS_NULL_1 = 9;
const WORD_POS_NULL_2 = 10;
const WORD_POS_NULL_3 = 11;
const WORD_POS_UNDEFINED_1 = 12;
const WORD_POS_UNDEFINED_2 = 13;
const WORD_POS_UNDEFINED_3 = 14;
const WORD_POS_UNDEFINED_4 = 15;
const WORD_POS_UNDEFINED_5 = 16;
const WORD_POS_UNDEFINED_6 = 17;
const WORD_POS_UNDEFINED_7 = 18;
const WORD_POS_UNDEFINED_8 = 19;
const WORD_POS_NAN_1 = 20;
const WORD_POS_NAN_2 = 21;
const WORD_POS_INFINITY_1 = 22;
const WORD_POS_INFINITY_2 = 23;
const WORD_POS_INFINITY_3 = 24;
const WORD_POS_INFINITY_4 = 25;
const WORD_POS_INFINITY_5 = 26;
const WORD_POS_INFINITY_6 = 27;
const WORD_POS_INFINITY_7 = 28;
const WORD_POS_FIELD = 29;
const WORD_POS_AFTER_FIELD = 30;
const WORD_POS_END = 31;
const CONTEXT_UNKNOWN = 0;
const CONTEXT_IN_ARRAY = 1; // const CONTEXT_IN_OBJECT = 2
const CONTEXT_OBJECT_FIELD = 3;
const CONTEXT_OBJECT_FIELD_VALUE = 4;
const contexts = [];
function getContext() {
return contexts.pop() || {
context: CONTEXT_UNKNOWN,
elements: null,
element_array: null
};
}
function dropContext(ctx) {
contexts.push(ctx);
}
const buffers = [];
function getBuffer() {
let buf = buffers.pop();
if (!buf) buf = {
buf: null,
n: 0
};else buf.n = 0;
return buf;
}
function dropBuffer(buf) {
buffers.push(buf);
}
const JSON6 = exports // istanbul ignore next
;
/*
let _DEBUG_LL = true;
let _DEBUG_PARSING = true;
let _DEBUG_PARSING_STACK = true;
const log = function(type) {
if (type === '_DEBUG_PARSING' && !_DEBUG_PARSING) {
return;
}
if (type === '_DEBUG_PARSING_STACK' && !_DEBUG_PARSING_STACK) {
return;
}
if (type === '_DEBUG_LL' && !_DEBUG_LL) {
return;
}
console.log.apply(console, [].slice.call(arguments, 1));
};
*/
JSON6.escape = function (string) {
let output = '';
if (!string) return string;
for (let n = 0; n < string.length; n++) {
const ch = string[n];
if (ch == '"' || ch == '\\' || ch == '`' || ch == '\'') {
output += '\\';
}
output += ch;
}
return output;
};
JSON6.begin = function (cb, reviver) {
const val = {
name: null,
// name of this value (if it's contained in an object)
value_type: VALUE_UNSET,
// value from above indiciating the type of this value
string: '',
// the string value of this value (strings and number types only)
contains: null
};
const pos = {
line: 1,
col: 1
};
let n = 0;
let word = WORD_POS_RESET,
status = true,
negative = false,
result = null,
elements = undefined,
element_array = [],
parse_context = CONTEXT_UNKNOWN,
comment = 0,
fromHex = false,
decimal = false,
exponent = false,
exponent_sign = false,
exponent_digit = false,
gatheringStringFirstChar = null,
gatheringString = false,
gatheringNumber = false,
stringEscape = false,
cr_escaped = false,
unicodeWide = false,
stringUnicode = false,
stringHex = false,
hex_char = 0,
hex_char_len = 0,
completed = false;
const context_stack = {
first: null,
last: null,
saved: null,
push(node) {
let recover = this.saved;
if (recover) {
this.saved = recover.next;
recover.node = node;
recover.next = null;
recover.prior = this.last;
} else {
recover = {
node: node,
next: null,
prior: this.last
};
}
if (!this.last) this.first = recover;
this.last = recover;
},
pop() {
const result = this.last;
if (!(this.last = result.prior)) this.first = null;
result.next = this.saved;
this.saved = result;
return result.node;
}
};
const inQueue = {
first: null,
last: null,
saved: null,
push(node) {
let recover = this.saved;
if (recover) {
this.saved = recover.next;
recover.node = node;
recover.next = null;
recover.prior = this.last;
} else {
recover = {
node: node,
next: null,
prior: this.last
};
}
if (!this.last) this.first = recover;else this.last.next = recover;
this.last = recover;
},
shift() {
const result = this.first;
if (!result) return null;
this.first = result.next;
if (!this.first) this.last = null;
result.next = this.saved;
this.saved = result; // node is in saved...
return result.node;
},
unshift(node) {
// usage in this module, recover will ALWAYS have a saved to use.
const recover = this.saved; //if( recover ) {
this.saved = recover.next;
recover.node = node;
recover.next = this.first;
recover.prior = null; //} else { recover = { node : node, next : this.first, prior : null }; }
if (!this.first) this.last = recover;
this.first = recover;
}
};
function throwEndError(leader
/* , c */
) {
throw new Error(`${leader} at ${n} [${pos.line}:${pos.col}]`);
}
return {
finalError() {
if (comment !== 0) {
// most of the time everything's good.
switch (comment) {
case 1:
return throwEndError("Comment began at end of document");
case 2:
console.log("Warning: '//' comment without end of line ended document");
break;
case 3:
return throwEndError("Open comment '/*' is missing close at end of document");
case 4:
return throwEndError("Incomplete '/* *' close at end of document");
}
}
if (gatheringString) throwEndError("Incomplete string");
},
value() {
this.finalError();
const r = result;
result = undefined;
return r;
},
reset() {
word = WORD_POS_RESET;
status = true;
if (inQueue.last) inQueue.last.next = inQueue.save;
inQueue.save = inQueue.first;
inQueue.first = inQueue.last = null;
if (context_stack.last) context_stack.last.next = context_stack.save;
context_stack.save = inQueue.first;
context_stack.first = context_stack.last = null; //= [];
element_array = null;
elements = undefined;
parse_context = CONTEXT_UNKNOWN;
val.value_type = VALUE_UNSET;
val.name = null;
val.string = '';
pos.line = 1;
pos.col = 1;
negative = false;
comment = 0;
completed = false;
gatheringString = false;
stringEscape = false; // string stringEscape intro
cr_escaped = false; // carraige return escaped
//stringUnicode = false; // reading \u
//unicodeWide = false; // reading \u{} in string
//stringHex = false; // reading \x in string
},
write(msg) {
let retcode;
if (msg !== undefined && typeof msg !== "string") msg = String(msg);
if (!status) throw new Error("Parser is in an error state, please reset.");
for (retcode = this._write(msg, false); retcode > 0; retcode = this._write()) {
this.finalError();
if (typeof reviver === 'function') (function walk(holder, key) {
const value = holder[key];
if (value && typeof value === 'object') {
for (const k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
const v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
})({
'': result
}, '');
cb(result);
result = undefined;
if (retcode < 2) break;
}
if (retcode) this.finalError();
},
_write(msg, complete_at_end) {
let input;
let buf;
let retval = 0;
function throwError(leader, c) {
throw new Error(`${leader} '${String.fromCodePoint(c)}' unexpected at ${n} (near '${buf.substr(n > 4 ? n - 4 : 0, n > 4 ? 3 : n - 1)}[${String.fromCodePoint(c)}]${buf.substr(n, 10)}') [${pos.line}:${pos.col}]`);
}
function RESET_VAL() {
val.value_type = VALUE_UNSET;
val.string = '';
}
function arrayPush() {
switch (val.value_type) {
case VALUE_NUMBER:
element_array.push((negative ? -1 : 1) * Number(val.string));
break;
case VALUE_STRING:
element_array.push(val.string);
break;
case VALUE_TRUE:
element_array.push(true);
break;
case VALUE_FALSE:
element_array.push(false);
break;
case VALUE_NEG_NAN:
element_array.push(-NaN);
break;
case VALUE_NAN:
element_array.push(NaN);
break;
case VALUE_NEG_INFINITY:
element_array.push(-Infinity);
break;
case VALUE_INFINITY:
element_array.push(Infinity);
break;
case VALUE_NULL:
element_array.push(null);
break;
case VALUE_UNDEFINED:
element_array.push(undefined);
break;
case VALUE_EMPTY:
element_array.push(undefined);
delete element_array[element_array.length - 1];
break;
case VALUE_OBJECT:
element_array.push(val.contains);
break;
case VALUE_ARRAY:
element_array.push(val.contains);
break;
}
}
function objectPush() {
switch (val.value_type) {
case VALUE_NUMBER:
elements[val.name] = (negative ? -1 : 1) * Number(val.string);
break;
case VALUE_STRING:
elements[val.name] = val.string;
break;
case VALUE_TRUE:
elements[val.name] = true;
break;
case VALUE_FALSE:
elements[val.name] = false;
break;
case VALUE_NEG_NAN:
elements[val.name] = -NaN;
break;
case VALUE_NAN:
elements[val.name] = NaN;
break;
case VALUE_NEG_INFINITY:
elements[val.name] = -Infinity;
break;
case VALUE_INFINITY:
elements[val.name] = Infinity;
break;
case VALUE_NULL:
elements[val.name] = null;
break;
case VALUE_UNDEFINED:
elements[val.name] = undefined;
break;
case VALUE_OBJECT:
elements[val.name] = val.contains;
break;
case VALUE_ARRAY:
elements[val.name] = val.contains;
break;
}
}
function gatherString(start_c) {
let retval = 0;
while (retval == 0 && n < buf.length) {
let str = buf.charAt(n);
const cInt = buf.codePointAt(n++);
if (cInt >= 0x10000) {
str += buf.charAt(n);
n++;
} //console.log( "gathering....", stringEscape, str, cInt, unicodeWide, stringHex, stringUnicode, hex_char_len );
pos.col++;
if (cInt == start_c) {
//( cInt == 34/*'"'*/ ) || ( cInt == 39/*'\''*/ ) || ( cInt == 96/*'`'*/ ) )
if (stringEscape) {
if (stringHex) throwError("Incomplete hexidecimal sequence", cInt);else if (unicodeWide) throwError("Incomplete long unicode sequence", cInt);else if (stringUnicode) throwError("Incomplete unicode sequence", cInt);
if (cr_escaped) {
cr_escaped = false; // \\ \r ' :end string, the backslash was used for \r
retval = 1; // complete string.
} else val.string += str; // escaped start quote
stringEscape = false;
} else {
// quote matches, not escaped, and not processing escape...
retval = 1;
}
} else if (stringEscape) {
if (unicodeWide) {
if (cInt == 125
/*'}'*/
) {
val.string += String.fromCodePoint(hex_char);
unicodeWide = false;
stringUnicode = false;
stringEscape = false;
continue;
}
hex_char *= 16;
if (cInt >= 48
/*'0'*/
&& cInt <= 57
/*'9'*/
) hex_char += cInt - 0x30;else if (cInt >= 65
/*'A'*/
&& cInt <= 70
/*'F'*/
) hex_char += cInt - 65 + 10;else if (cInt >= 97
/*'a'*/
&& cInt <= 102
/*'f'*/
) hex_char += cInt - 97 + 10;else {
throwError("(escaped character, parsing hex of \\u)", cInt);
}
continue;
} else if (stringHex || stringUnicode) {
if (hex_char_len === 0 && cInt === 123
/*'{'*/
) {
unicodeWide = true;
continue;
}
hex_char *= 16;
if (cInt >= 48
/*'0'*/
&& cInt <= 57
/*'9'*/
) hex_char += cInt - 0x30;else if (cInt >= 65
/*'A'*/
&& cInt <= 70
/*'F'*/
) hex_char += cInt - 65 + 10;else if (cInt >= 97
/*'a'*/
&& cInt <= 102
/*'f'*/
) hex_char += cInt - 97 + 10;else {
throwError(stringUnicode ? "(escaped character, parsing hex of \\u)" : "(escaped character, parsing hex of \\x)", cInt);
}
hex_char_len++;
if (stringUnicode) {
if (hex_char_len == 4) {
val.string += String.fromCodePoint(hex_char);
stringUnicode = false;
stringEscape = false;
}
} else if (hex_char_len == 2) {
val.string += String.fromCodePoint(hex_char);
stringHex = false;
stringEscape = false;
}
continue;
}
switch (cInt) {
case 13
/*'\r'*/
:
cr_escaped = true;
pos.col = 1;
continue;
case 0x2028: // LS (Line separator)
case 0x2029:
// PS (paragraph separator)
pos.col = 1;
// no return to get newline reset, so reset line pos.
// Fallthrough
case 10
/*'\n'*/
:
if (cr_escaped) {
// \\ \r \n
cr_escaped = false;
} else {
// \\ \n
pos.col = 1;
}
pos.line++;
break;
case 116
/*'t'*/
:
val.string += '\t';
break;
case 98
/*'b'*/
:
val.string += '\b';
break;
case 48
/*'0'*/
:
val.string += '\0';
break;
case 110
/*'n'*/
:
val.string += '\n';
break;
case 114
/*'r'*/
:
val.string += '\r';
break;
case 102
/*'f'*/
:
val.string += '\f';
break;
case 118
/*'v'*/
:
val.string += '\v';
break;
case 120
/*'x'*/
:
stringHex = true;
hex_char_len = 0;
hex_char = 0;
continue;
case 117
/*'u'*/
:
stringUnicode = true;
hex_char_len = 0;
hex_char = 0;
continue;
default:
val.string += str;
break;
} //console.log( "other..." );
stringEscape = false;
} else if (cInt === 92
/*'\\'*/
) {
stringEscape = true;
} else {
if (cr_escaped) {
cr_escaped = false; // \\ \r <any other character>
pos.line++;
pos.col = 2; // newline, plus one character.
}
val.string += str;
}
}
return retval;
}
function collectNumber() {
let _n;
while ((_n = n) < buf.length) {
const str = buf.charAt(_n);
const cInt = buf.codePointAt(n++);
if (cInt >= 0x10000) {
throwError("fault while parsing number;", cInt);
} //log('_DEBUG_PARSING', "in getting number:", n, cInt, String.fromCodePoint(cInt) );
if (cInt == 95
/*_*/
) continue;
pos.col++; // leading zeros should be forbidden.
if (cInt >= 48
/*'0'*/
&& cInt <= 57
/*'9'*/
) {
if (exponent) {
exponent_digit = true;
}
val.string += str;
} else if (cInt == 45
/*'-'*/
|| cInt == 43
/*'+'*/
) {
if (val.string.length == 0 || exponent && !exponent_sign && !exponent_digit) {
val.string += str;
exponent_sign = true;
} else {
status = false;
throwError("fault while parsing number;", cInt); // break;
}
} else if (cInt == 46
/*'.'*/
) {
if (!decimal && !fromHex && !exponent) {
val.string += str;
decimal = true;
} else {
status = false;
throwError("fault while parsing number;", cInt); // break;
}
} else if (fromHex && (cInt >= 95
/*'a'*/
&& cInt <= 102
/*'f'*/
|| cInt >= 65
/*'A'*/
&& cInt <= 70
/*'F'*/
)) {
val.string += str;
} else if (cInt == 120
/*'x'*/
|| cInt == 98
/*'b'*/
|| cInt == 111
/*'o'*/
|| cInt == 88
/*'X'*/
|| cInt == 66
/*'B'*/
|| cInt == 79
/*'O'*/
) {
// hex conversion.
if (!fromHex && val.string == '0') {
fromHex = true;
val.string += str;
} else {
status = false;
throwError("fault while parsing number;", cInt); // break;
}
} else if (cInt == 101
/*'e'*/
|| cInt == 69
/*'E'*/
) {
if (!exponent) {
val.string += str;
exponent = true;
} else {
status = false;
throwError("fault while parsing number;", cInt); // break;
}
} else {
if (cInt == 32
/*' '*/
|| cInt == 160
/*   */
|| cInt == 13 || cInt == 10 || cInt == 9 || cInt == 0xFEFF || cInt == 44
/*','*/
|| cInt == 125
/*'}'*/
|| cInt == 93
/*']'*/
|| cInt == 58
/*':'*/
) {
break;
} else {
if (complete_at_end) {
status = false;
throwError("fault while parsing number;", cInt);
}
break;
}
}
}
n = _n;
if (!complete_at_end && n == buf.length) {
gatheringNumber = true;
} else {
gatheringNumber = false;
val.value_type = VALUE_NUMBER;
if (parse_context == CONTEXT_UNKNOWN) {
completed = true;
}
}
}
if (!status) return -1;
if (msg && msg.length) {
input = getBuffer();
input.buf = msg;
inQueue.push(input);
} else {
if (gatheringNumber) {
//console.log( "Force completed.")
gatheringNumber = false;
val.value_type = VALUE_NUMBER;
if (parse_context == CONTEXT_UNKNOWN) {
completed = true;
} else {
throw new Error("context stack is not empty at flush");
}
retval = 1; // if returning buffers, then obviously there's more in this one.
}
}
while (status && (input = inQueue.shift())) {
n = input.n;
buf = input.buf;
if (gatheringString) {
const string_status = gatherString(gatheringStringFirstChar);
if (string_status > 0) {
gatheringString = false;
val.value_type = VALUE_STRING;
}
}
if (gatheringNumber) {
collectNumber();
}
while (!completed && status && n < buf.length) {
let str = buf.charAt(n);
const cInt = buf.codePointAt(n++);
if (cInt >= 0x10000) {
str += buf.charAt(n);
n++;
} //// log('_DEBUG_PARSING', "parsing at ", cInt, str );
//log('_DEBUG_LL', "processing: ", cInt, str, pos, comment, parse_context, word, val );
pos.col++;
if (comment) {
// '/'
if (comment == 1) {
// '/'
if (cInt == 42
/*'*'*/
) {
comment = 3;
} // '/*'
else if (cInt != 47
/*'/'*/
) {
// '//'(NOT)
throwError("fault while parsing;", cInt);
} else comment = 2; // '//' (valid)
} else if (comment == 2) {
// '// ...'
if (cInt == 10
/*'\n'*/
|| cInt == 13
/*'\r'*/
) comment = 0;
} else if (comment == 3) {
// '/*... '
if (cInt == 42
/*'*'*/
) comment = 4;
} else {
// if( comment == 4 ) { // '/* ... *'
if (cInt == 47
/*'/'*/
) comment = 0;else comment = 3; // any other char, goto expect * to close */
}
continue;
}
switch (cInt) {
case 47
/*'/'*/
:
comment = 1;
break;
case 123
/*'{'*/
:
if (word == WORD_POS_FIELD || word == WORD_POS_AFTER_FIELD || parse_context == CONTEXT_OBJECT_FIELD && word == WORD_POS_RESET) {
throwError("fault while parsing; getting field name unexpected ", cInt); // break;
}
{
const old_context = getContext(); //log('_DEBUG_PARSING', "Begin a new object; previously pushed into elements; but wait until trailing comma or close previously:%d", val.value_type );
val.value_type = VALUE_OBJECT;
const tmpobj = {};
if (parse_context == CONTEXT_UNKNOWN) result = elements = tmpobj;
old_context.context = parse_context;
old_context.elements = elements;
old_context.element_array = element_array;
old_context.name = val.name;
elements = tmpobj; //log('_DEBUG_PARSING_STACK',"push context (open object): ", context_stack.length );
context_stack.push(old_context);
RESET_VAL();
parse_context = CONTEXT_OBJECT_FIELD;
}
break;
case 91
/*'['*/
:
if (parse_context == CONTEXT_OBJECT_FIELD || word == WORD_POS_FIELD || word == WORD_POS_AFTER_FIELD) {
throwError("Fault while parsing; while getting field name unexpected", cInt); // break;
}
if (val.value_type == VALUE_UNSET || val.value_type == VALUE_UNDEFINED) {
const old_context = getContext(); //log('_DEBUG_PARSING', "Begin a new array; previously pushed into elements; but wait until trailing comma or close previously:%d", val.value_type );
val.value_type = VALUE_ARRAY;
const tmparr = [];
if (parse_context == CONTEXT_UNKNOWN) result = element_array = tmparr; //else if( parse_context == CONTEXT_IN_ARRAY )
// element_array.push( tmparr );
else if (parse_context == CONTEXT_OBJECT_FIELD_VALUE) elements[val.name] = tmparr;
old_context.context = parse_context;
old_context.elements = elements;
old_context.element_array = element_array;
old_context.name = val.name;
element_array = tmparr; //log('_DEBUG_PARSING_STACK', "push context (open array): ", context_stack.length );
context_stack.push(old_context);
RESET_VAL();
parse_context = CONTEXT_IN_ARRAY;
} else {
throwError("Unexpected array open after previous value", cInt);
}
break;
case 58
/*':'*/
:
////log('_DEBUG_PARSING', "colon context:", parse_context );
if (parse_context == CONTEXT_OBJECT_FIELD) {
word = WORD_POS_RESET;
val.name = val.string;
val.string = '';
parse_context = CONTEXT_OBJECT_FIELD_VALUE;
val.value_type = VALUE_UNSET;
} else {
if (parse_context == CONTEXT_IN_ARRAY) throwError("(in array, got colon out of string):parsing fault;", cInt);else throwError("(outside any object, got colon out of string):parsing fault;", cInt);
}
break;
case 125
/*'}'*/
:
////log('_DEBUG_PARSING', "close bracket context:", word, parse_context );
if (word == WORD_POS_END) {
// allow starting a new word
word = WORD_POS_RESET;
} // coming back after pushing an array or sub-object will reset the context to FIELD, so