UNPKG

json-6

Version:
1,619 lines (1,344 loc) 77.7 kB
(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 /* &nbsp */ || 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