Anticipating new JSLint

This commit is contained in:
Douglas Crockford 2015-02-25 10:21:21 -08:00
parent 3d7767b6b1
commit 4982ffbecf
5 changed files with 181 additions and 134 deletions

View file

@ -1,6 +1,6 @@
/*
cycle.js
2013-02-19
2015-02-25
Public Domain.
@ -13,9 +13,10 @@
NOT CONTROL.
*/
/*jslint evil: true, regexp: true */
/*jslint eval, for */
/*members $ref, apply, call, decycle, hasOwnProperty, length, prototype, push,
/*property
$ref, apply, call, decycle, hasOwnProperty, length, prototype, push,
retrocycle, stringify, test, toString
*/
@ -55,9 +56,9 @@ if (typeof JSON.decycle !== 'function') {
if (typeof value === 'object' && value !== null &&
!(value instanceof Boolean) &&
!(value instanceof Date) &&
!(value instanceof Number) &&
!(value instanceof RegExp) &&
!(value instanceof Date) &&
!(value instanceof Number) &&
!(value instanceof RegExp) &&
!(value instanceof String)) {
// If the value is an object or array, look to see if we have already
@ -90,7 +91,7 @@ if (typeof JSON.decycle !== 'function') {
for (name in value) {
if (Object.prototype.hasOwnProperty.call(value, name)) {
nu[name] = derez(value[name],
path + '[' + JSON.stringify(name) + ']');
path + '[' + JSON.stringify(name) + ']');
}
}
}
@ -125,8 +126,7 @@ if (typeof JSON.retrocycle !== 'function') {
// return JSON.retrocycle(JSON.parse(s));
// produces an array containing a single element which is the array itself.
var px =
/^\$(?:\[(?:\d+|\"(?:[^\\\"\u0000-\u001f]|\\([\\\"\/bfnrt]|u[0-9a-zA-Z]{4}))*\")\])*$/;
var px = /^\$(?:\[(?:\d+|\"(?:[^\\\"\u0000-\u001f]|\\([\\\"\/bfnrt]|u[0-9a-zA-Z]{4}))*\")\])*$/;
(function rez(value) {

97
json.js
View file

@ -1,6 +1,6 @@
/*
json.js
2014-02-04
2014-02-25
Public Domain
@ -183,16 +183,15 @@
redistribute.
*/
/*jslint evil: true, regexp: true, unparam: true */
/*jslint eval, for, this */
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
/*property
JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
lastIndex, length, parse, parseJSON, prototype, push, replace, slice,
stringify, test, toJSON, toJSONString, 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.
@ -205,28 +204,32 @@ if (typeof JSON !== 'object') {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
return n < 10
? '0' + n
: n;
}
function this_value() {
return this.valueOf();
}
if (typeof Date.prototype.toJSON !== 'function') {
Date.prototype.toJSON = function (key) {
Date.prototype.toJSON = function (ignore) {
return isFinite(this.valueOf())
? this.getUTCFullYear() + '-' +
? this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z'
: null;
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z'
: null;
};
String.prototype.toJSON =
Number.prototype.toJSON =
Boolean.prototype.toJSON = function (key) {
return this.valueOf();
};
Boolean.prototype.toJSON = this_value;
Number.prototype.toJSON = this_value;
String.prototype.toJSON = this_value;
}
var cx,
@ -245,12 +248,14 @@ if (typeof JSON !== 'object') {
// 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);
}) + '"' : '"' + string + '"';
? c
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"'
: '"' + string + '"';
}
@ -290,7 +295,9 @@ if (typeof JSON !== 'object') {
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : 'null';
return isFinite(value)
? String(value)
: 'null';
case 'boolean':
case 'null':
@ -334,10 +341,10 @@ if (typeof JSON !== 'object') {
// brackets.
v = partial.length === 0
? '[]'
: gap
? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
: '[' + partial.join(',') + ']';
? '[]'
: gap
? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
: '[' + partial.join(',') + ']';
gap = mind;
return v;
}
@ -351,7 +358,9 @@ if (typeof JSON !== 'object') {
if (typeof k === 'string') {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
partial.push(quote(k) + (gap
? ': '
: ':') + v);
}
}
}
@ -363,7 +372,9 @@ if (typeof JSON !== 'object') {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
partial.push(quote(k) + (gap
? ': '
: ':') + v);
}
}
}
@ -372,10 +383,11 @@ if (typeof JSON !== 'object') {
// 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;
return v;
}
@ -384,14 +396,14 @@ if (typeof JSON !== 'object') {
// If the JSON object does not yet have a stringify method, give it one.
if (typeof JSON.stringify !== 'function') {
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'"': '\\"',
'\\': '\\\\'
};
JSON.stringify = function (value, replacer, space) {
@ -480,7 +492,7 @@ if (typeof JSON !== 'object') {
if (cx.test(text)) {
text = text.replace(cx, function (a) {
return '\\u' +
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
@ -497,10 +509,11 @@ if (typeof JSON !== 'object') {
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
if (/^[\],:{}\s]*$/
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
if (/^[\],:{}\s]*$/.test(
text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
.replace(/(?:^|:|,)(?:\s*\[)+/g, '')
)) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
@ -513,8 +526,8 @@ if (typeof JSON !== 'object') {
// each name/value pair to a reviver function for possible transformation.
return typeof reviver === 'function'
? walk({'': j}, '')
: j;
? walk({'': j}, '')
: j;
}
// If the text is not JSON parseable, then a SyntaxError is thrown.

103
json2.js
View file

@ -1,6 +1,6 @@
/*
json2.js
2014-02-04
2015-02-25
Public Domain.
@ -48,7 +48,9 @@
Date.prototype.toJSON = function (key) {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
return n < 10
? '0' + n
: n;
}
return this.getUTCFullYear() + '-' +
@ -146,10 +148,12 @@
redistribute.
*/
/*jslint evil: true, regexp: true */
/*jslint
eval, for, this
*/
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
/*property
JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
lastIndex, length, parse, prototype, push, replace, slice, stringify,
test, toJSON, toString, valueOf
@ -168,7 +172,13 @@ if (typeof JSON !== 'object') {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
return n < 10
? '0' + n
: n;
}
function this_value() {
return this.valueOf();
}
if (typeof Date.prototype.toJSON !== 'function') {
@ -176,20 +186,18 @@ if (typeof JSON !== 'object') {
Date.prototype.toJSON = function () {
return isFinite(this.valueOf())
? this.getUTCFullYear() + '-' +
? this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z'
: null;
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z'
: null;
};
String.prototype.toJSON =
Number.prototype.toJSON =
Boolean.prototype.toJSON = function () {
return this.valueOf();
};
Boolean.prototype.toJSON = this_value;
Number.prototype.toJSON = this_value;
String.prototype.toJSON = this_value;
}
var cx,
@ -208,12 +216,14 @@ if (typeof JSON !== 'object') {
// 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);
}) + '"' : '"' + string + '"';
? c
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"'
: '"' + string + '"';
}
@ -253,7 +263,9 @@ if (typeof JSON !== 'object') {
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : 'null';
return isFinite(value)
? String(value)
: 'null';
case 'boolean':
case 'null':
@ -297,10 +309,10 @@ if (typeof JSON !== 'object') {
// brackets.
v = partial.length === 0
? '[]'
: gap
? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
: '[' + partial.join(',') + ']';
? '[]'
: gap
? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
: '[' + partial.join(',') + ']';
gap = mind;
return v;
}
@ -314,7 +326,11 @@ if (typeof JSON !== 'object') {
k = rep[i];
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
partial.push(quote(k) + (
gap
? ': '
: ':'
) + v);
}
}
}
@ -326,7 +342,11 @@ if (typeof JSON !== 'object') {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
partial.push(quote(k) + (
gap
? ': '
: ':'
) + v);
}
}
}
@ -336,10 +356,10 @@ if (typeof JSON !== 'object') {
// and wrap them in braces.
v = partial.length === 0
? '{}'
: gap
? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
: '{' + partial.join(',') + '}';
? '{}'
: gap
? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
: '{' + partial.join(',') + '}';
gap = mind;
return v;
}
@ -348,14 +368,14 @@ if (typeof JSON !== 'object') {
// If the JSON object does not yet have a stringify method, give it one.
if (typeof JSON.stringify !== 'function') {
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'"': '\\"',
'\\': '\\\\'
};
JSON.stringify = function (value, replacer, space) {
@ -444,7 +464,7 @@ if (typeof JSON !== 'object') {
if (cx.test(text)) {
text = text.replace(cx, function (a) {
return '\\u' +
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
@ -461,10 +481,13 @@ if (typeof JSON !== 'object') {
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
if (/^[\],:{}\s]*$/
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
if (
/^[\],:{}\s]*$/.test(
text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
.replace(/(?:^|:|,)(?:\s*\[)+/g, '')
)
) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
@ -477,8 +500,8 @@ if (typeof JSON !== 'object') {
// each name/value pair to a reviver function for possible transformation.
return typeof reviver === 'function'
? walk({'': j}, '')
: j;
? walk({'': j}, '')
: j;
}
// If the text is not JSON parseable, then a SyntaxError is thrown.

View file

@ -1,6 +1,6 @@
/*
json_parse.js
2012-06-20
2015-02-25
Public Domain.
@ -46,8 +46,11 @@
NOT CONTROL.
*/
/*members "", "\"", "\/", "\\", at, b, call, charAt, f, fromCharCode,
hasOwnProperty, message, n, name, prototype, push, r, t, text
/*jslint for */
/*property
at, b, call, charAt, f, fromCharCode, hasOwnProperty, message, n, name,
prototype, push, r, t, text
*/
var json_parse = (function () {
@ -64,14 +67,14 @@ var json_parse = (function () {
var at, // The index of the current character
ch, // The current character
escapee = {
'"': '"',
'"': '"',
'\\': '\\',
'/': '/',
b: '\b',
f: '\f',
n: '\n',
r: '\r',
t: '\t'
'/': '/',
b: '\b',
f: '\f',
n: '\n',
r: '\r',
t: '\t'
},
text,
@ -80,10 +83,10 @@ var json_parse = (function () {
// Call error when something is wrong.
throw {
name: 'SyntaxError',
name: 'SyntaxError',
message: m,
at: at,
text: text
at: at,
text: text
};
},
@ -302,7 +305,9 @@ var json_parse = (function () {
case '-':
return number();
default:
return ch >= '0' && ch <= '9' ? number() : word();
return ch >= '0' && ch <= '9'
? number()
: word();
}
};
@ -328,22 +333,22 @@ var json_parse = (function () {
// result.
return typeof reviver === 'function'
? (function walk(holder, key) {
var k, v, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
? (function walk(holder, key) {
var k, v, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
return reviver.call(holder, key, value);
}({'': result}, ''))
: result;
}
return reviver.call(holder, key, value);
}({'': result}, ''))
: result;
};
}());

View file

@ -1,6 +1,6 @@
/*
json_parse_state.js
2013-05-26
2015-02-25
Public Domain.
@ -46,13 +46,13 @@
NOT CONTROL.
*/
/*jslint regexp: true, unparam: true */
/*jslint for */
/*members "", "\"", ",", "\/", ":", "[", "\\", "]", acomma, avalue, b,
call, colon, container, exec, f, false, firstavalue, firstokey,
fromCharCode, go, hasOwnProperty, key, length, n, null, ocomma, okey,
ovalue, pop, prototype, push, r, replace, slice, state, t, test, true,
value, "{", "}"
/*property
acomma, avalue, b, call, colon, container, exec, f, false, firstavalue,
firstokey, fromCharCode, go, hasOwnProperty, key, length, n, null, ocomma,
okey, ovalue, pop, prototype, push, r, replace, slice, state, t, test,
true
*/
var json_parse = (function () {
@ -287,8 +287,10 @@ var json_parse = (function () {
// Remove and replace any backslash escapement.
return text.replace(/\\(?:u(.{4})|([^u]))/g, function (a, b, c) {
return b ? String.fromCharCode(parseInt(b, 16)) : escapes[c];
return text.replace(/\\(?:u(.{4})|([^u]))/g, function (ignore, b, c) {
return b
? String.fromCharCode(parseInt(b, 16))
: escapes[c];
});
}
@ -298,7 +300,7 @@ var json_parse = (function () {
// The extraction process is cautious.
var r, // The result of the exec method.
tx = /^[\x20\t\n\r]*(?:([,:\[\]{}]|true|false|null)|(-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)|"((?:[^\r\n\t\\\"]|\\(?:["\\\/trnfb]|u[0-9a-fA-F]{4}))*)")/;
tx = /^[\u0020\t\n\r]*(?:([,:\[\]{}]|true|false|null)|(-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)|"((?:[^\r\n\t\\\"]|\\(?:["\\\/trnfb]|u[0-9a-fA-F]{4}))*)")/;
// Set the starting state.
@ -315,7 +317,7 @@ var json_parse = (function () {
// For each token...
for (;;) {
while (true) {
r = tx.exec(source);
if (!r) {
break;
@ -367,8 +369,10 @@ var json_parse = (function () {
// remaining source contains anything except whitespace, then we did not have
//a well-formed JSON text.
if (state !== 'ok' || /[^\x20\t\n\r]/.test(source)) {
throw state instanceof SyntaxError ? state : new SyntaxError('JSON');
if (state !== 'ok' || (/[^\u0020\t\n\r]/.test(source))) {
throw state instanceof SyntaxError
? state
: new SyntaxError('JSON');
}
// If there is a reviver function, we recursively walk the new structure,
@ -377,7 +381,8 @@ var json_parse = (function () {
// value in an empty key. If there is not a reviver function, we simply return
// that value.
return typeof reviver === 'function' ? (function walk(holder, key) {
return typeof reviver === 'function'
? (function walk(holder, key) {
var k, v, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
@ -392,6 +397,7 @@ var json_parse = (function () {
}
}
return reviver.call(holder, key, value);
}({'': value}, '')) : value;
}({'': value}, ''))
: value;
};
}());