@aidenlx/jsonurl
Version:
JSON->URL defines a text format for the JSON data model suitable for use within a URL/URI (as described by RFC3986).
1,765 lines (1,478 loc) • 75.2 kB
JavaScript
'use strict';
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf(subClass, superClass);
}
function _getPrototypeOf(o) {
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf(o);
}
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
function _isNativeReflectConstruct() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _construct(Parent, args, Class) {
if (_isNativeReflectConstruct()) {
_construct = Reflect.construct;
} else {
_construct = function _construct(Parent, args, Class) {
var a = [null];
a.push.apply(a, args);
var Constructor = Function.bind.apply(Parent, a);
var instance = new Constructor();
if (Class) _setPrototypeOf(instance, Class.prototype);
return instance;
};
}
return _construct.apply(null, arguments);
}
function _isNativeFunction(fn) {
return Function.toString.call(fn).indexOf("[native code]") !== -1;
}
function _wrapNativeSuper(Class) {
var _cache = typeof Map === "function" ? new Map() : undefined;
_wrapNativeSuper = function _wrapNativeSuper(Class) {
if (Class === null || !_isNativeFunction(Class)) return Class;
if (typeof Class !== "function") {
throw new TypeError("Super expression must either be null or a function");
}
if (typeof _cache !== "undefined") {
if (_cache.has(Class)) return _cache.get(Class);
_cache.set(Class, Wrapper);
}
function Wrapper() {
return _construct(Class, arguments, _getPrototypeOf(this).constructor);
}
Wrapper.prototype = Object.create(Class.prototype, {
constructor: {
value: Wrapper,
enumerable: false,
writable: true,
configurable: true
}
});
return _setPrototypeOf(Wrapper, Class);
};
return _wrapNativeSuper(Class);
}
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _possibleConstructorReturn(self, call) {
if (call && (typeof call === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized(self);
}
function _createSuper(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct();
return function _createSuperInternal() {
var Super = _getPrototypeOf(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn(this, result);
};
}
/*
MIT License
Copyright (c) 2020 David MacCormack
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
var MSG_EXPECT_STRUCTCHAR = "JSON->URL: expected comma, open paren, or close paren";
var MSG_EXPECT_MOREARRAY = "JSON->URL: expected comma or close paren";
var MSG_EXPECT_VALUE = "JSON->URL: expected value";
var MSG_EXPECT_LITERAL = "JSON->URL: expected literal value";
var MSG_BADCHAR = "JSON->URL: unexpected character";
var MSG_INTERNAL = "JSON->URL: internal error";
var MSG_STILLOPEN = "JSON->URL: unexpected end of text inside composite";
var MSG_EXTRACHARS = "JSON->URL: unexpected text after composite";
var MSG_LIMIT_MAXCHARS = "JSON->URL: MaxParseChars exceeded";
var MSG_LIMIT_MAXDEPTH = "JSON->URL: MaxParseDepth exceeded";
var MSG_LIMIT_MAXVALUES = "JSON->URL: MaxParseValues exceeded";
var MSG_EXPECT_QUOTE = "JSON->URL: quoted string still open";
var MSG_IMPLIED_STRING_NULL = "JSON->URL: can not represent null with implied strings";
var MSG_IMPLIED_STRING_EMPTY = "JSON->URL: the empty string is not allowed";
var MSG_BAD_ESCAPE = "JSON->URL: invalid escape sequence";
var MSG_BAD_PCTENC = "JSON->URL: invalid percent-encoded sequence";
var MSG_EXPECT_OBJVALUE = "JSON->URL: expected object value";
function fmt(msg, pos) {
return pos === undefined ? msg : msg + " at position " + pos;
}
/*
MIT License
Copyright (c) 2020 David MacCormack
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/**
* Bit for characters that are safe inside a non-quoted string as-is.
*/
var IS_NSTRSAFE = 1 << 1;
/**
* Bit for characters that are safe inside a quoted string as-is.
*/
var IS_QSTRSAFE = 1 << 2;
/**
* Bit for quote character
*/
var IS_QUOTE = 1 << 3;
/**
* Bit for structural characters
*/
var IS_STRUCT = 1 << 4;
/**
* Bit for structural characters
*/
var IS_WFU = 1 << 5;
/**
* IS_QSTRSAFE | IS_NSTRSAFE
*/
var IS_ANY_STRSAFE = IS_QSTRSAFE | IS_NSTRSAFE;
/**
* bits for US-ASCII characters.
*/
var CHARBITS_BASE = [// ASCII 0 - 15
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ASCII 16 - 31
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
// ASCII 32 (space)
//
0, // ASCII 33 (!)
IS_ANY_STRSAFE, // ASCII 34 (")
0, // ASCII 35 (#)
0, // ASCII 36 ($)
IS_ANY_STRSAFE, // ASCII 37 (%)
IS_ANY_STRSAFE, // ASCII 38 (&)
IS_STRUCT | IS_WFU, // ASCII 39 (')
IS_NSTRSAFE | IS_QUOTE, // ASCII 40 (lparen)
IS_QSTRSAFE | IS_STRUCT, // ASCII 41 (rparen)
IS_QSTRSAFE | IS_STRUCT, // ASCII 42 (*)
IS_ANY_STRSAFE, // ASCII 43 (+)
IS_ANY_STRSAFE, // ASCII 44 (,)
IS_QSTRSAFE | IS_STRUCT, // ASCII 45 (-)
IS_ANY_STRSAFE, // ASCII 46 (.)
IS_ANY_STRSAFE, // ASCII 47 (/)
IS_ANY_STRSAFE, // ASCII 48 (0)
IS_ANY_STRSAFE, // ASCII 49 (1)
IS_ANY_STRSAFE, // ASCII 50 (2)
IS_ANY_STRSAFE, // ASCII 51 (3)
IS_ANY_STRSAFE, // ASCII 52 (4)
IS_ANY_STRSAFE, // ASCII 53 (5)
IS_ANY_STRSAFE, // ASCII 54 (6)
IS_ANY_STRSAFE, // ASCII 55 (7)
IS_ANY_STRSAFE, // ASCII 56 (8)
IS_ANY_STRSAFE, // ASCII 57 (9)
IS_ANY_STRSAFE, // ASCII 58 (:)
IS_QSTRSAFE | IS_STRUCT, // ASCII 59 (;)
IS_ANY_STRSAFE, // ASCII 60 (<)
0, // ASCII 61 (=)
IS_STRUCT | IS_WFU, // ASCII 62 (>)
0, // ASCII 63 (?)
IS_ANY_STRSAFE, // ASCII 64 (@)
IS_ANY_STRSAFE, // ASCII 65 (A)
IS_ANY_STRSAFE, // ASCII 66 (B)
IS_ANY_STRSAFE, // ASCII 67 (C)
IS_ANY_STRSAFE, // ASCII 68 (D)
IS_ANY_STRSAFE, // ASCII 69 (E)
IS_ANY_STRSAFE, // ASCII 70 (F)
IS_ANY_STRSAFE, // ASCII 71 (G)
IS_ANY_STRSAFE, // ASCII 72 (H)
IS_ANY_STRSAFE, // ASCII 73 (I)
IS_ANY_STRSAFE, // ASCII 74 (J)
IS_ANY_STRSAFE, // ASCII 75 (K)
IS_ANY_STRSAFE, // ASCII 76 (L)
IS_ANY_STRSAFE, // ASCII 77 (M)
IS_ANY_STRSAFE, // ASCII 78 (N)
IS_ANY_STRSAFE, // ASCII 79 (O)
IS_ANY_STRSAFE, // ASCII 80 (P)
IS_ANY_STRSAFE, // ASCII 81 (Q)
IS_ANY_STRSAFE, // ASCII 82 (R)
IS_ANY_STRSAFE, // ASCII 83 (S)
IS_ANY_STRSAFE, // ASCII 84 (T)
IS_ANY_STRSAFE, // ASCII 85 (U)
IS_ANY_STRSAFE, // ASCII 86 (V)
IS_ANY_STRSAFE, // ASCII 87 (W)
IS_ANY_STRSAFE, // ASCII 88 (X)
IS_ANY_STRSAFE, // ASCII 89 (Y)
IS_ANY_STRSAFE, // ASCII 90 (Z)
IS_ANY_STRSAFE, // ASCII 91 ([)
0, // ASCII 92 (backslash)
0, // ASCII 93 (])
0, // ASCII 94 (^)
0, // ASCII 95 (_)
IS_ANY_STRSAFE, // ASCII 96 (`)
0, // ASCII 97 (a)
IS_ANY_STRSAFE, // ASCII 98 (b)
IS_ANY_STRSAFE, // ASCII 99 (c)
IS_ANY_STRSAFE, // ASCII 100 (d)
IS_ANY_STRSAFE, // ASCII 101 (e)
IS_ANY_STRSAFE, // ASCII 102 (f)
IS_ANY_STRSAFE, // ASCII 103 (g)
IS_ANY_STRSAFE, // ASCII 104 (h)
IS_ANY_STRSAFE, // ASCII 105 (i)
IS_ANY_STRSAFE, // ASCII 106 (j)
IS_ANY_STRSAFE, // ASCII 107 (k)
IS_ANY_STRSAFE, // ASCII 108 (l)
IS_ANY_STRSAFE, // ASCII 109 (m)
IS_ANY_STRSAFE, // ASCII 110 (n)
IS_ANY_STRSAFE, // ASCII 111 (o)
IS_ANY_STRSAFE, // ASCII 112 (p)
IS_ANY_STRSAFE, // ASCII 113 (q)
IS_ANY_STRSAFE, // ASCII 114 (r)
IS_ANY_STRSAFE, // ASCII 115 (s)
IS_ANY_STRSAFE, // ASCII 116 (t)
IS_ANY_STRSAFE, // ASCII 117 (u)
IS_ANY_STRSAFE, // ASCII 118 (v)
IS_ANY_STRSAFE, // ASCII 119 (w)
IS_ANY_STRSAFE, // ASCII 120 (x)
IS_ANY_STRSAFE, // ASCII 121 (y)
IS_ANY_STRSAFE, // ASCII 122 (z)
IS_ANY_STRSAFE, // ASCII 123 ({)
0, // ASCII 124 (|)
0, // ASCII 125 (})
0, // ASCII 126 (~)
IS_ANY_STRSAFE, // ASCII 127
0];
function lookup(c) {
return c > 127 ? 0 : CHARBITS_BASE[c];
}
/*
MIT License
Copyright (c) 2020 David MacCormack
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
var JsonURLOptions = /*#__PURE__*/function () {
/**
* Construct a new instance. Make a copy of the given source options
* and apply defaults.
* @param {?Object} src initial set of options
*/
function JsonURLOptions(src) {
_classCallCheck(this, JsonURLOptions);
this.setOrDefault(src, "allowEmptyUnquotedValues");
this.setOrDefault(src, "allowEmptyUnquotedKeys");
this.setOrDefault(src, "AQF");
this.setOrDefault(src, "coerceNullToEmptyString");
this.setOrDefault(src, "ignoreNullArrayMembers");
this.setOrDefault(src, "ignoreNullObjectMembers");
this.setOrDefault(src, "impliedArray");
this.setOrDefault(src, "impliedObject");
this.setOrDefault(src, "impliedStringLiterals");
this.setOrDefault(src, "noEmptyComposite");
this.setOrDefault(src, "wwwFormUrlEncoded");
}
/**
* Set a named value from a source object or set its default (if given).
* @protected
*/
_createClass(JsonURLOptions, [{
key: "setOrDefault",
value: function setOrDefault(src, key, defValue) {
if (src === undefined || !(key in src)) {
if (defValue !== undefined && !(key in this)) {
this[key] = defValue;
}
} else if (!(key in this)) {
this[key] = src[key];
}
}
/**
* Override the given function.
* @protected
*/
}, {
key: "setOverride",
value: function setOverride(src, key) {
if (src !== undefined && key in src) {
this[key] = src[key];
}
}
/**
* Set a named value from a source object or set its default (if given).
* @protected
*/
}, {
key: "setOrDefaultInt",
value: function setOrDefaultInt(src, key, defValue) {
this.setOrDefault(src, key, defValue === undefined ? defValue : parseInt(defValue));
}
/**
* Evaluates to true if the given `ignore` option is present and truthy.
*/
}, {
key: "isPresentAndTrue",
value: function isPresentAndTrue(key) {
return key in this && this[key];
}
}]);
return JsonURLOptions;
}();
/*
MIT License
Copyright (c) 2020 David MacCormack
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/**
* JsonURL.parse() options.
* @public
* @property {Array} impliedArray An implied array.
* The parse() method implements a parser for the grammar oulined in
* section 2.7 of the JSON->URL specification. The given parse text
* is assumed to be an array, and the leading and trailing parens must
* not be present. The given prop.impliedArray value will be populated
* and returned.
* @property {Object} impliedObject An implied object.
* The parse() method implements a parser for the grammar oulined in
* section 2.8 of the JSON->URL specification. The given parse text
* is assumed to be an object, and the leading and trailing parens must
* not be present. The given prop.impliedObject value will be populated
* and returned.
* @property {boolean} wwwFormUrlEncoded Enable support for
* x-www-form-urlencoded content.
* The parse() method implements a parser for the grammar oulined in
* section 2.9 of the JSON->URL specification. The given parse text
* is may use ampersand and equal characters as the value and member
* separator characters, respetively, at the top-level. This may be
* combined with prop.impliedArray or prop.impliedObject.
* @property {boolean} impliedStringLiterals Assume all
* literals are strings.
* @property {boolean} allowEmptyUnquotedValues Allow the
* empty string as a value to be represented as a zero legnth string rather
* than back-to-back single quotes.
* @property {boolean} allowEmptyUnquotedKeys Allow the
* empty string as a key to be represented as a zero legnth string rather
* than back-to-back single quotes.
* @property {boolean} coerceNullToEmptyString Replace
* instances of the null value with an empty string.
* @property {boolean} noEmptyComposite Distinguish
* between empty array and empty object. Empty array is back-to-back parens,
* e.g. (). Empty object is two parens with a single colon inside, e.g. (:).
* Note that this prevents the parser from recognizing (:) as an object
* with a single member whose key and value is the unquoted empty string.
* @property {boolean} AQF Enable the Address Bar Query String Friendly
* syntax.
* @property {function} getMissingValue Provides a value for a
* missing, top-level value.
* @property {number} maxParseDepth Maximum parse depth.
* The parse() method will throw an Error if the depth
* of the input exceeds this value. The default is 32.
* @property {number} maxParseValues Maximum number of values to parse.
* The parse() method will throw an Error if it parses more than this
* number of values. The default is 4096.
* @property {number} maxParseChars Maximum number of characters to parse.
* The parse() method will throw an Error if it parses more than this
* number of characters. The default is 32K.
* @property {*} emptyValue The value which represents the empty composite.
* This may be any type. If it is a function then it will be called
* until it resolves to something that is not a function. The default
* is an empty Object.
* @property {*} nullValue The value which represents the null value.
* This may be any type. If it is a function then it will be called
* until it resolves to something that is not a function. The default
* is null.
*/
var JsonURLParseOptions = /*#__PURE__*/function (_JsonURLOptions) {
_inherits(JsonURLParseOptions, _JsonURLOptions);
var _super = _createSuper(JsonURLParseOptions);
/**
* Construct a new instance.
* @param {?Object} src initial set of options
* @param {?Object} limits this parameter is deprecated but included for
* compatibility. `maxParseChars`, `maxParseDepth`, and/or
* `maxParseValues` may be included here rather than `src`.
*/
function JsonURLParseOptions(src, limits) {
var _this;
_classCallCheck(this, JsonURLParseOptions);
_this = _super.call(this, src);
_this.setOrDefault(src, "emptyValue");
_this.setOrDefault(limits, "emptyValue", {});
_this.setOverride(src, "getMissingValue");
_this.setOrDefaultInt(src, "maxParseChars");
_this.setOrDefaultInt(limits, "maxParseChars", 1 << 15);
_this.setOrDefaultInt(src, "maxParseDepth");
_this.setOrDefaultInt(limits, "maxParseDepth", 1 << 5);
_this.setOrDefaultInt(src, "maxParseValues");
_this.setOrDefaultInt(limits, "maxParseValues", 1 << 12);
_this.setOrDefault(src, "nullValue");
_this.setOrDefault(limits, "nullValue", null);
return _this;
}
/**
* Get the value for the given key/name.
* @param {string} key property key/name
* @param {number} pos position in the JSON->URL text. This is helpful
* if you want to throw a SyntaxError.
*/
_createClass(JsonURLParseOptions, [{
key: "getMissingValue",
value: function getMissingValue(key, pos) {
throw new SyntaxError(fmt(MSG_EXPECT_OBJVALUE, pos));
}
}]);
return JsonURLParseOptions;
}(JsonURLOptions);
/*
MIT License
Copyright (c) 2020 David MacCormack
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/**
* JsonURL.stringify() options.
* @public
* @property {boolean} ignoreNullArrayMembers Ignore null array members.
* This is false by default.
* @property {boolean} ignoreNullObjectMembers Ignore null object members.
* This is false by default.
* @property {boolean} ignoreUndefinedArrayMembers Ignore undefined array members.
* This is false by default. They will be stringified as null because
* undefined is not a valid JSON value.
* @property {boolean} ignoreUndefinedObjectMembers Ignore undefined object members.
* This is true by default. They will be omitted from the stringified
* output. This mimics the behavior JSON.stringify().
* @property {boolean} wwwFormUrlEncoded Enable x-www-form-urlencoded
* structural characters.
* @property {boolean} isImplied Create JSON->URL text for an implied
* array or object.
* @property {boolean} impliedStringLiterals Assume all literals
* are strings.
* @property {boolean} allowEmptyUnquotedValues Allow the empty string
* as a value to be represented as a zero legnth string rather than
* bac-to-back single quotes.
* @property {boolean} allowEmptyUnquotedKeys Allow the empty string
* as a key to be represented as a zero legnth string rather than
* bac-to-back single quotes.
* @property {boolean} coerceNullToEmptyString Replace instances
* of the null value with an empty string.
* @property {boolean} noEmptyComposite Distinguish
* between empty array and empty object. Empty array is back-to-back parens,
* e.g. (). Empty object is two parens with a single colon inside, e.g. (:).
* @property {boolean} callFunctions If object values are functions
* then call them.
*/
var JsonURLStringifyOptions = /*#__PURE__*/function (_JsonURLOptions) {
_inherits(JsonURLStringifyOptions, _JsonURLOptions);
var _super = _createSuper(JsonURLStringifyOptions);
/**
* Construct a new instance.
* @param {?Object} src initial set of options
*/
function JsonURLStringifyOptions(src) {
var _this;
_classCallCheck(this, JsonURLStringifyOptions);
_this = _super.call(this, src);
var def = src !== undefined && "impliedStringLiterals" in src && src.impliedStringLiterals ? true : undefined;
_this.setOrDefault(src, "allowEmptyUnquotedValues", def);
_this.setOrDefault(src, "allowEmptyUnquotedKeys", def);
_this.setOrDefault(src, "callFunctions");
_this.setOrDefault(src, "isImplied");
_this.setOrDefault(src, "ignoreNullArrayMembers", def);
_this.setOrDefault(src, "ignoreNullObjectMembers", def);
_this.setOrDefault(src, "ignoreUndefinedArrayMembers", def);
_this.setOrDefault(src, "ignoreUndefinedObjectMembers", def); //
// provide consistency with JsonURL.parse() option names even though
// stringify doesn't care whether it's an object or array.
//
_this.isImplied = _this.isImplied || _this.impliedArray || _this.impliedObject;
return _this;
}
return JsonURLStringifyOptions;
}(JsonURLOptions);
/*
MIT License
Copyright (c) 2020 David MacCormack
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
var RX_DECODE_SPACE = /\+/g;
var RX_ENCODE_SPACE = / /g;
var RX_AQF_DECODE = /(![\s\S]?)/g; //
// patterns for use with RegEx.test().
// DO NOT PUT //g ON THESE!!!
//
var RX_ENCODE_STRING_SAFE = /^[-A-Za-z0-9._~!$*;=@?/ ][-A-Za-z0-9._~!$*;=@?/' ]*$/;
var RX_ENCODE_STRING_QSAFE = /^[-A-Za-z0-9._~!$*,;=@?/(),: ]+$/;
var RX_ENCODE_QUOTED_LITERAL = /^(?:true|false|null|(?:[-]?[0-9]+(?:[.][0-9]+)?(?:[eE][-+]?[0-9]+)?))$/;
var RX_ENCODE_BASE = /[(),:]|%2[04]|%3B/gi;
var RX_ENCODE_BASE_MAP = {
"%20": "+",
"%24": "$",
"(": "%28",
")": "%29",
",": "%2C",
":": "%3A",
"%3B": ";"
};
var RX_ENCODE_AQF = /[!(),:]|%2[01489C]|%3[AB]/gi;
var RX_ENCODE_AQF_MAP = {
"%20": "+",
"%21": "!!",
"!": "!!",
"%24": "$",
"%28": "!(",
"(": "!(",
"%29": "!)",
")": "!)",
"+": "!+",
"%2C": "!,",
",": "!,",
"%3A": "!:",
":": "!:",
"%3B": ";"
};
var CHAR_BANG = 0x21;
var CHAR_PERCENT = 0x25;
var CHAR_QUOTE = 0x27;
var CHAR_PAREN_OPEN = 0x28;
var CHAR_PAREN_CLOSE = 0x29;
var CHAR_PLUS = 0x2b;
var CHAR_COMMA = 0x2c;
var CHAR_DASH = 0x2d;
var CHAR_DOT = 0x2e;
var CHAR_COLON = 0x3a;
var CHAR_EQUALS = 0x3d;
var CHAR_AMP = 0x26;
var CHAR_0 = 0x30;
var CHAR_A = 0x41;
var CHAR_E = 0x45;
var CHAR_a = 0x61;
var CHAR_e = 0x65;
var CHAR_f = 0x66;
var CHAR_l = 0x6c;
var CHAR_n = 0x6e;
var CHAR_r = 0x72;
var CHAR_s = 0x73;
var CHAR_t = 0x74;
var CHAR_u = 0x75;
var STATE_PAREN = 1;
var STATE_IN_ARRAY = 2;
var STATE_ARRAY_AFTER_ELEMENT = 3;
var STATE_OBJECT_HAVE_KEY = 4;
var STATE_OBJECT_AFTER_ELEMENT = 5;
var STATE_IN_OBJECT = 6;
var UNESCAPE = new Array(111);
UNESCAPE[CHAR_BANG] = "!";
UNESCAPE[CHAR_PAREN_OPEN] = "(";
UNESCAPE[CHAR_PAREN_CLOSE] = ")";
UNESCAPE[CHAR_PLUS] = "+";
UNESCAPE[CHAR_COMMA] = ",";
UNESCAPE[CHAR_DASH] = ",";
UNESCAPE[CHAR_0] = "0";
UNESCAPE[CHAR_0 + 1] = "1";
UNESCAPE[CHAR_0 + 2] = "2";
UNESCAPE[CHAR_0 + 3] = "3";
UNESCAPE[CHAR_0 + 4] = "4";
UNESCAPE[CHAR_0 + 5] = "5";
UNESCAPE[CHAR_0 + 6] = "6";
UNESCAPE[CHAR_0 + 7] = "7";
UNESCAPE[CHAR_0 + 8] = "8";
UNESCAPE[CHAR_0 + 9] = "9";
UNESCAPE[CHAR_COLON] = ":";
UNESCAPE[CHAR_t] = "t";
UNESCAPE[CHAR_f] = "f";
UNESCAPE[CHAR_n] = "n";
var EMPTY_STRING = "";
var EMPTY_STRING_AQF = "!e";
var SPACE = " ";
function newEmptyString(pos, emptyOK) {
if (emptyOK) {
return EMPTY_STRING;
}
throw new SyntaxError(fmt(MSG_IMPLIED_STRING_EMPTY, pos));
}
function encodeStringLiteral(text, aqf) {
var re = aqf ? RX_ENCODE_AQF : RX_ENCODE_BASE;
var map = aqf ? RX_ENCODE_AQF_MAP : RX_ENCODE_BASE_MAP;
return encodeURIComponent(text).replace(re, function name(match) {
var ret = map[match];
return ret === undefined ? match : ret;
});
}
function hexDecodeOctet(text, pos, end) {
if (end <= pos + 1) {
throw new SyntaxError(fmt(MSG_BAD_PCTENC, pos));
}
var high = hexDecode(pos, text.charCodeAt(pos));
var low = hexDecode(pos, text.charCodeAt(pos + 1));
return high << 4 | low;
}
function hexDecode(pos, c) {
switch (c) {
case CHAR_0:
return 0;
case CHAR_0 + 1:
return 1;
case CHAR_0 + 2:
return 2;
case CHAR_0 + 3:
return 3;
case CHAR_0 + 4:
return 4;
case CHAR_0 + 5:
return 5;
case CHAR_0 + 6:
return 6;
case CHAR_0 + 7:
return 7;
case CHAR_0 + 8:
return 8;
case CHAR_0 + 9:
return 9;
case CHAR_A:
case CHAR_a:
return 10;
case CHAR_A + 1:
case CHAR_a + 1:
return 11;
case CHAR_A + 2:
case CHAR_a + 2:
return 12;
case CHAR_A + 3:
case CHAR_a + 3:
return 13;
case CHAR_A + 4:
case CHAR_a + 4:
return 14;
case CHAR_A + 5:
case CHAR_a + 5:
return 15;
default:
throw new SyntaxError(fmt(MSG_BAD_PCTENC, pos));
}
}
function toJsonURLText(obj) {
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
if (typeof obj === "boolean" || obj instanceof Boolean) return toJsonURLText_Boolean.apply(obj, args);else if (typeof obj === "number" || obj instanceof Number) return toJsonURLText_Number.apply(obj, args);else if (typeof obj === "string" || obj instanceof String) return toJsonURLText_String.apply(obj, args);else if (Array.isArray(obj)) return toJsonURLText_Array.apply(obj, args);else if (obj) return toJsonURLText_Object.apply(obj, args);else return EMPTY_STRING;
}
function toJsonURLText_Null(options) {
if (options.coerceNullToEmptyString) {
return toJsonURLText_EmptyString(options, false);
}
if (options.impliedStringLiterals) {
throw new SyntaxError(MSG_IMPLIED_STRING_NULL);
}
return "null";
}
function toJsonURLText_EmptyString(options, isKey) {
var emptyOK = isKey ? options.allowEmptyUnquotedKeys : options.allowEmptyUnquotedValues;
if (emptyOK) {
return EMPTY_STRING;
}
if (options.AQF) {
return EMPTY_STRING_AQF;
}
if (options.impliedStringLiterals) {
throw new SyntaxError(MSG_IMPLIED_STRING_EMPTY);
}
return "''";
}
function toJsonURLText_Boolean() {
return this === true ? "true" : "false";
}
function toJsonURLText_Number(options) {
var ret = String(this);
if (options.impliedStringLiterals && ret.indexOf("+") !== -1) {
//
// I don't think this will happen, but just in case...
//
return encodeStringLiteral(ret, options);
}
return ret;
}
function toJsonURLText_String(options, depth, isKey) {
if (this.length === 0) {
return toJsonURLText_EmptyString(options, isKey);
}
if (options.impliedStringLiterals) {
return encodeStringLiteral(this, options.AQF);
}
if (RX_ENCODE_QUOTED_LITERAL.test(this)) {
//
// if this string looks like a Boolean, Number, or ``null'' literal
// then it must be quoted
//
if (isKey === true) {
return this;
}
if (options.AQF) {
if (this.indexOf("+") == -1) {
return "!" + this;
}
return this.replace("+", "!+");
}
if (this.indexOf("+") == -1) {
return "'" + this + "'";
} //
// if the string needs to be encoded then it no longer looks like a
// literal and does not needs to be quoted.
//
return encodeURIComponent(this);
}
if (options.AQF) {
return encodeStringLiteral(this, true);
}
if (RX_ENCODE_STRING_SAFE.test(this)) {
//
// safe to use as long as I encode spaces
//
if (this.indexOf(SPACE) == -1) {
return this;
}
return this.replace(RX_ENCODE_SPACE, "+");
}
if (RX_ENCODE_STRING_QSAFE.test(this)) {
//
// safe to use as long as I quote it and encode spaces
//
if (this.indexOf(SPACE) == -1) {
return "'" + this + "'";
}
return "'" + this.replace(RX_ENCODE_SPACE, "+") + "'";
}
var ret = encodeStringLiteral(this);
if (ret.charCodeAt(0) == CHAR_QUOTE) {
//
// I need to encode the leading quote
//
return "%27" + ret.substring(1);
}
return ret;
}
function toJsonURLText_Array() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var ret = undefined;
this.forEach(function (e) {
if (typeof e === "function") {
if (!options.callFunctions) {
return;
}
while (typeof e === "function") {
e = e();
}
}
if (e === undefined) {
if (options.ignoreUndefinedArrayMembers) {
return;
}
e = toJsonURLText_Null(options);
} else if (e === null) {
if (options.ignoreNullArrayMembers) {
return;
}
e = toJsonURLText_Null(options);
} else {
e = toJsonURLText(e, options, depth + 1);
}
if (ret === undefined) {
ret = e;
} else if (!options.wwwFormUrlEncoded || depth > 0) {
ret += "," + e;
} else {
ret += "&" + e;
}
});
if (!options.isImplied || depth > 0) {
return ret === undefined ? "()" : "(" + ret + ")";
}
return ret === undefined ? EMPTY_STRING : ret;
}
function toJsonURLText_Object() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var ret = undefined;
var keys = Object.keys(this);
var obj = this;
keys.forEach(function (k) {
if (k === undefined || k === null) {
//
// I'm not sure this can actually happen. But, handling just in case.
//
return;
}
var v = obj[k];
if (typeof v === "function") {
if (!options.callFunctions) {
return;
}
while (typeof v === "function") {
v = v();
}
}
if (v === undefined) {
if (options.ignoreUndefinedObjectMembers) {
return;
}
v = toJsonURLText_Null(options);
} else if (v === null) {
if (options.ignoreNullObjectMembers) {
return;
}
v = toJsonURLText_Null(options);
} else {
v = toJsonURLText(v, options, depth + 1);
}
var jk = toJsonURLText(k, options, depth, true);
if (ret === undefined) {
if (!options.wwwFormUrlEncoded || depth > 0) {
ret = jk + ":" + v;
} else {
ret = jk + "=" + v;
}
} else {
if (!options.wwwFormUrlEncoded || depth > 0) {
ret += "," + jk + ":" + v;
} else {
ret += "&" + jk + "=" + v;
}
}
});
if (!options.isImplied || depth > 0) {
if (options.noEmptyComposite && ret === undefined) {
ret = ":";
}
return ret === undefined ? "()" : "(" + ret + ")";
}
return ret === undefined ? EMPTY_STRING : ret;
}
/**
* Base syntax parser.
* @private
*/
var Parser = /*#__PURE__*/function () {
/**
* Construct a new instance.
* @param {JsonURLParseOptions} options options provided by the user
*/
function Parser(text, pos, end, options) {
_classCallCheck(this, Parser);
this.text = text;
this.pos = this.markPos = pos;
this.end = end;
this.options = options;
}
/**
* Skip zero or more amperands.
*/
_createClass(Parser, [{
key: "skipAmps",
value: function skipAmps() {
var leading = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var text = this.text;
var end = this.end;
var pos = this.pos;
if (leading) {
//
// skip all leading amps and position `pos` at the first non-amp
// character (or EOF)
//
while (pos < end && text.charCodeAt(pos) === CHAR_AMP) {
pos++;
}
} else if (pos < end && text.charCodeAt(pos) === CHAR_AMP) {
//
// there is at least one amp
//
for (pos++; pos < end && text.charCodeAt(pos) === CHAR_AMP; pos++) {// skip all consecutive amps
}
if (pos !== end) {
// one or more amps followed by additional text; caller
// is looking to consume a value separator so go back one char.
pos--;
}
}
this.pos = pos;
}
/**
* Read the next char code. If it is a structural character then the
* current position will be advanced and the char will be returned.
* Otherwise, the current position will remain unchanged and undefined
* will be returned.
*/
}, {
key: "structChar",
value: function structChar() {
var parenOnly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
if (this.options.wwwFormUrlEncoded) {
var chr = this.text.charCodeAt(this.pos);
switch (chr) {
case CHAR_AMP:
case CHAR_EQUALS:
if (parenOnly) {
return undefined;
}
this.pos++;
return chr;
}
}
var pos = this.pos;
var c = this.ordinal();
switch (c) {
case CHAR_COMMA:
case CHAR_COLON:
if (parenOnly) {
this.pos = pos;
return undefined;
}
//fallthrough
case CHAR_PAREN_OPEN:
case CHAR_PAREN_CLOSE:
return c;
default:
this.pos = pos;
return undefined;
}
}
/**
* Read the next character code.
*
* If pos is undefined then the characther code will be read and returned,
* and the current position marker will be advanced. Otherwise, the
* character code at the given position will be read and returned by the
* current position marker will remain unchanged.
*
* AQF will apply percent decoding if necessary.
*
* Note, this will *not* perform UTF-8 decoding. That isn't necessary for
* the current use cases.
* @param pos an optional position to read from
*/
}, {
key: "ordinal",
value: function ordinal(pos) {
if (pos !== undefined) {
return this.text.charCodeAt(pos);
}
return this.text.charCodeAt(this.pos++);
}
/**
* Read and accept a single character code.
* @returns true if the expected character was accepted; false otherwise
*/
}, {
key: "accept",
value: function accept(c) {
var pos = this.pos;
if (this.ordinal() === c) {
return true;
}
this.pos = pos;
return false;
}
/**
* Effectively the same as this.accept(CHAR_PLUS) but allows CHAR_PLUS
* to be handled differently for AQF.
* @returns true if the expected character was accepted; false otherwise
*/
}, {
key: "acceptPlus",
value: function acceptPlus() {
//
// Not calling ordinal() because that would decode '+' to a space.
//
if (this.text.charCodeAt(this.pos) == CHAR_PLUS) {
this.pos++;
return true;
}
return false;
}
/**
* Test if all of the parse text has been consumed.
*/
}, {
key: "done",
value: function done() {
return this.end <= this.pos;
}
}, {
key: "validateLiteral",
value: function validateLiteral(ret, mask) {
var text = this.text;
var end = this.end;
for (; ret < end; ret++) {
var c = text.charCodeAt(ret);
var bits = lookup(c) & mask;
switch (bits) {
case 0:
throw new SyntaxError(fmt(MSG_BADCHAR, ret));
case IS_STRUCT:
return ret;
case IS_QUOTE:
return ret + 1;
default:
continue;
}
}
}
/**
* Find the end index of the next literal.
*/
}, {
key: "findLiteralEnd",
value: function findLiteralEnd() {
var text = this.text;
var end = this.end;
var ret = this.pos;
var isQuote = text.charCodeAt(ret) === CHAR_QUOTE;
if (isQuote) {
ret++;
}
var mask = isQuote ? IS_QSTRSAFE | IS_STRUCT | IS_QUOTE : IS_NSTRSAFE | IS_STRUCT;
ret = this.validateLiteral(ret, mask);
if (ret !== undefined) {
return ret;
}
if (isQuote) {
throw new SyntaxError(fmt(MSG_EXPECT_QUOTE, ret));
}
return end;
}
/**
* Test if the next character sequence represents the empty object.
*/
}, {
key: "isEmptyObject",
value: function isEmptyObject() {
if (this.options.noEmptyComposite) {
var start = this.pos;
if (!this.accept(CHAR_COLON)) {
return false;
}
var pos = this.pos;
var ret = this.accept(CHAR_PAREN_CLOSE); //
// this is non-obvious and deserves an explanation.
//
// If I do not match the empty object sequence then I effectively leave
// the current position the same as it was when I entered the function.
// If I do match the empty object sequence then I set the current
// position at the paren that closes it. This allows the caller to
// handle the case with just a small bit of additional logic.
//
this.pos = ret ? pos : start;
return ret;
}
return false;
}
/**
* Parse a single literal value.
*/
}, {
key: "parseLiteral",
value: function parseLiteral(isKey) {
var pos = this.pos;
var options = this.options;
var litend = this.findLiteralEnd();
if (isKey === undefined) {
isKey = this.ordinal(litend) == CHAR_COLON;
}
if (litend <= pos) {
var emptyOK = isKey ? this.options.allowEmptyUnquotedKeys : this.options.allowEmptyUnquotedValues;
return newEmptyString(pos, emptyOK);
} //
// I will consume up to this point
//
if (options.impliedStringLiterals === true) {
return this.parseStringLiteral(litend, true);
}
var tfn = this.parseTrueFalseNull(litend, isKey);
if (tfn !== undefined) {
return tfn;
}
var numval = this.parseNumberLiteral(litend, isKey);
if (numval !== undefined) {
return numval;
}
return this.parseStringLiteral(litend, false);
}
}, {
key: "parseDigits",
value: function parseDigits(litend) {
var ret = false;
var pos;
while (this.pos < litend) {
switch (this.ordinal()) {
case CHAR_0:
case CHAR_0 + 1:
case CHAR_0 + 2:
case CHAR_0 + 3:
case CHAR_0 + 4:
case CHAR_0 + 5:
case CHAR_0 + 6:
case CHAR_0 + 7:
case CHAR_0 + 8:
case CHAR_0 + 9:
pos = this.pos;
ret = true;
continue;
default:
this.pos = pos;
return ret;
}
}
this.pos = pos;
return ret;
}
}, {
key: "parseExponentValue",
value: function parseExponentValue(litend) {
var pos = this.pos;
if (litend <= pos) {
return false;
} //
// consume plus or minus
//
this.acceptPlus() || this.accept(CHAR_DASH);
return this.parseDigits(litend);
}
}, {
key: "parseExponent",
value: function parseExponent(litend) {
var pos = this.pos;
switch (this.ordinal()) {
case CHAR_E:
case CHAR_e:
if (this.parseExponentValue(litend)) {
return true;
}
break;
}
this.pos = pos;
return false;
}
}, {
key: "parseFraction",
value: function parseFraction(litend) {
var pos = this.pos;
if (litend <= pos) {
return false;
}
if (this.accept(CHAR_DOT) && this.parseDigits(litend)) {
return true;
}
this.pos = pos;
return false;
}
}, {
key: "parseInteger",
value: function parseInteger(litend) {
var pos = this.pos;
if (litend <= pos) {
return false;
}
if (this.accept(CHAR_0)) {
return true;
}
return this.parseDigits(litend);
}
}, {
key: "parseNumberLiteral",
value: function parseNumberLiteral(litend, forceString) {
var text = this.text;
var pos = this.pos;
this.accept(CHAR_DASH);
if (this.parseInteger(litend)) {
this.parseFraction(litend);
this.parseExponent(litend);
if (this.pos === litend) {
//
// this literal is a number
//
var s = decodeURIComponent(text.substring(pos, litend));
return forceString ? s : Number(s);
}
}
this.pos = pos;
return undefined;
}
}, {
key: "parseStringLiteral",
value: function parseStringLiteral(litend, impliedString) {
var text = this.text;
var pos = this.pos;
var ret = impliedString || text.charCodeAt(pos) !== CHAR_QUOTE ? text.substring(pos, litend) : text.substring(pos + 1, litend - 1);
ret = decodeURIComponent(ret.replace(RX_DECODE_SPACE, SPACE));
this.pos = litend;
return ret;
}
}, {
key: "parseTrueFalseNull",
value: function parseTrueFalseNull(litend, forceString) {
var text = this.text;
var pos = this.pos;
var c1, c2, c3, c4, c5;
switch (litend - pos) {
case 4:
c1 = text.charCodeAt(pos);
c2 = text.charCodeAt(pos + 1);
c3 = text.charCodeAt(pos + 2);
c4 = text.charCodeAt(pos + 3);
if (c1 === CHAR_t && c2 === CHAR_r && c3 === CHAR_u && c4 === CHAR_e) {
this.pos = litend;
return forceString ? "true" : true;
}
if (c1 === CHAR_n && c2 === CHAR_u && c3 === CHAR_l && c4 === CHAR_l) {
this.pos = litend;
return forceString ? "null" : this.newNullValue();
}
break;
case 5:
c1 = text.charCodeAt(pos);
c2 = text.charCodeAt(pos + 1);
c3 = text.charCodeAt(pos + 2);
c4 = text.charCodeAt(pos + 3);
c5 = text.charCodeAt(pos + 4);
if (c1 === CHAR_f && c2 === CHAR_a && c3 === CHAR_l && c4 === CHAR_s && c5 === CHAR_e) {
this.pos = litend;
return forceString ? "false" : false;
}
break;
}
return undefined;
}
}, {
key: "newEmptyValue",
value: function newEmptyValue() {
var options = this.options;
if (options.noEmptyComposite) {
return [];
}
var emptyValue = options.emptyValue;
if (typeof emptyValue === "function") {
return emptyValue();
}
return emptyValue;
}
}, {
key: "newNullValue",
value: function newNullValue() {
var options = this.options;
var ret = options.nullValue;
if (typeof ret === "function") {
ret = ret();
}
if (ret == null && options.coerceNullToEmptyString) {
ret = EMPTY_STRING;
}
return ret;
}
}]);
return Parser;
}();
/**
* Parser for Address Bar Query String Friendly (AQF) syntax.
* @private
*/
var ParserAQF = /*#__PURE__*/function (_Parser) {
_inherits(ParserAQF, _Parser);
var _super = _createSuper(ParserAQF);
/**
* Construct a new instance.
* @param {JsonURLParseOptions} options options provided by the user
*/
function ParserAQF(text, pos, end, options) {
_classCallCheck(this, ParserAQF);
return _super.call(this, text, pos, end, options);
}
_createClass(ParserAQF, [{
key: "ordinal",
value: function ordinal(pos) {
//
// decode position - use what's given; default to current position.
//
var dpos = pos || this.pos;
var c = this.text.charCodeAt(dpos);
var ret, cnt;
if (c === CHAR_PERCENT) {
ret = hexDecodeOctet(this.text, dpos + 1, this.end);
cnt = 3;
} else {
ret = c;
cnt = 1;
}
if (pos === undefined) {
this.pos += cnt;
}
return ret;
}
}, {
key: "acceptPlus",
value: function acceptPlus() {
return this.accept(CHAR_PLUS);
}
}, {
key: "findLiteralEnd",
value: function findLiteralEnd() {
var end = this.end;
var pos = this.pos;
var text = this.text;
var ret = pos;
var mask = IS_NSTRSAFE | IS_STRUCT | IS_WFU;
for (;;) {
if (end <= this.pos) {
this.pos = pos;
return end;
}
var c = text.charCodeAt(this.pos);
var bits = lookup(c) & mask; //
// validate the potentially encoded character
//
switch (bits) {
case IS_STRUCT | IS_WFU:
if (this.options.wwwFormUrlEncoded) {
ret = this.pos;
this.pos = pos;
return ret;
}
// fallthrough
case 0:
throw new SyntaxError(fmt(MSG_BADCHAR, ret));
} //
// decode
//
switch (this.ordinal()) {
case CHAR_PAREN_OPEN:
case CHAR_PAREN_CLOSE:
case CHAR_COLON:
case CHAR_COMMA:
this.pos = pos;
return ret;
case CHAR_BANG:
if (this.pos === end) {
throw new SyntaxError(fmt(MSG_BAD_ESCAPE, ret));
}
this.ord