Comparing version 0.0.1 to 0.0.3
@@ -11,2 +11,5 @@ { | ||
}, | ||
"files": [ | ||
"src/" | ||
], | ||
"keywords": [ | ||
@@ -26,3 +29,3 @@ "JSON", | ||
}, | ||
"version": "0.0.1" | ||
"version": "0.0.3" | ||
} |
@@ -20,5 +20,4 @@ /* | ||
// This file is copied from the Thrift project under Apache 2.0 license | ||
// There are some changes to variable names and styling | ||
// The other changes are documented before the changes | ||
// This file is copied from the Thrift project under the Apache 2.0 license. There are some changes to variable names, | ||
// styling and code. | ||
@@ -29,7 +28,38 @@ var Int64 = require('node-int64'); | ||
var BYTE_BUFFER_SIZE = 8; | ||
var BYTE_7 = 7; | ||
var BYTE_6 = 6; | ||
var BYTE_5 = 5; | ||
var BYTE_4 = 4; | ||
var BYTE_3 = 3; | ||
var BYTE_2 = 2; | ||
var BYTE_1 = 1; | ||
var MAX_NUM_OF_DECIMAL_DIGITS_REPRESENTABLE_BY_DOUBLE = 15; | ||
var NUM_OF_LEAST_SIGNIFICANT_DIGITS = 11; | ||
var POW10_11 = Math.pow(10, NUM_OF_LEAST_SIGNIFICANT_DIGITS); | ||
var POW10_15 = Math.pow(10, MAX_NUM_OF_DECIMAL_DIGITS_REPRESENTABLE_BY_DOUBLE); | ||
var POW2_24 = Math.pow(2, 24); | ||
var POW2_31 = Math.pow(2, 31); | ||
var POW2_32 = Math.pow(2, 32); | ||
var POW10_11 = Math.pow(10, 11); | ||
var POW2_48 = Math.pow(2, 48); | ||
var POW10_15_OVER_POW2_32 = Math.floor(POW10_15 / POW2_32); | ||
var POW10_15_REMAINDER_POW2_32 = Math.floor(POW10_15 % POW2_32); | ||
var POW2_48_OVER_POW10_11 = Math.floor(POW2_48 / POW10_11); | ||
var POW2_48_REMAINDER_POW10_11 = Math.floor(POW2_48 % POW10_11); | ||
var FOUR_BYTE_BITMASK = 0xffffffff; | ||
var FOUR_BYTE_HIGH_1_BITMASK = 0x80000000; | ||
var ONE_BYTE_BITMASK = 0xff; | ||
var ONE_BYTE_HIGH_1_BITMASK = 0x80; | ||
var ONE_BYTE_HIGH_3_BITMASK = 0xe0; | ||
var ONE_BYTE_BIT_LENGTH = 8; | ||
var TWO_BYTES_BIT_LENGTH = 16; | ||
var MAX_NUM_OF_CHARACTERS_FOR_INT64 = 19; | ||
var MIN_NUM_OF_CHARACTERS_FOR_INT64 = 16; | ||
Int64Util.toDecimalString = function (i64) | ||
@@ -39,4 +69,4 @@ { | ||
var i64Offset = i64.offset; | ||
if ((!i64Buffer[i64Offset] && !(i64Buffer[i64Offset + 1] & 0xe0)) || | ||
(!~i64Buffer[i64Offset] && !~(i64Buffer[i64Offset + 1] & 0xe0))) | ||
if ((!i64Buffer[i64Offset] && !(i64Buffer[i64Offset + BYTE_1] & ONE_BYTE_HIGH_3_BITMASK)) || | ||
(!~i64Buffer[i64Offset] && !~(i64Buffer[i64Offset + BYTE_1] & ONE_BYTE_HIGH_3_BITMASK))) | ||
{ | ||
@@ -46,36 +76,33 @@ // The magnitude is small enough. | ||
} | ||
else | ||
var negative = i64Buffer[i64Offset] & ONE_BYTE_HIGH_1_BITMASK; | ||
if (negative) | ||
{ | ||
var negative = i64Buffer[i64Offset] & 0x80; | ||
if (negative) | ||
// 2's complement | ||
var incremented = false; | ||
var buffer = new Buffer(BYTE_BUFFER_SIZE); | ||
for (var i = BYTE_BUFFER_SIZE - 1; i >= 0; --i) | ||
{ | ||
// 2's complement | ||
var incremented = false; | ||
var buffer = new Buffer(8); | ||
for (var i = 7; i >= 0; --i) | ||
{ | ||
buffer[i] = (~i64Buffer[i64Offset + i] + (incremented ? 0 : 1)) & 0xff; | ||
incremented |= i64Buffer[i64Offset + i]; | ||
} | ||
i64Buffer = buffer; | ||
buffer[i] = (~i64Buffer[i64Offset + i] + (incremented ? 0 : 1)) & ONE_BYTE_BITMASK; | ||
incremented |= i64Buffer[i64Offset + i]; | ||
} | ||
var high2 = i64Buffer[i64Offset + 1] + (i64Buffer[i64Offset] << 8); | ||
// Lesser 11 digits with exceeding values but is under 53 bits capacity. | ||
var low = i64Buffer[i64Offset + 7] + (i64Buffer[i64Offset + 6] << 8) + (i64Buffer[i64Offset + 5] << 16) + | ||
i64Buffer[i64Offset + 4] * POW2_24 // Bit shift renders 32th bit as sign, so use multiplication | ||
+ | ||
(i64Buffer[i64Offset + 3] + (i64Buffer[i64Offset + 2] << 8)) * POW2_32 + high2 * 74976710656; // The literal is 2^48 % 10^11 | ||
// 12th digit and greater. | ||
var high = Math.floor(low / POW10_11) + high2 * 2814; // The literal is 2^48 / 10^11 | ||
// The following if block was added when this file was copied from the Thrift project to fix an issue where | ||
// small negative numbers would have unnecessary leading zeros | ||
if (!high) | ||
{ | ||
low = String(low % POW10_11).slice(-11); | ||
return (negative ? '-' : '') + low; | ||
} | ||
// Make it exactly 11 with leading zeros. | ||
low = ('00000000000' + String(low % POW10_11)).slice(-11); | ||
return (negative ? '-' : '') + String(high) + low; | ||
i64Buffer = buffer; | ||
} | ||
var high2 = i64Buffer[i64Offset + BYTE_1] + (i64Buffer[i64Offset] << ONE_BYTE_BIT_LENGTH); | ||
// Lesser 11 digits with exceeding values but is under 53 bits capacity. | ||
var low = i64Buffer[i64Offset + BYTE_7] + (i64Buffer[i64Offset + BYTE_6] << ONE_BYTE_BIT_LENGTH) + | ||
(i64Buffer[i64Offset + BYTE_5] << TWO_BYTES_BIT_LENGTH) + | ||
i64Buffer[i64Offset + BYTE_4] * POW2_24 // Bit shift renders 32th bit as sign, so use multiplication | ||
+ | ||
(i64Buffer[i64Offset + BYTE_3] + (i64Buffer[i64Offset + BYTE_2] << ONE_BYTE_BIT_LENGTH)) * | ||
POW2_32 + high2 * POW2_48_REMAINDER_POW10_11; | ||
// 12th digit and greater. | ||
var high = Math.floor(low / POW10_11) + high2 * POW2_48_OVER_POW10_11; | ||
if (!high) | ||
{ | ||
low = String(low % POW10_11); | ||
return (negative ? '-' : '') + low; | ||
} | ||
// Make it exactly 11 with leading zeros. | ||
low = ('00000000000' + String(low % POW10_11)).slice(-NUM_OF_LEAST_SIGNIFICANT_DIGITS); | ||
return (negative ? '-' : '') + String(high) + low; | ||
}; | ||
@@ -86,3 +113,3 @@ | ||
var negative = text.charAt(0) === '-'; | ||
if (text.length < (negative ? 17 : 16)) | ||
if (text.length < (negative ? MIN_NUM_OF_CHARACTERS_FOR_INT64 + 1 : MIN_NUM_OF_CHARACTERS_FOR_INT64)) | ||
{ | ||
@@ -92,36 +119,31 @@ // The magnitude is smaller than 2^53. | ||
} | ||
else if (text.length > (negative ? 20 : 19)) | ||
else if (text.length > (negative ? MAX_NUM_OF_CHARACTERS_FOR_INT64 + 1 : MAX_NUM_OF_CHARACTERS_FOR_INT64)) | ||
{ | ||
throw new RangeError('Too many digits for Int64: ' + text); | ||
throw new RangeError('too many digits for Int64: ' + text); | ||
} | ||
else | ||
// Most significant (up to 5) digits | ||
var high5 = +text.slice(negative ? 1 : 0, -MAX_NUM_OF_DECIMAL_DIGITS_REPRESENTABLE_BY_DOUBLE); | ||
var low = +text.slice(-MAX_NUM_OF_DECIMAL_DIGITS_REPRESENTABLE_BY_DOUBLE) + high5 * | ||
POW10_15_REMAINDER_POW2_32; | ||
var high = Math.floor(low / POW2_32) + high5 * POW10_15_OVER_POW2_32; | ||
low = low % POW2_32; | ||
if (high >= POW2_31 && !(negative && high === POW2_31 && low === 0)) // Allow minimum Int64 | ||
{ | ||
// Most significant (up to 5) digits | ||
var high5 = +text.slice(negative ? 1 : 0, -15); | ||
var low = +text.slice(-15) + high5 * 2764472320; // The literal is 10^15 % 2^32 | ||
var high = Math.floor(low / POW2_32) + high5 * 232830; // The literal is 10^15 / 2^&32 | ||
low = low % POW2_32; | ||
// The equality operators were changed to '===' from '==' when this file was copied from the Thrift project | ||
if (high >= POW2_31 && | ||
!(negative && high === POW2_31 && low === 0) // Allow minimum Int64 | ||
) | ||
throw new RangeError('the magnitude is too large for Int64'); | ||
} | ||
if (negative) | ||
{ | ||
// 2's complement | ||
high = ~high; | ||
if (low === 0) | ||
{ | ||
throw new RangeError('The magnitude is too large for Int64.'); | ||
high = (high + 1) & FOUR_BYTE_BITMASK; | ||
} | ||
if (negative) | ||
else | ||
{ | ||
// 2's complement | ||
high = ~high; | ||
if (low === 0) | ||
{ | ||
high = (high + 1) & 0xffffffff; | ||
} | ||
else | ||
{ | ||
low = ~low + 1; | ||
} | ||
high = 0x80000000 | high; | ||
low = ~low + 1; | ||
} | ||
return new Int64(high, low); | ||
high = FOUR_BYTE_HIGH_1_BITMASK | high; | ||
} | ||
return new Int64(high, low); | ||
}; |
381
src/parse.js
@@ -6,17 +6,16 @@ /* | ||
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. | ||
This code should be minified before deployment. | ||
See http://javascript.crockford.com/jsmin.html | ||
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO NOT CONTROL. | ||
This file creates a json_parse function. | ||
During create you can (optionally) specify some behavioural switches | ||
require('json-long') | ||
require('json-int64') | ||
The resulting function follows this signature: | ||
json_parse(text, reviver) | ||
This method parses a JSON text to produce an object or array. | ||
It can throw a SyntaxError exception. | ||
The optional reviver parameter is a function that can filter and | ||
transform the results. It receives each of the keys and values, | ||
and its return value is used instead of the original value. | ||
If it returns what it received, then the structure is not modified. | ||
If it returns undefined then the member is deleted. | ||
This method parses a JSON text to produce an object or array. It can throw a SyntaxError exception. The | ||
optional reviver parameter is a function that can filter and transform the results. It receives each of the | ||
keys and values, and its return value is used instead of the original value. If it returns what it received, | ||
then the structure is not modified. If it returns undefined then the member is deleted. | ||
Example: | ||
// Parse the text. Values that look like ISO date strings will | ||
// be converted to Date objects. | ||
// Parse the text. Values that look like ISO date strings will be converted to Date objects. | ||
myData = json_parse(text, function (key, value) { | ||
@@ -34,63 +33,88 @@ var a; | ||
}); | ||
This is a reference implementation. You are free to copy, modify, or | ||
redistribute. | ||
This code should be minified before deployment. | ||
See http://javascript.crockford.com/jsmin.html | ||
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO | ||
NOT CONTROL. | ||
This is a reference implementation. You are free to copy, modify, or redistribute. | ||
*/ | ||
/*members "", "\"", "\/", "\\", at, b, call, charAt, f, fromCharCode, | ||
hasOwnProperty, message, n, name, prototype, push, r, t, text | ||
/*members "", "\"", "\/", "\\", at, b, call, charAt, f, fromCharCode, hasOwnProperty, message, n, name, prototype, | ||
push, r, t, text | ||
*/ | ||
var Int64Util = null; | ||
var json_parse = function (options) { | ||
var json_parse = function () | ||
{ | ||
"use strict"; | ||
// This is a function that can parse a JSON text, producing a JavaScript | ||
// data structure. It is a simple, recursive descent parser. It does not use | ||
// eval or regular expressions, so it can be used as a model for implementing | ||
// a JSON parser in other languages. | ||
// This is a function that can parse a JSON text, producing a JavaScript data structure. It is a simple, recursive | ||
// descent parser. It does not use eval or regular expressions, so it can be used as a model for implementing | ||
// a JSON parser in other languages. | ||
// We are defining the function inside of another function to avoid creating | ||
// global variables. | ||
// We are defining the function inside of another function to avoid creating global variables. | ||
var at, // The index of the current character | ||
ch, // The current character | ||
escapee = { | ||
'"': '"', | ||
'\\': '\\', | ||
'/': '/', | ||
b: '\b', | ||
f: '\f', | ||
n: '\n', | ||
r: '\r', | ||
t: '\t' | ||
var at; // The index of the current character | ||
var ch; // The current character | ||
var escapee = { | ||
'"': '"', | ||
'/': '/', | ||
'\\': '\\', | ||
b: '\b', | ||
f: '\f', | ||
n: '\n', | ||
r: '\r', | ||
t: '\t' | ||
}; | ||
var text | ||
var array = function () | ||
{ | ||
// Parse an array value. | ||
var array = []; | ||
if (ch === '[') | ||
{ | ||
next('['); | ||
white(); | ||
if (ch === ']') | ||
{ | ||
next(']'); | ||
return array; // empty array | ||
} | ||
while (ch) | ||
{ | ||
array.push(value()); | ||
white(); | ||
if (ch === ']') | ||
{ | ||
next(']'); | ||
return array; | ||
} | ||
next(','); | ||
white(); | ||
} | ||
} | ||
error("bad array"); | ||
}, | ||
text, | ||
error = function (m) { | ||
error = function (message) | ||
{ | ||
// Call error when something is wrong. | ||
// Call error when something is wrong. | ||
throw { | ||
name: 'SyntaxError', | ||
message: m, | ||
at: at, | ||
text: text | ||
at: at, | ||
message: message, | ||
name: 'SyntaxError', | ||
text: text | ||
}; | ||
}, | ||
next = function (c) { | ||
next = function (c) | ||
{ | ||
// If a c parameter is provided, verify that it matches the current character. | ||
// If a c parameter is provided, verify that it matches the current character. | ||
if (c && c !== ch) { | ||
error("Expected '" + c + "' instead of '" + ch + "'"); | ||
if (c && c !== ch) | ||
{ | ||
error("expected '" + c + "' instead of '" + ch + "'"); | ||
} | ||
// Get the next character. When there are no more characters, | ||
// return the empty string. | ||
// Get the next character. When there are no more characters, return the empty string. | ||
@@ -102,4 +126,5 @@ ch = text.charAt(at); | ||
number = function () { | ||
// Parse a number value. | ||
number = function () | ||
{ | ||
// Parse a number value. | ||
var isFloat = false; | ||
@@ -109,26 +134,33 @@ var number, | ||
if (ch === '-') { | ||
if (ch === '-') | ||
{ | ||
string = '-'; | ||
next('-'); | ||
} | ||
while (ch >= '0' && ch <= '9') { | ||
while (ch >= '0' && ch <= '9') | ||
{ | ||
string += ch; | ||
next(); | ||
} | ||
if (ch === '.') { | ||
if (ch === '.') | ||
{ | ||
isFloat = true; | ||
string += '.'; | ||
while (next() && ch >= '0' && ch <= '9') { | ||
while (next() && ch >= '0' && ch <= '9') | ||
{ | ||
string += ch; | ||
} | ||
} | ||
if (ch === 'e' || ch === 'E') { | ||
if (ch === 'e' || ch === 'E') | ||
{ | ||
isFloat = true; | ||
string += ch; | ||
next(); | ||
if (ch === '-' || ch === '+') { | ||
if (ch === '-' || ch === '+') | ||
{ | ||
string += ch; | ||
next(); | ||
} | ||
while (ch >= '0' && ch <= '9') { | ||
while (ch >= '0' && ch <= '9') | ||
{ | ||
string += ch; | ||
@@ -139,10 +171,13 @@ next(); | ||
number = +string; | ||
if (!isFinite(number)) { | ||
error("Bad number"); | ||
} else { | ||
if (!isFinite(number)) | ||
{ | ||
error("bad number"); | ||
} | ||
else | ||
{ | ||
if (!isFloat && Number(string).toString() !== string) | ||
{ | ||
if (Int64Util == null) | ||
if (Int64Util === null) | ||
Int64Util = require("./int64_util.js"); | ||
return Int64Util.fromDecimalString(string); | ||
return Int64Util.fromDecimalString(string); | ||
} | ||
@@ -153,6 +188,45 @@ return number | ||
string = function () { | ||
object = function () | ||
{ | ||
// Parse an object value. | ||
// Parse a string value. | ||
var key, | ||
object = {}; | ||
if (ch === '{') | ||
{ | ||
next('{'); | ||
white(); | ||
if (ch === '}') | ||
{ | ||
next('}'); | ||
return object; // empty object | ||
} | ||
while (ch) | ||
{ | ||
key = string(); | ||
white(); | ||
next(':'); | ||
if (Object.hasOwnProperty.call(object, key)) | ||
{ | ||
error('duplicate key "' + key + '"'); | ||
} | ||
object[key] = value(); | ||
white(); | ||
if (ch === '}') | ||
{ | ||
next('}'); | ||
return object; | ||
} | ||
next(','); | ||
white(); | ||
} | ||
} | ||
error("bad object"); | ||
}, | ||
string = function () | ||
{ | ||
// Parse a string value. | ||
var hex, | ||
@@ -163,17 +237,24 @@ i, | ||
// When parsing for string values, we must look for " and \ characters. | ||
// When parsing for string values, we must look for " and \ characters. | ||
if (ch === '"') { | ||
while (next()) { | ||
if (ch === '"') { | ||
if (ch === '"') | ||
{ | ||
while (next()) | ||
{ | ||
if (ch === '"') | ||
{ | ||
next(); | ||
return string; | ||
} | ||
if (ch === '\\') { | ||
if (ch === '\\') | ||
{ | ||
next(); | ||
if (ch === 'u') { | ||
if (ch === 'u') | ||
{ | ||
uffff = 0; | ||
for (i = 0; i < 4; i += 1) { | ||
for (i = 0; i < 4; i += 1) | ||
{ | ||
hex = parseInt(next(), 16); | ||
if (!isFinite(hex)) { | ||
if (!isFinite(hex)) | ||
{ | ||
break; | ||
@@ -184,8 +265,14 @@ } | ||
string += String.fromCharCode(uffff); | ||
} else if (typeof escapee[ch] === 'string') { | ||
} | ||
else if (typeof escapee[ch] === 'string') | ||
{ | ||
string += escapee[ch]; | ||
} else { | ||
} | ||
else | ||
{ | ||
break; | ||
} | ||
} else { | ||
} | ||
else | ||
{ | ||
string += ch; | ||
@@ -195,10 +282,13 @@ } | ||
} | ||
error("Bad string"); | ||
error("bad string"); | ||
}, | ||
white = function () { | ||
value, // Place holder for the value function. | ||
// Skip whitespace. | ||
white = function () | ||
{ | ||
// Skip whitespace. | ||
while (ch && ch <= ' ') { | ||
while (ch && ch <= ' ') | ||
{ | ||
next(); | ||
@@ -208,7 +298,8 @@ } | ||
word = function () { | ||
word = function () | ||
{ | ||
// true, false, or null. | ||
// true, false, or null. | ||
switch (ch) { | ||
switch (ch) | ||
{ | ||
case 't': | ||
@@ -234,75 +325,12 @@ next('t'); | ||
} | ||
error("Unexpected '" + ch + "'"); | ||
}, | ||
value, // Place holder for the value function. | ||
array = function () { | ||
// Parse an array value. | ||
var array = []; | ||
if (ch === '[') { | ||
next('['); | ||
white(); | ||
if (ch === ']') { | ||
next(']'); | ||
return array; // empty array | ||
} | ||
while (ch) { | ||
array.push(value()); | ||
white(); | ||
if (ch === ']') { | ||
next(']'); | ||
return array; | ||
} | ||
next(','); | ||
white(); | ||
} | ||
} | ||
error("Bad array"); | ||
}, | ||
object = function () { | ||
// Parse an object value. | ||
var key, | ||
object = {}; | ||
if (ch === '{') { | ||
next('{'); | ||
white(); | ||
if (ch === '}') { | ||
next('}'); | ||
return object; // empty object | ||
} | ||
while (ch) { | ||
key = string(); | ||
white(); | ||
next(':'); | ||
if (Object.hasOwnProperty.call(object, key)) { | ||
error('Duplicate key "' + key + '"'); | ||
} | ||
object[key] = value(); | ||
white(); | ||
if (ch === '}') { | ||
next('}'); | ||
return object; | ||
} | ||
next(','); | ||
white(); | ||
} | ||
} | ||
error("Bad object"); | ||
error("unexpected '" + ch + "'"); | ||
}; | ||
value = function () { | ||
value = function () | ||
{ | ||
// Parse a JSON value. It could be an object, an array, a string, a number, or a word. | ||
// Parse a JSON value. It could be an object, an array, a string, a number, | ||
// or a word. | ||
white(); | ||
switch (ch) { | ||
switch (ch) | ||
{ | ||
case '{': | ||
@@ -321,6 +349,6 @@ return object(); | ||
// Return the json_parse function. It will have access to all of the above | ||
// functions and variables. | ||
// Return the json_parse function. It will have access to all of the above functions and variables. | ||
return function (source, reviver) { | ||
return function (source, reviver) | ||
{ | ||
var result; | ||
@@ -333,21 +361,26 @@ | ||
white(); | ||
if (ch) { | ||
error("Syntax error"); | ||
if (ch) | ||
{ | ||
error("syntax error"); | ||
} | ||
// If there is a reviver function, we recursively walk the new structure, | ||
// passing each name/value pair to the reviver function for possible | ||
// transformation, starting with a temporary root object that holds the result | ||
// in an empty key. If there is not a reviver function, we simply return the | ||
// result. | ||
// If there is a reviver function, we recursively walk the new structure, passing each name/value pair to the | ||
// reviver function for possible transformation, starting with a temporary root object that holds the result | ||
// in an empty key. If there is not a reviver function, we simply return the result. | ||
return typeof reviver === 'function' | ||
? (function walk(holder, key) { | ||
var k, v, value = holder[key]; | ||
if (value && typeof value === 'object') { | ||
Object.keys(value).forEach(function(k) { | ||
return typeof reviver === 'function' ? | ||
(function walk(holder, key) | ||
{ | ||
var v, value = holder[key]; | ||
if (value && typeof value === 'object') | ||
{ | ||
Object.keys(value).forEach(function (k) | ||
{ | ||
v = walk(value, k); | ||
if (v !== undefined) { | ||
if (v !== undefined) | ||
{ | ||
value[k] = v; | ||
} else { | ||
} | ||
else | ||
{ | ||
delete value[k]; | ||
@@ -358,4 +391,4 @@ } | ||
return reviver.call(holder, key, value); | ||
}({'': result}, '')) | ||
: result; | ||
}({ '': result }, '')) : | ||
result; | ||
}; | ||
@@ -362,0 +395,0 @@ } |
@@ -1,2 +0,1 @@ | ||
var Int64 = require('node-int64'); | ||
var Int64Util = require('./int64_util.js'); | ||
@@ -12,25 +11,17 @@ | ||
See http://javascript.crockford.com/jsmin.html | ||
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO | ||
NOT CONTROL. | ||
This file creates a global JSON object containing two methods: stringify | ||
and parse. | ||
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO NOT CONTROL. | ||
This file creates a global JSON object containing two methods: stringify and parse. | ||
JSON.stringify(value, replacer, space) | ||
value any JavaScript value, usually an object or array. | ||
replacer an optional parameter that determines how object | ||
values are stringified for objects. It can be a | ||
replacer an optional parameter that determines how object values are stringified for objects. It can be a | ||
function or an array of strings. | ||
space an optional parameter that specifies the indentation | ||
of nested structures. If it is omitted, the text will | ||
be packed without extra whitespace. If it is a number, | ||
it will specify the number of spaces to indent at each | ||
level. If it is a string (such as '\t' or ' '), | ||
it contains the characters used to indent at each level. | ||
This method produces a JSON text from a JavaScript value. | ||
When an object value is found, if the object contains a toJSON | ||
method, its toJSON method will be called and the result will be | ||
stringified. A toJSON method does not serialize: it returns the | ||
value represented by the name/value pair that should be serialized, | ||
or undefined if nothing should be serialized. The toJSON method | ||
will be passed the key associated with the value, and this will be | ||
bound to the value | ||
space an optional parameter that specifies the indentation of nested structures. If it is omitted, the | ||
text will be packed without extra whitespace. If it is a number, it will specify the number of | ||
spaces to indent at each level. If it is a string (such as '\t' or ' '), it contains the | ||
characters used to indent at each level. | ||
This method produces a JSON text from a JavaScript value. When an object value is found, if the object | ||
contains a toJSON method, its toJSON method will be called and the result will be stringified. A toJSON | ||
method does not serialize: it returns the value represented by the name/value pair that should be | ||
serialized, or undefined if nothing should be serialized. The toJSON method will be passed the key | ||
associated with the value, and this will be bound to the value. | ||
For example, this would serialize Dates as ISO strings. | ||
@@ -49,22 +40,13 @@ Date.prototype.toJSON = function (key) { | ||
}; | ||
You can provide an optional replacer method. It will be passed the | ||
key and value of each member, with this bound to the containing | ||
object. The value that is returned from your method will be | ||
serialized. If your method returns undefined, then the member will | ||
be excluded from the serialization. | ||
If the replacer parameter is an array of strings, then it will be | ||
used to select the members to be serialized. It filters the results | ||
such that only members with keys listed in the replacer array are | ||
stringified. | ||
Values that do not have JSON representations, such as undefined or | ||
functions, will not be serialized. Such values in objects will be | ||
dropped; in arrays they will be replaced with null. You can use | ||
a replacer function to replace those with JSON values. | ||
JSON.stringify(undefined) returns undefined. | ||
The optional space parameter produces a stringification of the | ||
value that is filled with line breaks and indentation to make it | ||
easier to read. | ||
If the space parameter is a non-empty string, then that string will | ||
be used for indentation. If the space parameter is a number, then | ||
the indentation will be that many spaces. | ||
You can provide an optional replacer method. It will be passed the key and value of each member, with this | ||
bound to the containing object. The value that is returned from your method will be serialized. If your | ||
method returns undefined, then the member will be excluded from the serialization. If the replacer parameter | ||
is an array of strings, then it will be used to select the members to be serialized. It filters the results | ||
such that only members with keys listed in the replacer array are stringified. Values that do not have JSON | ||
representations, such as undefined or functions, will not be serialized. Such values in objects will be | ||
dropped; in arrays they will be replaced with null. You can use a replacer function to replace those with | ||
JSON values. JSON.stringify(undefined) returns undefined. The optional space parameter produces a | ||
stringification of the value that is filled with line breaks and indentation to make it easier to read. If | ||
the space parameter is a non-empty string, then that string will be used for indentation. If the space | ||
parameter is a number, then the indentation will be that many spaces. | ||
Example: | ||
@@ -80,39 +62,3 @@ text = JSON.stringify(['e', {pluribus: 'unum'}]); | ||
// text is '["Date(---current time---)"]' | ||
JSON.parse(text, reviver) | ||
This method parses a JSON text to produce an object or array. | ||
It can throw a SyntaxError exception. | ||
The optional reviver parameter is a function that can filter and | ||
transform the results. It receives each of the keys and values, | ||
and its return value is used instead of the original value. | ||
If it returns what it received, then the structure is not modified. | ||
If it returns undefined then the member is deleted. | ||
Example: | ||
// Parse the text. Values that look like ISO date strings will | ||
// be converted to Date objects. | ||
myData = JSON.parse(text, function (key, value) { | ||
var a; | ||
if (typeof value === 'string') { | ||
a = | ||
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); | ||
if (a) { | ||
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], | ||
+a[5], +a[6])); | ||
} | ||
} | ||
return value; | ||
}); | ||
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { | ||
var d; | ||
if (typeof value === 'string' && | ||
value.slice(0, 5) === 'Date(' && | ||
value.slice(-1) === ')') { | ||
d = new Date(value.slice(5, -1)); | ||
if (d) { | ||
return d; | ||
} | ||
} | ||
return value; | ||
}); | ||
This is a reference implementation. You are free to copy, modify, or | ||
redistribute. | ||
This is a reference implementation. You are free to copy, modify, or redistribute. | ||
*/ | ||
@@ -122,28 +68,24 @@ | ||
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, | ||
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, | ||
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, | ||
lastIndex, length, parse, prototype, push, replace, slice, stringify, | ||
test, toJSON, toString, valueOf | ||
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, call, charCodeAt, getUTCDate, getUTCFullYear, | ||
getUTCHours, getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, lastIndex, length, parse, prototype, | ||
push, replace, slice, stringify, test, toJSON, toString, valueOf | ||
*/ | ||
// Create a JSON object only if one does not already exist. We create the | ||
// methods in a closure to avoid creating global variables. | ||
// Create a JSON object only if one does not already exist. We create the methods in a closure to avoid creating global | ||
// variables. | ||
var JSON = module.exports; | ||
(function () { | ||
var BASE_16 = 16; | ||
(function () | ||
{ | ||
'use strict'; | ||
function f(n) { | ||
// Format integers to have at least two digits. | ||
return n < 10 ? '0' + n : n; | ||
} | ||
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, | ||
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, | ||
var escapable = | ||
/[\\"\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, | ||
gap, | ||
indent, | ||
meta = { // table of character substitutions | ||
meta = { // table of character substitutions | ||
'\b': '\\b', | ||
@@ -154,3 +96,3 @@ '\t': '\\t', | ||
'\r': '\\r', | ||
'"' : '\\"', | ||
'"': '\\"', | ||
'\\': '\\\\' | ||
@@ -161,15 +103,15 @@ }, | ||
function quote(string) { | ||
function quote(string) | ||
{ | ||
// If the string contains no control characters, no quote characters, and no backslash characters, then we can | ||
// safely slap some quotes around it. Otherwise we must also replace the offending characters with safe escape | ||
// sequences. | ||
// If the string contains no control characters, no quote characters, and no | ||
// backslash characters, then we can safely slap some quotes around it. | ||
// Otherwise we must also replace the offending characters with safe escape | ||
// sequences. | ||
escapable.lastIndex = 0; | ||
return escapable.test(string) ? '"' + string.replace(escapable, function (a) { | ||
return escapable.test(string) ? '"' + string.replace(escapable, function (a) | ||
{ | ||
var c = meta[a]; | ||
return typeof c === 'string' | ||
? c | ||
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); | ||
return typeof c === 'string' ? | ||
c : | ||
'\\u' + ('0000' + a.charCodeAt(0).toString(BASE_16)).slice(-4); | ||
}) + '"' : '"' + string + '"'; | ||
@@ -179,38 +121,67 @@ } | ||
function str(key, holder) { | ||
function str(key, holder) | ||
{ | ||
// Produce a string from holder[key]. | ||
// Produce a string from holder[key]. | ||
var i; // The loop counter. | ||
var k; // The member key. | ||
var v; // The member value. | ||
var length; | ||
var mind = gap; | ||
var partial; | ||
var value = holder[key]; | ||
var isInt64 = true; | ||
var Int64Keys = ["buffer", "offset"]; | ||
var Int64Types = [Uint8Array, Number]; | ||
var valueKeys = []; | ||
var i, // The loop counter. | ||
k, // The member key. | ||
v, // The member value. | ||
length, | ||
mind = gap, | ||
partial, | ||
value = holder[key], | ||
isInt64 = value != null && value instanceof Int64; | ||
if (value !== null && value !== undefined) | ||
{ | ||
valueKeys = Object.keys(value).sort(); | ||
// Since javascript is duck-typed, we check the keys of the object and their types. Built-in types are ok. | ||
if (valueKeys.length === Int64Keys.length) | ||
{ | ||
for (var it = 0; isInt64 && it < valueKeys.length; ++it) | ||
{ | ||
if ((valueKeys[it] !== Int64Keys[it]) || (!value[valueKeys[it]] instanceof Int64Types[it])) | ||
{ | ||
isInt64 = false; | ||
break; | ||
} | ||
} | ||
} | ||
else | ||
{ | ||
isInt64 = false; | ||
} | ||
} | ||
else | ||
{ | ||
isInt64 = false; | ||
} | ||
// If the value has a toJSON method, call it to obtain a replacement value. | ||
// If the value has a toJSON method, call it to obtain a replacement value. | ||
if (value && typeof value === 'object' && | ||
typeof value.toJSON === 'function') { | ||
if (value && typeof value === 'object' && typeof value.toJSON === 'function') | ||
{ | ||
value = value.toJSON(key); | ||
} | ||
// If we were called with a replacer function, then call the replacer to | ||
// obtain a replacement value. | ||
// If we were called with a replacer function, then call the replacer to obtain a replacement value. | ||
if (typeof rep === 'function') { | ||
if (typeof rep === 'function') | ||
{ | ||
value = rep.call(holder, key, value); | ||
} | ||
// What happens next depends on the value's type. | ||
// What happens next depends on the value's type. | ||
switch (typeof value) { | ||
switch (typeof value) | ||
{ | ||
case 'string': | ||
return quote(value); | ||
return quote(value); | ||
case 'number': | ||
// JSON numbers must be finite. Encode non-finite numbers as null. | ||
// JSON numbers must be finite. Encode non-finite numbers as null. | ||
@@ -222,17 +193,15 @@ return isFinite(value) ? String(value) : 'null'; | ||
// If the value is a boolean or null, convert it to a string. Note: | ||
// typeof null does not produce 'null'. The case is included here in | ||
// the remote chance that this gets fixed someday. | ||
// If the value is a boolean or null, convert it to a string. Note: typeof null does not produce 'null'. | ||
// The case is included here in the remote chance that this gets fixed someday. | ||
return String(value); | ||
// If the type is 'object', we might be dealing with an object or an array or | ||
// null. | ||
// If the type is 'object', we might be dealing with an object or an array or null. | ||
case 'object': | ||
// Due to a specification blunder in ECMAScript, typeof null is 'object', | ||
// so watch out for that case. | ||
// Due to a specification blunder in ECMAScript, typeof null is 'object', so watch out for that case. | ||
if (!value) { | ||
if (!value) | ||
{ | ||
return 'null'; | ||
@@ -246,3 +215,3 @@ } | ||
// Make an array to hold the partial results of stringifying this object value. | ||
// Make an array to hold the partial results of stringifying this object value. | ||
@@ -252,22 +221,21 @@ gap += indent; | ||
// Is the value an array? | ||
// Is the value an array? | ||
if (Object.prototype.toString.apply(value) === '[object Array]') { | ||
if (Object.prototype.toString.apply(value) === '[object Array]') | ||
{ | ||
// The value is an array. Stringify every element. Use null as a placeholder for non-JSON values. | ||
// The value is an array. Stringify every element. Use null as a placeholder | ||
// for non-JSON values. | ||
length = value.length; | ||
for (i = 0; i < length; i += 1) { | ||
for (i = 0; i < length; i += 1) | ||
{ | ||
partial[i] = str(i, value) || 'null'; | ||
} | ||
// Join all of the elements together, separated with commas, and wrap them in | ||
// brackets. | ||
// Join all of the elements together, separated with commas, and wrap them in brackets. | ||
v = partial.length === 0 | ||
? '[]' | ||
: gap | ||
? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' | ||
: '[' + partial.join(',') + ']'; | ||
v = partial.length === 0 ? | ||
'[]' : | ||
gap ? | ||
'[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : | ||
'[' + partial.join(',') + ']'; | ||
gap = mind; | ||
@@ -277,11 +245,15 @@ return v; | ||
// If the replacer is an array, use it to select the members to be stringified. | ||
// If the replacer is an array, use it to select the members to be stringified. | ||
if (rep && typeof rep === 'object') { | ||
if (rep && typeof rep === 'object') | ||
{ | ||
length = rep.length; | ||
for (i = 0; i < length; i += 1) { | ||
if (typeof rep[i] === 'string') { | ||
for (i = 0; i < length; i += 1) | ||
{ | ||
if (typeof rep[i] === 'string') | ||
{ | ||
k = rep[i]; | ||
v = str(k, value); | ||
if (v) { | ||
if (v) | ||
{ | ||
partial.push(quote(k) + (gap ? ': ' : ':') + v); | ||
@@ -291,9 +263,12 @@ } | ||
} | ||
} else { | ||
} | ||
else | ||
{ | ||
// Otherwise, iterate through all of the keys in the object. | ||
// Otherwise, iterate through all of the keys in the object. | ||
Object.keys(value).forEach(function(k) { | ||
Object.keys(value).forEach(function (k) | ||
{ | ||
var v = str(k, value); | ||
if (v) { | ||
if (v) | ||
{ | ||
partial.push(quote(k) + (gap ? ': ' : ':') + v); | ||
@@ -304,10 +279,9 @@ } | ||
// Join all of the member texts together, separated with commas, | ||
// and wrap them in braces. | ||
// Join all of the member texts together, separated with commas, and wrap them in braces. | ||
v = partial.length === 0 | ||
? '{}' | ||
: gap | ||
? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' | ||
: '{' + partial.join(',') + '}'; | ||
v = partial.length === 0 ? | ||
'{}' : | ||
gap ? | ||
'{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : | ||
'{' + partial.join(',') + '}'; | ||
gap = mind; | ||
@@ -318,13 +292,13 @@ return v; | ||
// If the JSON object does not yet have a stringify method, give it one. | ||
// If the JSON object does not yet have a stringify method, give it one. | ||
if (typeof JSON.stringify !== 'function') { | ||
JSON.stringify = function (value, replacer, space) { | ||
if (typeof JSON.stringify !== 'function') | ||
{ | ||
JSON.stringify = function (value, replacer, space) | ||
{ | ||
// The stringify method takes a value and an optional replacer, and an optional space parameter, and returns | ||
// a JSON text. The replacer can be a function that can replace values, or an array of strings that will | ||
// select the keys. A default replacer method can be provided. Use of the space parameter can produce text | ||
// that is more easily readable. | ||
// The stringify method takes a value and an optional replacer, and an optional | ||
// space parameter, and returns a JSON text. The replacer can be a function | ||
// that can replace values, or an array of strings that will select the keys. | ||
// A default replacer method can be provided. Use of the space parameter can | ||
// produce text that is more easily readable. | ||
var i; | ||
@@ -334,32 +308,34 @@ gap = ''; | ||
// If the space parameter is a number, make an indent string containing that | ||
// many spaces. | ||
// If the space parameter is a number, make an indent string containing that many spaces. | ||
if (typeof space === 'number') { | ||
for (i = 0; i < space; i += 1) { | ||
if (typeof space === 'number') | ||
{ | ||
for (i = 0; i < space; i += 1) | ||
{ | ||
indent += ' '; | ||
} | ||
// If the space parameter is a string, it will be used as the indent string. | ||
// If the space parameter is a string, it will be used as the indent string. | ||
} else if (typeof space === 'string') { | ||
} | ||
else if (typeof space === 'string') | ||
{ | ||
indent = space; | ||
} | ||
// If there is a replacer, it must be a function or an array. | ||
// Otherwise, throw an error. | ||
// If there is a replacer, it must be a function or an array. Otherwise, throw an error. | ||
rep = replacer; | ||
if (replacer && typeof replacer !== 'function' && | ||
(typeof replacer !== 'object' || | ||
typeof replacer.length !== 'number')) { | ||
throw new Error('JSON.stringify'); | ||
(typeof replacer !== 'object' || typeof replacer.length !== 'number')) | ||
{ | ||
throw new Error('the type of the replacer must be a function or an array, found ' + typeof replacer); | ||
} | ||
// Make a fake root object containing our value under the key of ''. | ||
// Return the result of stringifying the value. | ||
// Make a fake root object containing our value under the key of ''. Return the result of stringifying the | ||
// value. | ||
return str('', {'': value}); | ||
return str('', { '': value }); | ||
}; | ||
} | ||
}()); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
43306
8
765