OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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 #include "src/json-stringifier.h" | 5 #include "src/json-stringifier.h" |
6 | 6 |
7 #include "src/conversions.h" | 7 #include "src/conversions.h" |
8 #include "src/lookup.h" | 8 #include "src/lookup.h" |
9 #include "src/messages.h" | 9 #include "src/messages.h" |
10 #include "src/objects-inl.h" | 10 #include "src/objects-inl.h" |
11 #include "src/utils.h" | 11 #include "src/utils.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 | 15 |
16 // Translation table to escape Latin1 characters. | 16 // Translation table to escape Latin1 characters. |
17 // Table entries start at a multiple of 8 and are null-terminated. | 17 // Table entries start at a multiple of 8 and are null-terminated. |
18 const char* const BasicJsonStringifier::JsonEscapeTable = | 18 const char* const JsonStringifier::JsonEscapeTable = |
19 "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 " | 19 "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 " |
20 "\\u0004\0 \\u0005\0 \\u0006\0 \\u0007\0 " | 20 "\\u0004\0 \\u0005\0 \\u0006\0 \\u0007\0 " |
21 "\\b\0 \\t\0 \\n\0 \\u000b\0 " | 21 "\\b\0 \\t\0 \\n\0 \\u000b\0 " |
22 "\\f\0 \\r\0 \\u000e\0 \\u000f\0 " | 22 "\\f\0 \\r\0 \\u000e\0 \\u000f\0 " |
23 "\\u0010\0 \\u0011\0 \\u0012\0 \\u0013\0 " | 23 "\\u0010\0 \\u0011\0 \\u0012\0 \\u0013\0 " |
24 "\\u0014\0 \\u0015\0 \\u0016\0 \\u0017\0 " | 24 "\\u0014\0 \\u0015\0 \\u0016\0 \\u0017\0 " |
25 "\\u0018\0 \\u0019\0 \\u001a\0 \\u001b\0 " | 25 "\\u0018\0 \\u0019\0 \\u001a\0 \\u001b\0 " |
26 "\\u001c\0 \\u001d\0 \\u001e\0 \\u001f\0 " | 26 "\\u001c\0 \\u001d\0 \\u001e\0 \\u001f\0 " |
27 " \0 !\0 \\\"\0 #\0 " | 27 " \0 !\0 \\\"\0 #\0 " |
28 "$\0 %\0 &\0 '\0 " | 28 "$\0 %\0 &\0 '\0 " |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 "\334\0 \335\0 \336\0 \337\0 " | 74 "\334\0 \335\0 \336\0 \337\0 " |
75 "\340\0 \341\0 \342\0 \343\0 " | 75 "\340\0 \341\0 \342\0 \343\0 " |
76 "\344\0 \345\0 \346\0 \347\0 " | 76 "\344\0 \345\0 \346\0 \347\0 " |
77 "\350\0 \351\0 \352\0 \353\0 " | 77 "\350\0 \351\0 \352\0 \353\0 " |
78 "\354\0 \355\0 \356\0 \357\0 " | 78 "\354\0 \355\0 \356\0 \357\0 " |
79 "\360\0 \361\0 \362\0 \363\0 " | 79 "\360\0 \361\0 \362\0 \363\0 " |
80 "\364\0 \365\0 \366\0 \367\0 " | 80 "\364\0 \365\0 \366\0 \367\0 " |
81 "\370\0 \371\0 \372\0 \373\0 " | 81 "\370\0 \371\0 \372\0 \373\0 " |
82 "\374\0 \375\0 \376\0 \377\0 "; | 82 "\374\0 \375\0 \376\0 \377\0 "; |
83 | 83 |
84 BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate) | 84 JsonStringifier::JsonStringifier(Isolate* isolate) |
85 : isolate_(isolate), builder_(isolate), gap_(nullptr), indent_(0) { | 85 : isolate_(isolate), builder_(isolate), gap_(nullptr), indent_(0) { |
86 tojson_string_ = factory()->toJSON_string(); | 86 tojson_string_ = factory()->toJSON_string(); |
87 stack_ = factory()->NewJSArray(8); | 87 stack_ = factory()->NewJSArray(8); |
88 } | 88 } |
89 | 89 |
90 MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object, | 90 MaybeHandle<Object> JsonStringifier::Stringify(Handle<Object> object, |
91 Handle<Object> replacer, | 91 Handle<Object> replacer, |
92 Handle<Object> gap) { | 92 Handle<Object> gap) { |
93 if (!InitializeReplacer(replacer)) return MaybeHandle<Object>(); | 93 if (!InitializeReplacer(replacer)) return MaybeHandle<Object>(); |
94 if (!gap->IsUndefined() && !InitializeGap(gap)) return MaybeHandle<Object>(); | 94 if (!gap->IsUndefined() && !InitializeGap(gap)) return MaybeHandle<Object>(); |
95 Result result = SerializeObject(object); | 95 Result result = SerializeObject(object); |
96 if (result == UNCHANGED) return factory()->undefined_value(); | 96 if (result == UNCHANGED) return factory()->undefined_value(); |
97 if (result == SUCCESS) return builder_.Finish(); | 97 if (result == SUCCESS) return builder_.Finish(); |
98 DCHECK(result == EXCEPTION); | 98 DCHECK(result == EXCEPTION); |
99 return MaybeHandle<Object>(); | 99 return MaybeHandle<Object>(); |
100 } | 100 } |
101 | 101 |
102 bool IsInList(Handle<String> key, List<Handle<String> >* list) { | 102 bool IsInList(Handle<String> key, List<Handle<String> >* list) { |
103 // TODO(yangguo): This is O(n^2) for n properties in the list. Deal with this | 103 // TODO(yangguo): This is O(n^2) for n properties in the list. Deal with this |
104 // if this becomes an issue. | 104 // if this becomes an issue. |
105 for (const Handle<String>& existing : *list) { | 105 for (const Handle<String>& existing : *list) { |
106 if (String::Equals(existing, key)) return true; | 106 if (String::Equals(existing, key)) return true; |
107 } | 107 } |
108 return false; | 108 return false; |
109 } | 109 } |
110 | 110 |
111 bool BasicJsonStringifier::InitializeReplacer(Handle<Object> replacer) { | 111 bool JsonStringifier::InitializeReplacer(Handle<Object> replacer) { |
112 DCHECK(property_list_.is_null()); | 112 DCHECK(property_list_.is_null()); |
| 113 DCHECK(replacer_function_.is_null()); |
113 Maybe<bool> is_array = Object::IsArray(replacer); | 114 Maybe<bool> is_array = Object::IsArray(replacer); |
114 if (is_array.IsNothing()) return false; | 115 if (is_array.IsNothing()) return false; |
115 if (is_array.FromJust()) { | 116 if (is_array.FromJust()) { |
116 HandleScope handle_scope(isolate_); | 117 HandleScope handle_scope(isolate_); |
117 List<Handle<String> > list; | 118 List<Handle<String> > list; |
118 Handle<Object> length_obj; | 119 Handle<Object> length_obj; |
119 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 120 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
120 isolate_, length_obj, | 121 isolate_, length_obj, |
121 Object::GetLengthFromArrayLike(isolate_, replacer), false); | 122 Object::GetLengthFromArrayLike(isolate_, replacer), false); |
122 uint32_t length; | 123 uint32_t length; |
(...skipping 14 matching lines...) Expand all Loading... |
137 } | 138 } |
138 } | 139 } |
139 if (key.is_null()) continue; | 140 if (key.is_null()) continue; |
140 if (!IsInList(key, &list)) list.Add(key); | 141 if (!IsInList(key, &list)) list.Add(key); |
141 } | 142 } |
142 property_list_ = factory()->NewUninitializedFixedArray(list.length()); | 143 property_list_ = factory()->NewUninitializedFixedArray(list.length()); |
143 for (int i = 0; i < list.length(); i++) { | 144 for (int i = 0; i < list.length(); i++) { |
144 property_list_->set(i, *list[i]); | 145 property_list_->set(i, *list[i]); |
145 } | 146 } |
146 property_list_ = handle_scope.CloseAndEscape(property_list_); | 147 property_list_ = handle_scope.CloseAndEscape(property_list_); |
| 148 } else if (replacer->IsCallable()) { |
| 149 replacer_function_ = Handle<JSReceiver>::cast(replacer); |
147 } | 150 } |
148 return true; | 151 return true; |
149 } | 152 } |
150 | 153 |
151 bool BasicJsonStringifier::InitializeGap(Handle<Object> gap) { | 154 bool JsonStringifier::InitializeGap(Handle<Object> gap) { |
152 DCHECK_NULL(gap_); | 155 DCHECK_NULL(gap_); |
153 HandleScope scope(isolate_); | 156 HandleScope scope(isolate_); |
154 if (gap->IsJSValue()) { | 157 if (gap->IsJSValue()) { |
155 Handle<Object> value(Handle<JSValue>::cast(gap)->value(), isolate_); | 158 Handle<Object> value(Handle<JSValue>::cast(gap)->value(), isolate_); |
156 if (value->IsString()) { | 159 if (value->IsString()) { |
157 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap, | 160 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap, |
158 Object::ToString(isolate_, gap), false); | 161 Object::ToString(isolate_, gap), false); |
159 } else if (value->IsNumber()) { | 162 } else if (value->IsNumber()) { |
160 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap, Object::ToNumber(gap), | 163 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap, Object::ToNumber(gap), |
161 false); | 164 false); |
(...skipping 19 matching lines...) Expand all Loading... |
181 if (num_value > 0) { | 184 if (num_value > 0) { |
182 int gap_length = std::min(num_value, 10); | 185 int gap_length = std::min(num_value, 10); |
183 gap_ = NewArray<uc16>(gap_length + 1); | 186 gap_ = NewArray<uc16>(gap_length + 1); |
184 for (int i = 0; i < gap_length; i++) gap_[i] = ' '; | 187 for (int i = 0; i < gap_length; i++) gap_[i] = ' '; |
185 gap_[gap_length] = '\0'; | 188 gap_[gap_length] = '\0'; |
186 } | 189 } |
187 } | 190 } |
188 return true; | 191 return true; |
189 } | 192 } |
190 | 193 |
191 MaybeHandle<Object> BasicJsonStringifier::StringifyString( | 194 MaybeHandle<Object> JsonStringifier::ApplyToJsonFunction(Handle<Object> object, |
192 Isolate* isolate, Handle<String> object) { | 195 Handle<Object> key) { |
193 static const int kJsonQuoteWorstCaseBlowup = 6; | 196 HandleScope scope(isolate_); |
194 static const int kSpaceForQuotes = 2; | |
195 int worst_case_length = | |
196 object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; | |
197 | |
198 if (worst_case_length > 32 * KB) { // Slow path if too large. | |
199 BasicJsonStringifier stringifier(isolate); | |
200 Handle<Object> undefined = isolate->factory()->undefined_value(); | |
201 return stringifier.Stringify(object, undefined, undefined); | |
202 } | |
203 | |
204 object = String::Flatten(object); | |
205 DCHECK(object->IsFlat()); | |
206 Handle<SeqString> result; | |
207 if (object->IsOneByteRepresentationUnderneath()) { | |
208 result = isolate->factory() | |
209 ->NewRawOneByteString(worst_case_length) | |
210 .ToHandleChecked(); | |
211 IncrementalStringBuilder::NoExtendString<uint8_t> no_extend( | |
212 result, worst_case_length); | |
213 no_extend.Append('\"'); | |
214 SerializeStringUnchecked_(object->GetFlatContent().ToOneByteVector(), | |
215 &no_extend); | |
216 no_extend.Append('\"'); | |
217 return no_extend.Finalize(); | |
218 } else { | |
219 result = isolate->factory() | |
220 ->NewRawTwoByteString(worst_case_length) | |
221 .ToHandleChecked(); | |
222 IncrementalStringBuilder::NoExtendString<uc16> no_extend(result, | |
223 worst_case_length); | |
224 no_extend.Append('\"'); | |
225 SerializeStringUnchecked_(object->GetFlatContent().ToUC16Vector(), | |
226 &no_extend); | |
227 no_extend.Append('\"'); | |
228 return no_extend.Finalize(); | |
229 } | |
230 } | |
231 | |
232 MaybeHandle<Object> BasicJsonStringifier::ApplyToJsonFunction( | |
233 Handle<Object> object, Handle<Object> key) { | |
234 LookupIterator it(object, tojson_string_, | 197 LookupIterator it(object, tojson_string_, |
235 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); | 198 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); |
236 Handle<Object> fun; | 199 Handle<Object> fun; |
237 ASSIGN_RETURN_ON_EXCEPTION(isolate_, fun, Object::GetProperty(&it), Object); | 200 ASSIGN_RETURN_ON_EXCEPTION(isolate_, fun, Object::GetProperty(&it), Object); |
238 if (!fun->IsCallable()) return object; | 201 if (!fun->IsCallable()) return object; |
239 | 202 |
240 // Call toJSON function. | 203 // Call toJSON function. |
241 if (key->IsSmi()) key = factory()->NumberToString(key); | 204 if (key->IsSmi()) key = factory()->NumberToString(key); |
242 Handle<Object> argv[] = {key}; | 205 Handle<Object> argv[] = {key}; |
243 HandleScope scope(isolate_); | |
244 ASSIGN_RETURN_ON_EXCEPTION(isolate_, object, | 206 ASSIGN_RETURN_ON_EXCEPTION(isolate_, object, |
245 Execution::Call(isolate_, fun, object, 1, argv), | 207 Execution::Call(isolate_, fun, object, 1, argv), |
246 Object); | 208 Object); |
247 return scope.CloseAndEscape(object); | 209 return scope.CloseAndEscape(object); |
248 } | 210 } |
249 | 211 |
250 BasicJsonStringifier::Result BasicJsonStringifier::StackPush( | 212 MaybeHandle<Object> JsonStringifier::ApplyReplacerFunction( |
251 Handle<Object> object) { | 213 Handle<Object> object, Handle<Object> key) { |
| 214 HandleScope scope(isolate_); |
| 215 if (key->IsSmi()) key = factory()->NumberToString(key); |
| 216 Handle<Object> argv[] = {key, object}; |
| 217 Handle<JSReceiver> holder = CurrentHolder(object); |
| 218 ASSIGN_RETURN_ON_EXCEPTION( |
| 219 isolate_, object, |
| 220 Execution::Call(isolate_, replacer_function_, holder, 2, argv), Object); |
| 221 return scope.CloseAndEscape(object); |
| 222 } |
| 223 |
| 224 Handle<JSReceiver> JsonStringifier::CurrentHolder(Handle<Object> value) { |
| 225 int length = Smi::cast(stack_->length())->value(); |
| 226 if (length == 0) { |
| 227 Handle<JSObject> holder = |
| 228 factory()->NewJSObject(isolate_->object_function()); |
| 229 JSObject::AddProperty(holder, factory()->empty_string(), value, NONE); |
| 230 return holder; |
| 231 } else { |
| 232 FixedArray* elements = FixedArray::cast(stack_->elements()); |
| 233 return Handle<JSReceiver>(JSReceiver::cast(elements->get(length - 1)), |
| 234 isolate_); |
| 235 } |
| 236 } |
| 237 |
| 238 JsonStringifier::Result JsonStringifier::StackPush(Handle<Object> object) { |
252 StackLimitCheck check(isolate_); | 239 StackLimitCheck check(isolate_); |
253 if (check.HasOverflowed()) { | 240 if (check.HasOverflowed()) { |
254 isolate_->StackOverflow(); | 241 isolate_->StackOverflow(); |
255 return EXCEPTION; | 242 return EXCEPTION; |
256 } | 243 } |
257 | 244 |
258 int length = Smi::cast(stack_->length())->value(); | 245 int length = Smi::cast(stack_->length())->value(); |
259 { | 246 { |
260 DisallowHeapAllocation no_allocation; | 247 DisallowHeapAllocation no_allocation; |
261 FixedArray* elements = FixedArray::cast(stack_->elements()); | 248 FixedArray* elements = FixedArray::cast(stack_->elements()); |
262 for (int i = 0; i < length; i++) { | 249 for (int i = 0; i < length; i++) { |
263 if (elements->get(i) == *object) { | 250 if (elements->get(i) == *object) { |
264 AllowHeapAllocation allow_to_return_error; | 251 AllowHeapAllocation allow_to_return_error; |
265 Handle<Object> error = | 252 Handle<Object> error = |
266 factory()->NewTypeError(MessageTemplate::kCircularStructure); | 253 factory()->NewTypeError(MessageTemplate::kCircularStructure); |
267 isolate_->Throw(*error); | 254 isolate_->Throw(*error); |
268 return EXCEPTION; | 255 return EXCEPTION; |
269 } | 256 } |
270 } | 257 } |
271 } | 258 } |
272 JSArray::SetLength(stack_, length + 1); | 259 JSArray::SetLength(stack_, length + 1); |
273 FixedArray::cast(stack_->elements())->set(length, *object); | 260 FixedArray::cast(stack_->elements())->set(length, *object); |
274 return SUCCESS; | 261 return SUCCESS; |
275 } | 262 } |
276 | 263 |
277 void BasicJsonStringifier::StackPop() { | 264 void JsonStringifier::StackPop() { |
278 int length = Smi::cast(stack_->length())->value(); | 265 int length = Smi::cast(stack_->length())->value(); |
279 stack_->set_length(Smi::FromInt(length - 1)); | 266 stack_->set_length(Smi::FromInt(length - 1)); |
280 } | 267 } |
281 | 268 |
282 template <bool deferred_string_key> | 269 template <bool deferred_string_key> |
283 BasicJsonStringifier::Result BasicJsonStringifier::Serialize_( | 270 JsonStringifier::Result JsonStringifier::Serialize_(Handle<Object> object, |
284 Handle<Object> object, bool comma, Handle<Object> key) { | 271 bool comma, |
| 272 Handle<Object> key) { |
285 if (object->IsJSReceiver()) { | 273 if (object->IsJSReceiver()) { |
286 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 274 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
287 isolate_, object, ApplyToJsonFunction(object, key), EXCEPTION); | 275 isolate_, object, ApplyToJsonFunction(object, key), EXCEPTION); |
288 } | 276 } |
| 277 if (!replacer_function_.is_null()) { |
| 278 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 279 isolate_, object, ApplyReplacerFunction(object, key), EXCEPTION); |
| 280 } |
289 | 281 |
290 if (object->IsSmi()) { | 282 if (object->IsSmi()) { |
291 if (deferred_string_key) SerializeDeferredKey(comma, key); | 283 if (deferred_string_key) SerializeDeferredKey(comma, key); |
292 return SerializeSmi(Smi::cast(*object)); | 284 return SerializeSmi(Smi::cast(*object)); |
293 } | 285 } |
294 | 286 |
295 switch (HeapObject::cast(*object)->map()->instance_type()) { | 287 switch (HeapObject::cast(*object)->map()->instance_type()) { |
296 case HEAP_NUMBER_TYPE: | 288 case HEAP_NUMBER_TYPE: |
297 case MUTABLE_HEAP_NUMBER_TYPE: | 289 case MUTABLE_HEAP_NUMBER_TYPE: |
298 if (deferred_string_key) SerializeDeferredKey(comma, key); | 290 if (deferred_string_key) SerializeDeferredKey(comma, key); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 return SerializeJSProxy(Handle<JSProxy>::cast(object)); | 329 return SerializeJSProxy(Handle<JSProxy>::cast(object)); |
338 } | 330 } |
339 return SerializeJSObject(Handle<JSObject>::cast(object)); | 331 return SerializeJSObject(Handle<JSObject>::cast(object)); |
340 } | 332 } |
341 } | 333 } |
342 | 334 |
343 UNREACHABLE(); | 335 UNREACHABLE(); |
344 return UNCHANGED; | 336 return UNCHANGED; |
345 } | 337 } |
346 | 338 |
347 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSValue( | 339 JsonStringifier::Result JsonStringifier::SerializeJSValue( |
348 Handle<JSValue> object) { | 340 Handle<JSValue> object) { |
349 String* class_name = object->class_name(); | 341 String* class_name = object->class_name(); |
350 if (class_name == isolate_->heap()->String_string()) { | 342 if (class_name == isolate_->heap()->String_string()) { |
351 Handle<Object> value; | 343 Handle<Object> value; |
352 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 344 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
353 isolate_, value, Object::ToString(isolate_, object), EXCEPTION); | 345 isolate_, value, Object::ToString(isolate_, object), EXCEPTION); |
354 SerializeString(Handle<String>::cast(value)); | 346 SerializeString(Handle<String>::cast(value)); |
355 } else if (class_name == isolate_->heap()->Number_string()) { | 347 } else if (class_name == isolate_->heap()->Number_string()) { |
356 Handle<Object> value; | 348 Handle<Object> value; |
357 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, value, Object::ToNumber(object), | 349 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, value, Object::ToNumber(object), |
358 EXCEPTION); | 350 EXCEPTION); |
359 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value)); | 351 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value)); |
360 SerializeHeapNumber(Handle<HeapNumber>::cast(value)); | 352 SerializeHeapNumber(Handle<HeapNumber>::cast(value)); |
361 } else if (class_name == isolate_->heap()->Boolean_string()) { | 353 } else if (class_name == isolate_->heap()->Boolean_string()) { |
362 Object* value = JSValue::cast(*object)->value(); | 354 Object* value = JSValue::cast(*object)->value(); |
363 DCHECK(value->IsBoolean()); | 355 DCHECK(value->IsBoolean()); |
364 builder_.AppendCString(value->IsTrue() ? "true" : "false"); | 356 builder_.AppendCString(value->IsTrue() ? "true" : "false"); |
365 } else { | 357 } else { |
366 // ES6 24.3.2.1 step 10.c, serialize as an ordinary JSObject. | 358 // ES6 24.3.2.1 step 10.c, serialize as an ordinary JSObject. |
367 return SerializeJSObject(object); | 359 return SerializeJSObject(object); |
368 } | 360 } |
369 return SUCCESS; | 361 return SUCCESS; |
370 } | 362 } |
371 | 363 |
372 BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) { | 364 JsonStringifier::Result JsonStringifier::SerializeSmi(Smi* object) { |
373 static const int kBufferSize = 100; | 365 static const int kBufferSize = 100; |
374 char chars[kBufferSize]; | 366 char chars[kBufferSize]; |
375 Vector<char> buffer(chars, kBufferSize); | 367 Vector<char> buffer(chars, kBufferSize); |
376 builder_.AppendCString(IntToCString(object->value(), buffer)); | 368 builder_.AppendCString(IntToCString(object->value(), buffer)); |
377 return SUCCESS; | 369 return SUCCESS; |
378 } | 370 } |
379 | 371 |
380 BasicJsonStringifier::Result BasicJsonStringifier::SerializeDouble( | 372 JsonStringifier::Result JsonStringifier::SerializeDouble(double number) { |
381 double number) { | |
382 if (std::isinf(number) || std::isnan(number)) { | 373 if (std::isinf(number) || std::isnan(number)) { |
383 builder_.AppendCString("null"); | 374 builder_.AppendCString("null"); |
384 return SUCCESS; | 375 return SUCCESS; |
385 } | 376 } |
386 static const int kBufferSize = 100; | 377 static const int kBufferSize = 100; |
387 char chars[kBufferSize]; | 378 char chars[kBufferSize]; |
388 Vector<char> buffer(chars, kBufferSize); | 379 Vector<char> buffer(chars, kBufferSize); |
389 builder_.AppendCString(DoubleToCString(number, buffer)); | 380 builder_.AppendCString(DoubleToCString(number, buffer)); |
390 return SUCCESS; | 381 return SUCCESS; |
391 } | 382 } |
392 | 383 |
393 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( | 384 JsonStringifier::Result JsonStringifier::SerializeJSArray( |
394 Handle<JSArray> object) { | 385 Handle<JSArray> object) { |
395 HandleScope handle_scope(isolate_); | 386 HandleScope handle_scope(isolate_); |
396 Result stack_push = StackPush(object); | 387 Result stack_push = StackPush(object); |
397 if (stack_push != SUCCESS) return stack_push; | 388 if (stack_push != SUCCESS) return stack_push; |
398 uint32_t length = 0; | 389 uint32_t length = 0; |
399 CHECK(object->length()->ToArrayLength(&length)); | 390 CHECK(object->length()->ToArrayLength(&length)); |
400 DCHECK(!object->IsAccessCheckNeeded()); | 391 DCHECK(!object->IsAccessCheckNeeded()); |
401 builder_.AppendCharacter('['); | 392 builder_.AppendCharacter('['); |
402 Indent(); | 393 Indent(); |
403 switch (object->GetElementsKind()) { | 394 uint32_t i = 0; |
404 case FAST_SMI_ELEMENTS: { | 395 if (replacer_function_.is_null()) { |
405 Handle<FixedArray> elements(FixedArray::cast(object->elements()), | 396 switch (object->GetElementsKind()) { |
406 isolate_); | 397 case FAST_SMI_ELEMENTS: { |
407 for (uint32_t i = 0; i < length; i++) { | 398 Handle<FixedArray> elements(FixedArray::cast(object->elements()), |
408 Separator(i == 0); | 399 isolate_); |
409 SerializeSmi(Smi::cast(elements->get(i))); | 400 while (i < length) { |
| 401 Separator(i == 0); |
| 402 SerializeSmi(Smi::cast(elements->get(i))); |
| 403 i++; |
| 404 } |
| 405 break; |
410 } | 406 } |
411 break; | 407 case FAST_DOUBLE_ELEMENTS: { |
| 408 // Empty array is FixedArray but not FixedDoubleArray. |
| 409 if (length == 0) break; |
| 410 Handle<FixedDoubleArray> elements( |
| 411 FixedDoubleArray::cast(object->elements()), isolate_); |
| 412 while (i < length) { |
| 413 Separator(i == 0); |
| 414 SerializeDouble(elements->get_scalar(i)); |
| 415 i++; |
| 416 } |
| 417 break; |
| 418 } |
| 419 case FAST_ELEMENTS: { |
| 420 Handle<Object> old_length(object->length(), isolate_); |
| 421 while (i < length) { |
| 422 if (object->length() != *old_length || |
| 423 object->GetElementsKind() != FAST_ELEMENTS) { |
| 424 // Fall back to slow path. |
| 425 break; |
| 426 } |
| 427 Separator(i == 0); |
| 428 Result result = SerializeElement( |
| 429 isolate_, |
| 430 Handle<Object>(FixedArray::cast(object->elements())->get(i), |
| 431 isolate_), |
| 432 i); |
| 433 if (result == UNCHANGED) { |
| 434 builder_.AppendCString("null"); |
| 435 } else if (result != SUCCESS) { |
| 436 return result; |
| 437 } |
| 438 i++; |
| 439 } |
| 440 break; |
| 441 } |
| 442 // The FAST_HOLEY_* cases could be handled in a faster way. They resemble |
| 443 // the non-holey cases except that a lookup is necessary for holes. |
| 444 default: |
| 445 break; |
412 } | 446 } |
413 case FAST_DOUBLE_ELEMENTS: { | 447 } |
414 // Empty array is FixedArray but not FixedDoubleArray. | 448 if (i < length) { |
415 if (length == 0) break; | 449 // Slow path for non-fast elements and fall-back in edge case. |
416 Handle<FixedDoubleArray> elements( | 450 Result result = SerializeArrayLikeSlow(object, i, length); |
417 FixedDoubleArray::cast(object->elements()), isolate_); | 451 if (result != SUCCESS) return result; |
418 for (uint32_t i = 0; i < length; i++) { | |
419 Separator(i == 0); | |
420 SerializeDouble(elements->get_scalar(i)); | |
421 } | |
422 break; | |
423 } | |
424 case FAST_ELEMENTS: { | |
425 Handle<Object> old_length(object->length(), isolate_); | |
426 for (uint32_t i = 0; i < length; i++) { | |
427 if (object->length() != *old_length || | |
428 object->GetElementsKind() != FAST_ELEMENTS) { | |
429 Result result = SerializeArrayLikeSlow(object, i, length); | |
430 if (result != SUCCESS) return result; | |
431 break; | |
432 } | |
433 Separator(i == 0); | |
434 Result result = SerializeElement( | |
435 isolate_, | |
436 Handle<Object>(FixedArray::cast(object->elements())->get(i), | |
437 isolate_), | |
438 i); | |
439 if (result == SUCCESS) continue; | |
440 if (result == UNCHANGED) { | |
441 builder_.AppendCString("null"); | |
442 } else { | |
443 return result; | |
444 } | |
445 } | |
446 break; | |
447 } | |
448 // The FAST_HOLEY_* cases could be handled in a faster way. They resemble | |
449 // the non-holey cases except that a lookup is necessary for holes. | |
450 default: { | |
451 Result result = SerializeArrayLikeSlow(object, 0, length); | |
452 if (result != SUCCESS) return result; | |
453 break; | |
454 } | |
455 } | 452 } |
456 Unindent(); | 453 Unindent(); |
457 if (length > 0) NewLine(); | 454 if (length > 0) NewLine(); |
458 builder_.AppendCharacter(']'); | 455 builder_.AppendCharacter(']'); |
459 StackPop(); | 456 StackPop(); |
460 return SUCCESS; | 457 return SUCCESS; |
461 } | 458 } |
462 | 459 |
463 BasicJsonStringifier::Result BasicJsonStringifier::SerializeArrayLikeSlow( | 460 JsonStringifier::Result JsonStringifier::SerializeArrayLikeSlow( |
464 Handle<JSReceiver> object, uint32_t start, uint32_t length) { | 461 Handle<JSReceiver> object, uint32_t start, uint32_t length) { |
465 for (uint32_t i = start; i < length; i++) { | 462 for (uint32_t i = start; i < length; i++) { |
466 Separator(i == 0); | 463 Separator(i == 0); |
467 Handle<Object> element; | 464 Handle<Object> element; |
468 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 465 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
469 isolate_, element, JSReceiver::GetElement(isolate_, object, i), | 466 isolate_, element, JSReceiver::GetElement(isolate_, object, i), |
470 EXCEPTION); | 467 EXCEPTION); |
471 if (element->IsUndefined()) { | 468 Result result = SerializeElement(isolate_, element, i); |
| 469 if (result == SUCCESS) continue; |
| 470 if (result == UNCHANGED) { |
472 builder_.AppendCString("null"); | 471 builder_.AppendCString("null"); |
473 } else { | 472 } else { |
474 Result result = SerializeElement(isolate_, element, i); | 473 return result; |
475 if (result == SUCCESS) continue; | |
476 if (result == UNCHANGED) { | |
477 builder_.AppendCString("null"); | |
478 } else { | |
479 return result; | |
480 } | |
481 } | 474 } |
482 } | 475 } |
483 return SUCCESS; | 476 return SUCCESS; |
484 } | 477 } |
485 | 478 |
486 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( | 479 JsonStringifier::Result JsonStringifier::SerializeJSObject( |
487 Handle<JSObject> object) { | 480 Handle<JSObject> object) { |
488 HandleScope handle_scope(isolate_); | 481 HandleScope handle_scope(isolate_); |
489 Result stack_push = StackPush(object); | 482 Result stack_push = StackPush(object); |
490 if (stack_push != SUCCESS) return stack_push; | 483 if (stack_push != SUCCESS) return stack_push; |
491 | 484 |
492 if (property_list_.is_null() && | 485 if (property_list_.is_null() && |
493 object->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER && | 486 object->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER && |
494 object->HasFastProperties() && | 487 object->HasFastProperties() && |
495 Handle<JSObject>::cast(object)->elements()->length() == 0) { | 488 Handle<JSObject>::cast(object)->elements()->length() == 0) { |
496 DCHECK(object->IsJSObject()); | 489 DCHECK(object->IsJSObject()); |
497 DCHECK(!object->IsJSGlobalProxy()); | 490 DCHECK(!object->IsJSGlobalProxy()); |
498 Handle<JSObject> js_obj = Handle<JSObject>::cast(object); | 491 Handle<JSObject> js_obj = Handle<JSObject>::cast(object); |
499 DCHECK(!js_obj->HasIndexedInterceptor()); | 492 DCHECK(!js_obj->HasIndexedInterceptor()); |
500 DCHECK(!js_obj->HasNamedInterceptor()); | 493 DCHECK(!js_obj->HasNamedInterceptor()); |
501 Handle<Map> map(js_obj->map()); | 494 Handle<Map> map(js_obj->map()); |
502 builder_.AppendCharacter('{'); | 495 builder_.AppendCharacter('{'); |
503 Indent(); | 496 Indent(); |
504 bool comma = false; | 497 bool comma = false; |
505 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { | 498 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { |
506 Handle<Name> name(map->instance_descriptors()->GetKey(i), isolate_); | 499 Handle<Name> name(map->instance_descriptors()->GetKey(i), isolate_); |
507 // TODO(rossberg): Should this throw? | 500 // TODO(rossberg): Should this throw? |
508 if (!name->IsString()) continue; | 501 if (!name->IsString()) continue; |
509 Handle<String> key = Handle<String>::cast(name); | 502 Handle<String> key = Handle<String>::cast(name); |
510 PropertyDetails details = map->instance_descriptors()->GetDetails(i); | 503 PropertyDetails details = map->instance_descriptors()->GetDetails(i); |
511 if (details.IsDontEnum()) continue; | 504 if (details.IsDontEnum()) continue; |
512 Handle<Object> property; | 505 Handle<Object> property; |
513 if (details.type() == DATA && *map == js_obj->map()) { | 506 if (details.type() == DATA && *map == js_obj->map()) { |
514 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i); | 507 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i); |
515 if (js_obj->IsUnboxedDoubleField(field_index)) { | 508 property = JSObject::FastPropertyAt(js_obj, details.representation(), |
516 double value = js_obj->RawFastDoublePropertyAt(field_index); | 509 field_index); |
517 property = isolate_->factory()->NewHeapNumber(value); | |
518 } else { | |
519 property = handle(js_obj->RawFastPropertyAt(field_index), isolate_); | |
520 } | |
521 } else { | 510 } else { |
522 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 511 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
523 isolate_, property, Object::GetPropertyOrElement(js_obj, key), | 512 isolate_, property, Object::GetPropertyOrElement(js_obj, key), |
524 EXCEPTION); | 513 EXCEPTION); |
525 } | 514 } |
526 Result result = SerializeProperty(property, comma, key); | 515 Result result = SerializeProperty(property, comma, key); |
527 if (!comma && result == SUCCESS) comma = true; | 516 if (!comma && result == SUCCESS) comma = true; |
528 if (result == EXCEPTION) return result; | 517 if (result == EXCEPTION) return result; |
529 } | 518 } |
530 Unindent(); | 519 Unindent(); |
531 if (comma) NewLine(); | 520 if (comma) NewLine(); |
532 builder_.AppendCharacter('}'); | 521 builder_.AppendCharacter('}'); |
533 } else { | 522 } else { |
534 Result result = SerializeJSReceiverSlow(object); | 523 Result result = SerializeJSReceiverSlow(object); |
535 if (result != SUCCESS) return result; | 524 if (result != SUCCESS) return result; |
536 } | 525 } |
537 StackPop(); | 526 StackPop(); |
538 return SUCCESS; | 527 return SUCCESS; |
539 } | 528 } |
540 | 529 |
541 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSReceiverSlow( | 530 JsonStringifier::Result JsonStringifier::SerializeJSReceiverSlow( |
542 Handle<JSReceiver> object) { | 531 Handle<JSReceiver> object) { |
543 Handle<FixedArray> contents = property_list_; | 532 Handle<FixedArray> contents = property_list_; |
544 if (contents.is_null()) { | 533 if (contents.is_null()) { |
545 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 534 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
546 isolate_, contents, | 535 isolate_, contents, |
547 KeyAccumulator::GetKeys(object, OWN_ONLY, ENUMERABLE_STRINGS), | 536 KeyAccumulator::GetKeys(object, OWN_ONLY, ENUMERABLE_STRINGS), |
548 EXCEPTION); | 537 EXCEPTION); |
549 } | 538 } |
550 builder_.AppendCharacter('{'); | 539 builder_.AppendCharacter('{'); |
551 Indent(); | 540 Indent(); |
(...skipping 21 matching lines...) Expand all Loading... |
573 Result result = SerializeProperty(property, comma, key_handle); | 562 Result result = SerializeProperty(property, comma, key_handle); |
574 if (!comma && result == SUCCESS) comma = true; | 563 if (!comma && result == SUCCESS) comma = true; |
575 if (result == EXCEPTION) return result; | 564 if (result == EXCEPTION) return result; |
576 } | 565 } |
577 Unindent(); | 566 Unindent(); |
578 if (comma) NewLine(); | 567 if (comma) NewLine(); |
579 builder_.AppendCharacter('}'); | 568 builder_.AppendCharacter('}'); |
580 return SUCCESS; | 569 return SUCCESS; |
581 } | 570 } |
582 | 571 |
583 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSProxy( | 572 JsonStringifier::Result JsonStringifier::SerializeJSProxy( |
584 Handle<JSProxy> object) { | 573 Handle<JSProxy> object) { |
585 Result stack_push = StackPush(object); | 574 Result stack_push = StackPush(object); |
586 if (stack_push != SUCCESS) return stack_push; | 575 if (stack_push != SUCCESS) return stack_push; |
587 Maybe<bool> is_array = Object::IsArray(object); | 576 Maybe<bool> is_array = Object::IsArray(object); |
588 if (is_array.IsNothing()) return EXCEPTION; | 577 if (is_array.IsNothing()) return EXCEPTION; |
589 if (is_array.FromJust()) { | 578 if (is_array.FromJust()) { |
590 Handle<Object> length_object; | 579 Handle<Object> length_object; |
591 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 580 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
592 isolate_, length_object, | 581 isolate_, length_object, |
593 Object::GetLengthFromArrayLike(isolate_, object), EXCEPTION); | 582 Object::GetLengthFromArrayLike(isolate_, object), EXCEPTION); |
(...skipping 14 matching lines...) Expand all Loading... |
608 builder_.AppendCharacter(']'); | 597 builder_.AppendCharacter(']'); |
609 } else { | 598 } else { |
610 Result result = SerializeJSReceiverSlow(object); | 599 Result result = SerializeJSReceiverSlow(object); |
611 if (result != SUCCESS) return result; | 600 if (result != SUCCESS) return result; |
612 } | 601 } |
613 StackPop(); | 602 StackPop(); |
614 return SUCCESS; | 603 return SUCCESS; |
615 } | 604 } |
616 | 605 |
617 template <typename SrcChar, typename DestChar> | 606 template <typename SrcChar, typename DestChar> |
618 void BasicJsonStringifier::SerializeStringUnchecked_( | 607 void JsonStringifier::SerializeStringUnchecked_( |
619 Vector<const SrcChar> src, | 608 Vector<const SrcChar> src, |
620 IncrementalStringBuilder::NoExtend<DestChar>* dest) { | 609 IncrementalStringBuilder::NoExtend<DestChar>* dest) { |
621 // Assert that uc16 character is not truncated down to 8 bit. | 610 // Assert that uc16 character is not truncated down to 8 bit. |
622 // The <uc16, char> version of this method must not be called. | 611 // The <uc16, char> version of this method must not be called. |
623 DCHECK(sizeof(DestChar) >= sizeof(SrcChar)); | 612 DCHECK(sizeof(DestChar) >= sizeof(SrcChar)); |
624 | 613 |
625 for (int i = 0; i < src.length(); i++) { | 614 for (int i = 0; i < src.length(); i++) { |
626 SrcChar c = src[i]; | 615 SrcChar c = src[i]; |
627 if (DoNotEscape(c)) { | 616 if (DoNotEscape(c)) { |
628 dest->Append(c); | 617 dest->Append(c); |
629 } else { | 618 } else { |
630 dest->AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]); | 619 dest->AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]); |
631 } | 620 } |
632 } | 621 } |
633 } | 622 } |
634 | 623 |
635 template <typename SrcChar, typename DestChar> | 624 template <typename SrcChar, typename DestChar> |
636 void BasicJsonStringifier::SerializeString_(Handle<String> string) { | 625 void JsonStringifier::SerializeString_(Handle<String> string) { |
637 int length = string->length(); | 626 int length = string->length(); |
638 builder_.Append<uint8_t, DestChar>('"'); | 627 builder_.Append<uint8_t, DestChar>('"'); |
639 // We make a rough estimate to find out if the current string can be | 628 // We make a rough estimate to find out if the current string can be |
640 // serialized without allocating a new string part. The worst case length of | 629 // serialized without allocating a new string part. The worst case length of |
641 // an escaped character is 6. Shifting the remainin string length right by 3 | 630 // an escaped character is 6. Shifting the remainin string length right by 3 |
642 // is a more pessimistic estimate, but faster to calculate. | 631 // is a more pessimistic estimate, but faster to calculate. |
643 int worst_case_length = length << 3; | 632 int worst_case_length = length << 3; |
644 if (builder_.CurrentPartCanFit(worst_case_length)) { | 633 if (builder_.CurrentPartCanFit(worst_case_length)) { |
645 DisallowHeapAllocation no_gc; | 634 DisallowHeapAllocation no_gc; |
646 Vector<const SrcChar> vector = string->GetCharVector<SrcChar>(); | 635 Vector<const SrcChar> vector = string->GetCharVector<SrcChar>(); |
647 IncrementalStringBuilder::NoExtendBuilder<DestChar> no_extend( | 636 IncrementalStringBuilder::NoExtendBuilder<DestChar> no_extend( |
648 &builder_, worst_case_length); | 637 &builder_, worst_case_length); |
649 SerializeStringUnchecked_(vector, &no_extend); | 638 SerializeStringUnchecked_(vector, &no_extend); |
650 } else { | 639 } else { |
651 FlatStringReader reader(isolate_, string); | 640 FlatStringReader reader(isolate_, string); |
652 for (int i = 0; i < reader.length(); i++) { | 641 for (int i = 0; i < reader.length(); i++) { |
653 SrcChar c = reader.Get<SrcChar>(i); | 642 SrcChar c = reader.Get<SrcChar>(i); |
654 if (DoNotEscape(c)) { | 643 if (DoNotEscape(c)) { |
655 builder_.Append<SrcChar, DestChar>(c); | 644 builder_.Append<SrcChar, DestChar>(c); |
656 } else { | 645 } else { |
657 builder_.AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]); | 646 builder_.AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]); |
658 } | 647 } |
659 } | 648 } |
660 } | 649 } |
661 | 650 |
662 builder_.Append<uint8_t, DestChar>('"'); | 651 builder_.Append<uint8_t, DestChar>('"'); |
663 } | 652 } |
664 | 653 |
665 template <> | 654 template <> |
666 bool BasicJsonStringifier::DoNotEscape(uint8_t c) { | 655 bool JsonStringifier::DoNotEscape(uint8_t c) { |
667 return c >= '#' && c <= '~' && c != '\\'; | 656 return c >= '#' && c <= '~' && c != '\\'; |
668 } | 657 } |
669 | 658 |
670 template <> | 659 template <> |
671 bool BasicJsonStringifier::DoNotEscape(uint16_t c) { | 660 bool JsonStringifier::DoNotEscape(uint16_t c) { |
672 return c >= '#' && c != '\\' && c != 0x7f; | 661 return c >= '#' && c != '\\' && c != 0x7f; |
673 } | 662 } |
674 | 663 |
675 void BasicJsonStringifier::NewLine() { | 664 void JsonStringifier::NewLine() { |
676 if (gap_ == nullptr) return; | 665 if (gap_ == nullptr) return; |
677 builder_.AppendCharacter('\n'); | 666 builder_.AppendCharacter('\n'); |
678 for (int i = 0; i < indent_; i++) builder_.AppendCString(gap_); | 667 for (int i = 0; i < indent_; i++) builder_.AppendCString(gap_); |
679 } | 668 } |
680 | 669 |
681 void BasicJsonStringifier::Separator(bool first) { | 670 void JsonStringifier::Separator(bool first) { |
682 if (!first) builder_.AppendCharacter(','); | 671 if (!first) builder_.AppendCharacter(','); |
683 NewLine(); | 672 NewLine(); |
684 } | 673 } |
685 | 674 |
686 void BasicJsonStringifier::SerializeDeferredKey(bool deferred_comma, | 675 void JsonStringifier::SerializeDeferredKey(bool deferred_comma, |
687 Handle<Object> deferred_key) { | 676 Handle<Object> deferred_key) { |
688 Separator(!deferred_comma); | 677 Separator(!deferred_comma); |
689 SerializeString(Handle<String>::cast(deferred_key)); | 678 SerializeString(Handle<String>::cast(deferred_key)); |
690 builder_.AppendCharacter(':'); | 679 builder_.AppendCharacter(':'); |
691 if (gap_ != nullptr) builder_.AppendCharacter(' '); | 680 if (gap_ != nullptr) builder_.AppendCharacter(' '); |
692 } | 681 } |
693 | 682 |
694 void BasicJsonStringifier::SerializeString(Handle<String> object) { | 683 void JsonStringifier::SerializeString(Handle<String> object) { |
695 object = String::Flatten(object); | 684 object = String::Flatten(object); |
696 if (builder_.CurrentEncoding() == String::ONE_BYTE_ENCODING) { | 685 if (builder_.CurrentEncoding() == String::ONE_BYTE_ENCODING) { |
697 if (object->IsOneByteRepresentationUnderneath()) { | 686 if (object->IsOneByteRepresentationUnderneath()) { |
698 SerializeString_<uint8_t, uint8_t>(object); | 687 SerializeString_<uint8_t, uint8_t>(object); |
699 } else { | 688 } else { |
700 builder_.ChangeEncoding(); | 689 builder_.ChangeEncoding(); |
701 SerializeString(object); | 690 SerializeString(object); |
702 } | 691 } |
703 } else { | 692 } else { |
704 if (object->IsOneByteRepresentationUnderneath()) { | 693 if (object->IsOneByteRepresentationUnderneath()) { |
705 SerializeString_<uint8_t, uc16>(object); | 694 SerializeString_<uint8_t, uc16>(object); |
706 } else { | 695 } else { |
707 SerializeString_<uc16, uc16>(object); | 696 SerializeString_<uc16, uc16>(object); |
708 } | 697 } |
709 } | 698 } |
710 } | 699 } |
711 | 700 |
712 } // namespace internal | 701 } // namespace internal |
713 } // namespace v8 | 702 } // namespace v8 |
OLD | NEW |