| OLD | NEW | 
|---|
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 (function(global, utils) { | 5 (function(global, utils) { | 
| 6 | 6 | 
| 7 "use strict"; | 7 "use strict"; | 
| 8 | 8 | 
| 9 %CheckIsBootstrapping(); | 9 %CheckIsBootstrapping(); | 
| 10 | 10 | 
| 11 // ------------------------------------------------------------------- | 11 // ------------------------------------------------------------------- | 
| 12 // Imports | 12 // Imports | 
| 13 | 13 | 
| 14 var GlobalJSON = global.JSON; | 14 var GlobalJSON = global.JSON; | 
|  | 15 var GlobalSet = global.Set; | 
| 15 var InternalArray = utils.InternalArray; | 16 var InternalArray = utils.InternalArray; | 
| 16 var MakeTypeError; | 17 var MakeTypeError; | 
| 17 var MaxSimple; | 18 var MaxSimple; | 
| 18 var MinSimple; | 19 var MinSimple; | 
| 19 var ObjectHasOwnProperty; | 20 var ObjectHasOwnProperty; | 
| 20 var ObjectKeys; | 21 var ObjectKeys; | 
| 21 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol"); | 22 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol"); | 
| 22 | 23 | 
| 23 utils.Import(function(from) { | 24 utils.Import(function(from) { | 
| 24   MakeTypeError = from.MakeTypeError; | 25   MakeTypeError = from.MakeTypeError; | 
| 25   MaxSimple = from.MaxSimple; | 26   MaxSimple = from.MaxSimple; | 
| 26   MinSimple = from.MinSimple; | 27   MinSimple = from.MinSimple; | 
| 27   ObjectHasOwnProperty = from.ObjectHasOwnProperty; | 28   ObjectHasOwnProperty = from.ObjectHasOwnProperty; | 
| 28   ObjectKeys = from.ObjectKeys; | 29   ObjectKeys = from.ObjectKeys; | 
| 29 }); | 30 }); | 
| 30 | 31 | 
| 31 // ------------------------------------------------------------------- | 32 // ------------------------------------------------------------------- | 
| 32 | 33 | 
|  | 34 function CreateDataProperty(o, p, v) { | 
|  | 35   var desc = {value: v, enumerable: true, writable: true, configurable: true}; | 
|  | 36   return %reflect_define_property(o, p, desc); | 
|  | 37 } | 
|  | 38 | 
|  | 39 | 
| 33 function InternalizeJSONProperty(holder, name, reviver) { | 40 function InternalizeJSONProperty(holder, name, reviver) { | 
| 34   var val = holder[name]; | 41   var val = holder[name]; | 
| 35   if (IS_OBJECT(val) && val !== null) { | 42   if (IS_SPEC_OBJECT(val)) { | 
| 36     if (IS_ARRAY(val)) { | 43     if (%is_arraylike(val)) { | 
| 37       var length = val.length; | 44       var length = TO_LENGTH(val.length); | 
| 38       for (var i = 0; i < length; i++) { | 45       for (var i = 0; i < length; i++) { | 
| 39         var newElement = | 46         var newElement = | 
| 40             InternalizeJSONProperty(val, %_NumberToString(i), reviver); | 47             InternalizeJSONProperty(val, %_NumberToString(i), reviver); | 
| 41         if (IS_UNDEFINED(newElement)) { | 48         if (IS_UNDEFINED(newElement)) { | 
| 42           delete val[i]; | 49           %reflect_delete_property(val, i); | 
| 43         } else { | 50         } else { | 
| 44           val[i] = newElement; | 51           CreateDataProperty(val, i, newElement); | 
| 45         } | 52         } | 
| 46       } | 53       } | 
| 47     } else { | 54     } else { | 
| 48       for (var p of ObjectKeys(val)) { | 55       for (var p of ObjectKeys(val)) { | 
| 49         var newElement = InternalizeJSONProperty(val, p, reviver); | 56         var newElement = InternalizeJSONProperty(val, p, reviver); | 
| 50         if (IS_UNDEFINED(newElement)) { | 57         if (IS_UNDEFINED(newElement)) { | 
| 51           delete val[p]; | 58           %reflect_delete_property(val, p); | 
| 52         } else { | 59         } else { | 
| 53           val[p] = newElement; | 60           CreateDataProperty(val, p, newElement); | 
| 54         } | 61         } | 
| 55       } | 62       } | 
| 56     } | 63     } | 
| 57   } | 64   } | 
| 58   return %_Call(reviver, holder, name, val); | 65   return %_Call(reviver, holder, name, val); | 
| 59 } | 66 } | 
| 60 | 67 | 
| 61 | 68 | 
| 62 function JSONParse(text, reviver) { | 69 function JSONParse(text, reviver) { | 
| 63   var unfiltered = %ParseJson(text); | 70   var unfiltered = %ParseJson(text); | 
| 64   if (IS_CALLABLE(reviver)) { | 71   if (IS_CALLABLE(reviver)) { | 
| 65     return InternalizeJSONProperty({'': unfiltered}, '', reviver); | 72     return InternalizeJSONProperty({'': unfiltered}, '', reviver); | 
| 66   } else { | 73   } else { | 
| 67     return unfiltered; | 74     return unfiltered; | 
| 68   } | 75   } | 
| 69 } | 76 } | 
| 70 | 77 | 
| 71 | 78 | 
| 72 function SerializeArray(value, replacer, stack, indent, gap) { | 79 function SerializeArray(value, replacer, stack, indent, gap) { | 
| 73   if (!%PushIfAbsent(stack, value)) throw MakeTypeError(kCircularStructure); | 80   if (!%PushIfAbsent(stack, value)) throw MakeTypeError(kCircularStructure); | 
| 74   var stepback = indent; | 81   var stepback = indent; | 
| 75   indent += gap; | 82   indent += gap; | 
| 76   var partial = new InternalArray(); | 83   var partial = new InternalArray(); | 
| 77   var len = value.length; | 84   var len = TO_LENGTH(value.length); | 
| 78   for (var i = 0; i < len; i++) { | 85   for (var i = 0; i < len; i++) { | 
| 79     var strP = JSONSerialize(%_NumberToString(i), value, replacer, stack, | 86     var strP = JSONSerialize(%_NumberToString(i), value, replacer, stack, | 
| 80                              indent, gap); | 87                              indent, gap); | 
| 81     if (IS_UNDEFINED(strP)) { | 88     if (IS_UNDEFINED(strP)) { | 
| 82       strP = "null"; | 89       strP = "null"; | 
| 83     } | 90     } | 
| 84     partial.push(strP); | 91     partial.push(strP); | 
| 85   } | 92   } | 
| 86   var final; | 93   var final; | 
| 87   if (gap == "") { | 94   if (gap == "") { | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 99 | 106 | 
| 100 | 107 | 
| 101 function SerializeObject(value, replacer, stack, indent, gap) { | 108 function SerializeObject(value, replacer, stack, indent, gap) { | 
| 102   if (!%PushIfAbsent(stack, value)) throw MakeTypeError(kCircularStructure); | 109   if (!%PushIfAbsent(stack, value)) throw MakeTypeError(kCircularStructure); | 
| 103   var stepback = indent; | 110   var stepback = indent; | 
| 104   indent += gap; | 111   indent += gap; | 
| 105   var partial = new InternalArray(); | 112   var partial = new InternalArray(); | 
| 106   if (IS_ARRAY(replacer)) { | 113   if (IS_ARRAY(replacer)) { | 
| 107     var length = replacer.length; | 114     var length = replacer.length; | 
| 108     for (var i = 0; i < length; i++) { | 115     for (var i = 0; i < length; i++) { | 
| 109       if (HAS_OWN_PROPERTY(replacer, i)) { | 116       var p = replacer[i]; | 
| 110         var p = replacer[i]; | 117       var strP = JSONSerialize(p, value, replacer, stack, indent, gap); | 
| 111         var strP = JSONSerialize(p, value, replacer, stack, indent, gap); | 118       if (!IS_UNDEFINED(strP)) { | 
| 112         if (!IS_UNDEFINED(strP)) { | 119         var member = %QuoteJSONString(p) + ":"; | 
| 113           var member = %QuoteJSONString(p) + ":"; | 120         if (gap != "") member += " "; | 
| 114           if (gap != "") member += " "; | 121         member += strP; | 
| 115           member += strP; | 122         partial.push(member); | 
| 116           partial.push(member); |  | 
| 117         } |  | 
| 118       } | 123       } | 
| 119     } | 124     } | 
| 120   } else { | 125   } else { | 
| 121     for (var p in value) { | 126     for (var p of ObjectKeys(value)) { | 
| 122       if (HAS_OWN_PROPERTY(value, p)) { | 127       var strP = JSONSerialize(p, value, replacer, stack, indent, gap); | 
| 123         var strP = JSONSerialize(p, value, replacer, stack, indent, gap); | 128       if (!IS_UNDEFINED(strP)) { | 
| 124         if (!IS_UNDEFINED(strP)) { | 129         var member = %QuoteJSONString(p) + ":"; | 
| 125           var member = %QuoteJSONString(p) + ":"; | 130         if (gap != "") member += " "; | 
| 126           if (gap != "") member += " "; | 131         member += strP; | 
| 127           member += strP; | 132         partial.push(member); | 
| 128           partial.push(member); |  | 
| 129         } |  | 
| 130       } | 133       } | 
| 131     } | 134     } | 
| 132   } | 135   } | 
| 133   var final; | 136   var final; | 
| 134   if (gap == "") { | 137   if (gap == "") { | 
| 135     final = "{" + partial.join(",") + "}"; | 138     final = "{" + partial.join(",") + "}"; | 
| 136   } else if (partial.length > 0) { | 139   } else if (partial.length > 0) { | 
| 137     var separator = ",\n" + indent; | 140     var separator = ",\n" + indent; | 
| 138     final = "{\n" + indent + partial.join(separator) + "\n" + | 141     final = "{\n" + indent + partial.join(separator) + "\n" + | 
| 139         stepback + "}"; | 142         stepback + "}"; | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
| 159   if (IS_STRING(value)) { | 162   if (IS_STRING(value)) { | 
| 160     return %QuoteJSONString(value); | 163     return %QuoteJSONString(value); | 
| 161   } else if (IS_NUMBER(value)) { | 164   } else if (IS_NUMBER(value)) { | 
| 162     return JSON_NUMBER_TO_STRING(value); | 165     return JSON_NUMBER_TO_STRING(value); | 
| 163   } else if (IS_BOOLEAN(value)) { | 166   } else if (IS_BOOLEAN(value)) { | 
| 164     return value ? "true" : "false"; | 167     return value ? "true" : "false"; | 
| 165   } else if (IS_NULL(value)) { | 168   } else if (IS_NULL(value)) { | 
| 166     return "null"; | 169     return "null"; | 
| 167   } else if (IS_SPEC_OBJECT(value) && !IS_CALLABLE(value)) { | 170   } else if (IS_SPEC_OBJECT(value) && !IS_CALLABLE(value)) { | 
| 168     // Non-callable object. If it's a primitive wrapper, it must be unwrapped. | 171     // Non-callable object. If it's a primitive wrapper, it must be unwrapped. | 
| 169     if (IS_ARRAY(value)) { | 172     if (%is_arraylike(value)) { | 
| 170       return SerializeArray(value, replacer, stack, indent, gap); | 173       return SerializeArray(value, replacer, stack, indent, gap); | 
| 171     } else if (IS_NUMBER_WRAPPER(value)) { | 174     } else if (IS_NUMBER_WRAPPER(value)) { | 
| 172       value = TO_NUMBER(value); | 175       value = TO_NUMBER(value); | 
| 173       return JSON_NUMBER_TO_STRING(value); | 176       return JSON_NUMBER_TO_STRING(value); | 
| 174     } else if (IS_STRING_WRAPPER(value)) { | 177     } else if (IS_STRING_WRAPPER(value)) { | 
| 175       return %QuoteJSONString(TO_STRING(value)); | 178       return %QuoteJSONString(TO_STRING(value)); | 
| 176     } else if (IS_BOOLEAN_WRAPPER(value)) { | 179     } else if (IS_BOOLEAN_WRAPPER(value)) { | 
| 177       return %_ValueOf(value) ? "true" : "false"; | 180       return %_ValueOf(value) ? "true" : "false"; | 
| 178     } else { | 181     } else { | 
| 179       return SerializeObject(value, replacer, stack, indent, gap); | 182       return SerializeObject(value, replacer, stack, indent, gap); | 
| 180     } | 183     } | 
| 181   } | 184   } | 
| 182   // Undefined or a callable object. | 185   // Undefined or a callable object. | 
| 183   return UNDEFINED; | 186   return UNDEFINED; | 
| 184 } | 187 } | 
| 185 | 188 | 
| 186 | 189 | 
| 187 function JSONStringify(value, replacer, space) { | 190 function JSONStringify(value, replacer, space) { | 
| 188   if (%_ArgumentsLength() == 1) { | 191   if (%_ArgumentsLength() == 1 && !%_IsJSProxy(value)) { | 
| 189     return %BasicJSONStringify(value); | 192     return %BasicJSONStringify(value); | 
| 190   } | 193   } | 
| 191   if (IS_ARRAY(replacer)) { | 194   if (!IS_CALLABLE(replacer) && %is_arraylike(replacer)) { | 
| 192     // Deduplicate replacer array items. |  | 
| 193     var property_list = new InternalArray(); | 195     var property_list = new InternalArray(); | 
| 194     var seen_properties = { __proto__: null }; | 196     var seen_properties = new GlobalSet(); | 
| 195     var length = replacer.length; | 197     var length = TO_LENGTH(replacer.length); | 
| 196     for (var i = 0; i < length; i++) { | 198     for (var i = 0; i < length; i++) { | 
| 197       var v = replacer[i]; | 199       var v = replacer[i]; | 
| 198       var item; | 200       var item; | 
| 199       if (IS_STRING(v)) { | 201       if (IS_STRING(v)) { | 
| 200         item = v; | 202         item = v; | 
| 201       } else if (IS_NUMBER(v)) { | 203       } else if (IS_NUMBER(v)) { | 
| 202         item = %_NumberToString(v); | 204         item = %_NumberToString(v); | 
| 203       } else if (IS_STRING_WRAPPER(v) || IS_NUMBER_WRAPPER(v)) { | 205       } else if (IS_STRING_WRAPPER(v) || IS_NUMBER_WRAPPER(v)) { | 
| 204         item = TO_STRING(v); | 206         item = TO_STRING(v); | 
| 205       } else { | 207       } else { | 
| 206         continue; | 208         continue; | 
| 207       } | 209       } | 
| 208       if (!seen_properties[item]) { | 210       if (!seen_properties.has(item)) { | 
| 209         property_list.push(item); | 211         property_list.push(item); | 
| 210         seen_properties[item] = true; | 212         seen_properties.add(item); | 
| 211       } | 213       } | 
| 212     } | 214     } | 
| 213     replacer = property_list; | 215     replacer = property_list; | 
| 214   } | 216   } | 
| 215   if (IS_OBJECT(space)) { | 217   if (IS_OBJECT(space)) { | 
| 216     // Unwrap 'space' if it is wrapped | 218     // Unwrap 'space' if it is wrapped | 
| 217     if (IS_NUMBER_WRAPPER(space)) { | 219     if (IS_NUMBER_WRAPPER(space)) { | 
| 218       space = TO_NUMBER(space); | 220       space = TO_NUMBER(space); | 
| 219     } else if (IS_STRING_WRAPPER(space)) { | 221     } else if (IS_STRING_WRAPPER(space)) { | 
| 220       space = TO_STRING(space); | 222       space = TO_STRING(space); | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 252 function JsonSerializeAdapter(key, object) { | 254 function JsonSerializeAdapter(key, object) { | 
| 253   var holder = {}; | 255   var holder = {}; | 
| 254   holder[key] = object; | 256   holder[key] = object; | 
| 255   // No need to pass the actual holder since there is no replacer function. | 257   // No need to pass the actual holder since there is no replacer function. | 
| 256   return JSONSerialize(key, holder, UNDEFINED, new InternalArray(), "", ""); | 258   return JSONSerialize(key, holder, UNDEFINED, new InternalArray(), "", ""); | 
| 257 } | 259 } | 
| 258 | 260 | 
| 259 %InstallToContext(["json_serialize_adapter", JsonSerializeAdapter]); | 261 %InstallToContext(["json_serialize_adapter", JsonSerializeAdapter]); | 
| 260 | 262 | 
| 261 }) | 263 }) | 
| OLD | NEW | 
|---|