| Index: src/json.js
|
| diff --git a/src/json.js b/src/json.js
|
| index c0af9d0e4630460c4429052f6d667b198b122e9d..6217739e48a4d5a739d6c6ea24c95ccc92352470 100644
|
| --- a/src/json.js
|
| +++ b/src/json.js
|
| @@ -146,41 +146,40 @@ function SerializeObject(value, replacer, stack, indent, gap) {
|
|
|
| function JSONSerialize(key, holder, replacer, stack, indent, gap) {
|
| var value = holder[key];
|
| - if (IS_OBJECT(value) && value) {
|
| + if (IS_SPEC_OBJECT(value)) {
|
| var toJSON = value.toJSON;
|
| if (IS_FUNCTION(toJSON)) {
|
| - value = toJSON.call(value, key);
|
| + value = %_CallFunction(value, key, toJSON);
|
| }
|
| }
|
| if (IS_FUNCTION(replacer)) {
|
| - value = replacer.call(holder, key, value);
|
| + value = %_CallFunction(holder, key, value, replacer);
|
| }
|
| - // Unwrap value if necessary
|
| - if (IS_OBJECT(value)) {
|
| - if (IS_NUMBER_WRAPPER(value)) {
|
| - value = $Number(value);
|
| + if (IS_STRING(value)) {
|
| + return %QuoteJSONString(value);
|
| + } else if (IS_NUMBER(value)) {
|
| + return $isFinite(value) ? $String(value) : "null";
|
| + } else if (IS_BOOLEAN(value)) {
|
| + return value ? "true" : "false";
|
| + } else if (IS_NULL(value)) {
|
| + return "null";
|
| + } else if (IS_SPEC_OBJECT(value) && !(typeof value == "function")) {
|
| + // Non-callable object. If it's a primitive wrapper, it must be unwrapped.
|
| + if (IS_ARRAY(value)) {
|
| + return SerializeArray(value, replacer, stack, indent, gap);
|
| + } else if (IS_NUMBER_WRAPPER(value)) {
|
| + value = ToNumber(value);
|
| + return $isFinite(value) ? ToString(value) : "null";
|
| } else if (IS_STRING_WRAPPER(value)) {
|
| - value = $String(value);
|
| + return %QuoteJSONString(ToString(value));
|
| } else if (IS_BOOLEAN_WRAPPER(value)) {
|
| - value = %_ValueOf(value);
|
| + return %_ValueOf(value) ? "true" : "false";
|
| + } else {
|
| + return SerializeObject(value, replacer, stack, indent, gap);
|
| }
|
| }
|
| - switch (typeof value) {
|
| - case "string":
|
| - return %QuoteJSONString(value);
|
| - case "object":
|
| - if (!value) {
|
| - return "null";
|
| - } else if (IS_ARRAY(value)) {
|
| - return SerializeArray(value, replacer, stack, indent, gap);
|
| - } else {
|
| - return SerializeObject(value, replacer, stack, indent, gap);
|
| - }
|
| - case "number":
|
| - return $isFinite(value) ? $String(value) : "null";
|
| - case "boolean":
|
| - return value ? "true" : "false";
|
| - }
|
| + // Undefined or a callable object.
|
| + return void 0;
|
| }
|
|
|
|
|
| @@ -236,40 +235,41 @@ function BasicSerializeObject(value, stack, builder) {
|
|
|
| function BasicJSONSerialize(key, holder, stack, builder) {
|
| var value = holder[key];
|
| - if (IS_OBJECT(value) && value) {
|
| + if (IS_SPEC_OBJECT(value)) {
|
| var toJSON = value.toJSON;
|
| - if (IS_FUNCTION(toJSON)) value = toJSON.call(value, $String(key));
|
| + if (IS_FUNCTION(toJSON)) {
|
| + value = %_CallFunction(value, ToString(key), toJSON);
|
| + }
|
| }
|
| if (IS_STRING(value)) {
|
| builder.push(%QuoteJSONString(value));
|
| } else if (IS_NUMBER(value)) {
|
| builder.push(($isFinite(value) ? %_NumberToString(value) : "null"));
|
| } else if (IS_BOOLEAN(value)) {
|
| - builder.push((value ? "true" : "false"));
|
| - } else if (IS_OBJECT(value)) {
|
| + builder.push(value ? "true" : "false");
|
| + } else if (IS_NULL(value)) {
|
| + builder.push("null");
|
| + } else if (IS_SPEC_OBJECT(value) && !(typeof value == "function")) {
|
| + // Value is a non-callable object.
|
| // Unwrap value if necessary
|
| if (IS_NUMBER_WRAPPER(value)) {
|
| - value = %_ValueOf(value);
|
| + value = ToNumber(value);
|
| builder.push(($isFinite(value) ? %_NumberToString(value) : "null"));
|
| } else if (IS_STRING_WRAPPER(value)) {
|
| - builder.push(%QuoteJSONString(%_ValueOf(value)));
|
| + builder.push(%QuoteJSONString(ToString(value)));
|
| } else if (IS_BOOLEAN_WRAPPER(value)) {
|
| - builder.push((%_ValueOf(value) ? "true" : "false"));
|
| + builder.push(%_ValueOf(value) ? "true" : "false");
|
| + } else if (IS_ARRAY(value)) {
|
| + BasicSerializeArray(value, stack, builder);
|
| } else {
|
| - // Regular non-wrapped object
|
| - if (!value) {
|
| - builder.push("null");
|
| - } else if (IS_ARRAY(value)) {
|
| - BasicSerializeArray(value, stack, builder);
|
| - } else {
|
| - BasicSerializeObject(value, stack, builder);
|
| - }
|
| + BasicSerializeObject(value, stack, builder);
|
| }
|
| }
|
| }
|
|
|
| +
|
| function JSONStringify(value, replacer, space) {
|
| - if (IS_UNDEFINED(replacer) && IS_UNDEFINED(space)) {
|
| + if (%_ArgumentsLength() == 1) {
|
| var builder = [];
|
| BasicJSONSerialize('', {'': value}, [], builder);
|
| if (builder.length == 0) return;
|
| @@ -280,21 +280,18 @@ function JSONStringify(value, replacer, space) {
|
| if (IS_OBJECT(space)) {
|
| // Unwrap 'space' if it is wrapped
|
| if (IS_NUMBER_WRAPPER(space)) {
|
| - space = $Number(space);
|
| + space = ToNumber(space);
|
| } else if (IS_STRING_WRAPPER(space)) {
|
| - space = $String(space);
|
| + space = ToString(space);
|
| }
|
| }
|
| var gap;
|
| if (IS_NUMBER(space)) {
|
| - space = $Math.min(ToInteger(space), 10);
|
| - gap = "";
|
| - for (var i = 0; i < space; i++) {
|
| - gap += " ";
|
| - }
|
| + space = MathMax(0, MathMin(ToInteger(space), 10));
|
| + gap = SubString(" ", 0, space);
|
| } else if (IS_STRING(space)) {
|
| if (space.length > 10) {
|
| - gap = space.substring(0, 10);
|
| + gap = SubString(space, 0, 10);
|
| } else {
|
| gap = space;
|
| }
|
|
|