Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Side by Side Diff: src/json-stringifier.cc

Issue 2008293002: Revert of [json] support replacer function in BasicJsonStringifier. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@jsonproplist
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/json-stringifier.h ('k') | src/runtime/runtime.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 JsonStringifier::JsonEscapeTable = 18 const char* const BasicJsonStringifier::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
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 JsonStringifier::JsonStringifier(Isolate* isolate) 84 BasicJsonStringifier::BasicJsonStringifier(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> JsonStringifier::Stringify(Handle<Object> object, 90 MaybeHandle<Object> BasicJsonStringifier::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 JsonStringifier::InitializeReplacer(Handle<Object> replacer) { 111 bool BasicJsonStringifier::InitializeReplacer(Handle<Object> replacer) {
112 DCHECK(property_list_.is_null()); 112 DCHECK(property_list_.is_null());
113 DCHECK(replacer_function_.is_null());
114 Maybe<bool> is_array = Object::IsArray(replacer); 113 Maybe<bool> is_array = Object::IsArray(replacer);
115 if (is_array.IsNothing()) return false; 114 if (is_array.IsNothing()) return false;
116 if (is_array.FromJust()) { 115 if (is_array.FromJust()) {
117 HandleScope handle_scope(isolate_); 116 HandleScope handle_scope(isolate_);
118 List<Handle<String> > list; 117 List<Handle<String> > list;
119 Handle<Object> length_obj; 118 Handle<Object> length_obj;
120 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 119 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
121 isolate_, length_obj, 120 isolate_, length_obj,
122 Object::GetLengthFromArrayLike(isolate_, replacer), false); 121 Object::GetLengthFromArrayLike(isolate_, replacer), false);
123 uint32_t length; 122 uint32_t length;
(...skipping 14 matching lines...) Expand all
138 } 137 }
139 } 138 }
140 if (key.is_null()) continue; 139 if (key.is_null()) continue;
141 if (!IsInList(key, &list)) list.Add(key); 140 if (!IsInList(key, &list)) list.Add(key);
142 } 141 }
143 property_list_ = factory()->NewUninitializedFixedArray(list.length()); 142 property_list_ = factory()->NewUninitializedFixedArray(list.length());
144 for (int i = 0; i < list.length(); i++) { 143 for (int i = 0; i < list.length(); i++) {
145 property_list_->set(i, *list[i]); 144 property_list_->set(i, *list[i]);
146 } 145 }
147 property_list_ = handle_scope.CloseAndEscape(property_list_); 146 property_list_ = handle_scope.CloseAndEscape(property_list_);
148 } else if (replacer->IsCallable()) {
149 replacer_function_ = Handle<JSReceiver>::cast(replacer);
150 } 147 }
151 return true; 148 return true;
152 } 149 }
153 150
154 bool JsonStringifier::InitializeGap(Handle<Object> gap) { 151 bool BasicJsonStringifier::InitializeGap(Handle<Object> gap) {
155 DCHECK_NULL(gap_); 152 DCHECK_NULL(gap_);
156 HandleScope scope(isolate_); 153 HandleScope scope(isolate_);
157 if (gap->IsJSValue()) { 154 if (gap->IsJSValue()) {
158 Handle<Object> value(Handle<JSValue>::cast(gap)->value(), isolate_); 155 Handle<Object> value(Handle<JSValue>::cast(gap)->value(), isolate_);
159 if (value->IsString()) { 156 if (value->IsString()) {
160 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap, 157 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap,
161 Object::ToString(isolate_, gap), false); 158 Object::ToString(isolate_, gap), false);
162 } else if (value->IsNumber()) { 159 } else if (value->IsNumber()) {
163 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap, Object::ToNumber(gap), 160 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap, Object::ToNumber(gap),
164 false); 161 false);
(...skipping 19 matching lines...) Expand all
184 if (num_value > 0) { 181 if (num_value > 0) {
185 int gap_length = std::min(num_value, 10); 182 int gap_length = std::min(num_value, 10);
186 gap_ = NewArray<uc16>(gap_length + 1); 183 gap_ = NewArray<uc16>(gap_length + 1);
187 for (int i = 0; i < gap_length; i++) gap_[i] = ' '; 184 for (int i = 0; i < gap_length; i++) gap_[i] = ' ';
188 gap_[gap_length] = '\0'; 185 gap_[gap_length] = '\0';
189 } 186 }
190 } 187 }
191 return true; 188 return true;
192 } 189 }
193 190
194 MaybeHandle<Object> JsonStringifier::ApplyToJsonFunction(Handle<Object> object, 191 MaybeHandle<Object> BasicJsonStringifier::StringifyString(
195 Handle<Object> key) { 192 Isolate* isolate, Handle<String> object) {
196 HandleScope scope(isolate_); 193 static const int kJsonQuoteWorstCaseBlowup = 6;
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) {
197 LookupIterator it(object, tojson_string_, 234 LookupIterator it(object, tojson_string_,
198 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); 235 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
199 Handle<Object> fun; 236 Handle<Object> fun;
200 ASSIGN_RETURN_ON_EXCEPTION(isolate_, fun, Object::GetProperty(&it), Object); 237 ASSIGN_RETURN_ON_EXCEPTION(isolate_, fun, Object::GetProperty(&it), Object);
201 if (!fun->IsCallable()) return object; 238 if (!fun->IsCallable()) return object;
202 239
203 // Call toJSON function. 240 // Call toJSON function.
204 if (key->IsSmi()) key = factory()->NumberToString(key); 241 if (key->IsSmi()) key = factory()->NumberToString(key);
205 Handle<Object> argv[] = {key}; 242 Handle<Object> argv[] = {key};
243 HandleScope scope(isolate_);
206 ASSIGN_RETURN_ON_EXCEPTION(isolate_, object, 244 ASSIGN_RETURN_ON_EXCEPTION(isolate_, object,
207 Execution::Call(isolate_, fun, object, 1, argv), 245 Execution::Call(isolate_, fun, object, 1, argv),
208 Object); 246 Object);
209 return scope.CloseAndEscape(object); 247 return scope.CloseAndEscape(object);
210 } 248 }
211 249
212 MaybeHandle<Object> JsonStringifier::ApplyReplacerFunction( 250 BasicJsonStringifier::Result BasicJsonStringifier::StackPush(
213 Handle<Object> object, Handle<Object> key) { 251 Handle<Object> object) {
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) {
239 StackLimitCheck check(isolate_); 252 StackLimitCheck check(isolate_);
240 if (check.HasOverflowed()) { 253 if (check.HasOverflowed()) {
241 isolate_->StackOverflow(); 254 isolate_->StackOverflow();
242 return EXCEPTION; 255 return EXCEPTION;
243 } 256 }
244 257
245 int length = Smi::cast(stack_->length())->value(); 258 int length = Smi::cast(stack_->length())->value();
246 { 259 {
247 DisallowHeapAllocation no_allocation; 260 DisallowHeapAllocation no_allocation;
248 FixedArray* elements = FixedArray::cast(stack_->elements()); 261 FixedArray* elements = FixedArray::cast(stack_->elements());
249 for (int i = 0; i < length; i++) { 262 for (int i = 0; i < length; i++) {
250 if (elements->get(i) == *object) { 263 if (elements->get(i) == *object) {
251 AllowHeapAllocation allow_to_return_error; 264 AllowHeapAllocation allow_to_return_error;
252 Handle<Object> error = 265 Handle<Object> error =
253 factory()->NewTypeError(MessageTemplate::kCircularStructure); 266 factory()->NewTypeError(MessageTemplate::kCircularStructure);
254 isolate_->Throw(*error); 267 isolate_->Throw(*error);
255 return EXCEPTION; 268 return EXCEPTION;
256 } 269 }
257 } 270 }
258 } 271 }
259 JSArray::SetLength(stack_, length + 1); 272 JSArray::SetLength(stack_, length + 1);
260 FixedArray::cast(stack_->elements())->set(length, *object); 273 FixedArray::cast(stack_->elements())->set(length, *object);
261 return SUCCESS; 274 return SUCCESS;
262 } 275 }
263 276
264 void JsonStringifier::StackPop() { 277 void BasicJsonStringifier::StackPop() {
265 int length = Smi::cast(stack_->length())->value(); 278 int length = Smi::cast(stack_->length())->value();
266 stack_->set_length(Smi::FromInt(length - 1)); 279 stack_->set_length(Smi::FromInt(length - 1));
267 } 280 }
268 281
269 template <bool deferred_string_key> 282 template <bool deferred_string_key>
270 JsonStringifier::Result JsonStringifier::Serialize_(Handle<Object> object, 283 BasicJsonStringifier::Result BasicJsonStringifier::Serialize_(
271 bool comma, 284 Handle<Object> object, bool comma, Handle<Object> key) {
272 Handle<Object> key) {
273 if (object->IsJSReceiver()) { 285 if (object->IsJSReceiver()) {
274 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 286 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
275 isolate_, object, ApplyToJsonFunction(object, key), EXCEPTION); 287 isolate_, object, ApplyToJsonFunction(object, key), EXCEPTION);
276 } 288 }
277 if (!replacer_function_.is_null()) {
278 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
279 isolate_, object, ApplyReplacerFunction(object, key), EXCEPTION);
280 }
281 289
282 if (object->IsSmi()) { 290 if (object->IsSmi()) {
283 if (deferred_string_key) SerializeDeferredKey(comma, key); 291 if (deferred_string_key) SerializeDeferredKey(comma, key);
284 return SerializeSmi(Smi::cast(*object)); 292 return SerializeSmi(Smi::cast(*object));
285 } 293 }
286 294
287 switch (HeapObject::cast(*object)->map()->instance_type()) { 295 switch (HeapObject::cast(*object)->map()->instance_type()) {
288 case HEAP_NUMBER_TYPE: 296 case HEAP_NUMBER_TYPE:
289 case MUTABLE_HEAP_NUMBER_TYPE: 297 case MUTABLE_HEAP_NUMBER_TYPE:
290 if (deferred_string_key) SerializeDeferredKey(comma, key); 298 if (deferred_string_key) SerializeDeferredKey(comma, key);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 return SerializeJSProxy(Handle<JSProxy>::cast(object)); 337 return SerializeJSProxy(Handle<JSProxy>::cast(object));
330 } 338 }
331 return SerializeJSObject(Handle<JSObject>::cast(object)); 339 return SerializeJSObject(Handle<JSObject>::cast(object));
332 } 340 }
333 } 341 }
334 342
335 UNREACHABLE(); 343 UNREACHABLE();
336 return UNCHANGED; 344 return UNCHANGED;
337 } 345 }
338 346
339 JsonStringifier::Result JsonStringifier::SerializeJSValue( 347 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSValue(
340 Handle<JSValue> object) { 348 Handle<JSValue> object) {
341 String* class_name = object->class_name(); 349 String* class_name = object->class_name();
342 if (class_name == isolate_->heap()->String_string()) { 350 if (class_name == isolate_->heap()->String_string()) {
343 Handle<Object> value; 351 Handle<Object> value;
344 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 352 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
345 isolate_, value, Object::ToString(isolate_, object), EXCEPTION); 353 isolate_, value, Object::ToString(isolate_, object), EXCEPTION);
346 SerializeString(Handle<String>::cast(value)); 354 SerializeString(Handle<String>::cast(value));
347 } else if (class_name == isolate_->heap()->Number_string()) { 355 } else if (class_name == isolate_->heap()->Number_string()) {
348 Handle<Object> value; 356 Handle<Object> value;
349 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, value, Object::ToNumber(object), 357 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, value, Object::ToNumber(object),
350 EXCEPTION); 358 EXCEPTION);
351 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value)); 359 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value));
352 SerializeHeapNumber(Handle<HeapNumber>::cast(value)); 360 SerializeHeapNumber(Handle<HeapNumber>::cast(value));
353 } else if (class_name == isolate_->heap()->Boolean_string()) { 361 } else if (class_name == isolate_->heap()->Boolean_string()) {
354 Object* value = JSValue::cast(*object)->value(); 362 Object* value = JSValue::cast(*object)->value();
355 DCHECK(value->IsBoolean()); 363 DCHECK(value->IsBoolean());
356 builder_.AppendCString(value->IsTrue() ? "true" : "false"); 364 builder_.AppendCString(value->IsTrue() ? "true" : "false");
357 } else { 365 } else {
358 // ES6 24.3.2.1 step 10.c, serialize as an ordinary JSObject. 366 // ES6 24.3.2.1 step 10.c, serialize as an ordinary JSObject.
359 return SerializeJSObject(object); 367 return SerializeJSObject(object);
360 } 368 }
361 return SUCCESS; 369 return SUCCESS;
362 } 370 }
363 371
364 JsonStringifier::Result JsonStringifier::SerializeSmi(Smi* object) { 372 BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) {
365 static const int kBufferSize = 100; 373 static const int kBufferSize = 100;
366 char chars[kBufferSize]; 374 char chars[kBufferSize];
367 Vector<char> buffer(chars, kBufferSize); 375 Vector<char> buffer(chars, kBufferSize);
368 builder_.AppendCString(IntToCString(object->value(), buffer)); 376 builder_.AppendCString(IntToCString(object->value(), buffer));
369 return SUCCESS; 377 return SUCCESS;
370 } 378 }
371 379
372 JsonStringifier::Result JsonStringifier::SerializeDouble(double number) { 380 BasicJsonStringifier::Result BasicJsonStringifier::SerializeDouble(
381 double number) {
373 if (std::isinf(number) || std::isnan(number)) { 382 if (std::isinf(number) || std::isnan(number)) {
374 builder_.AppendCString("null"); 383 builder_.AppendCString("null");
375 return SUCCESS; 384 return SUCCESS;
376 } 385 }
377 static const int kBufferSize = 100; 386 static const int kBufferSize = 100;
378 char chars[kBufferSize]; 387 char chars[kBufferSize];
379 Vector<char> buffer(chars, kBufferSize); 388 Vector<char> buffer(chars, kBufferSize);
380 builder_.AppendCString(DoubleToCString(number, buffer)); 389 builder_.AppendCString(DoubleToCString(number, buffer));
381 return SUCCESS; 390 return SUCCESS;
382 } 391 }
383 392
384 JsonStringifier::Result JsonStringifier::SerializeJSArray( 393 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray(
385 Handle<JSArray> object) { 394 Handle<JSArray> object) {
386 HandleScope handle_scope(isolate_); 395 HandleScope handle_scope(isolate_);
387 Result stack_push = StackPush(object); 396 Result stack_push = StackPush(object);
388 if (stack_push != SUCCESS) return stack_push; 397 if (stack_push != SUCCESS) return stack_push;
389 uint32_t length = 0; 398 uint32_t length = 0;
390 CHECK(object->length()->ToArrayLength(&length)); 399 CHECK(object->length()->ToArrayLength(&length));
391 DCHECK(!object->IsAccessCheckNeeded()); 400 DCHECK(!object->IsAccessCheckNeeded());
392 builder_.AppendCharacter('['); 401 builder_.AppendCharacter('[');
393 Indent(); 402 Indent();
394 uint32_t i = 0; 403 switch (object->GetElementsKind()) {
395 if (replacer_function_.is_null()) { 404 case FAST_SMI_ELEMENTS: {
396 switch (object->GetElementsKind()) { 405 Handle<FixedArray> elements(FixedArray::cast(object->elements()),
397 case FAST_SMI_ELEMENTS: { 406 isolate_);
398 Handle<FixedArray> elements(FixedArray::cast(object->elements()), 407 for (uint32_t i = 0; i < length; i++) {
399 isolate_); 408 Separator(i == 0);
400 while (i < length) { 409 SerializeSmi(Smi::cast(elements->get(i)));
401 Separator(i == 0); 410 }
402 SerializeSmi(Smi::cast(elements->get(i))); 411 break;
403 i++; 412 }
413 case FAST_DOUBLE_ELEMENTS: {
414 // Empty array is FixedArray but not FixedDoubleArray.
415 if (length == 0) break;
416 Handle<FixedDoubleArray> elements(
417 FixedDoubleArray::cast(object->elements()), isolate_);
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;
404 } 432 }
405 break; 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 }
406 } 445 }
407 case FAST_DOUBLE_ELEMENTS: { 446 break;
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;
446 } 447 }
447 } 448 // The FAST_HOLEY_* cases could be handled in a faster way. They resemble
448 if (i < length) { 449 // the non-holey cases except that a lookup is necessary for holes.
449 // Slow path for non-fast elements and fall-back in edge case. 450 default: {
450 Result result = SerializeArrayLikeSlow(object, i, length); 451 Result result = SerializeArrayLikeSlow(object, 0, length);
451 if (result != SUCCESS) return result; 452 if (result != SUCCESS) return result;
453 break;
454 }
452 } 455 }
453 Unindent(); 456 Unindent();
454 if (length > 0) NewLine(); 457 if (length > 0) NewLine();
455 builder_.AppendCharacter(']'); 458 builder_.AppendCharacter(']');
456 StackPop(); 459 StackPop();
457 return SUCCESS; 460 return SUCCESS;
458 } 461 }
459 462
460 JsonStringifier::Result JsonStringifier::SerializeArrayLikeSlow( 463 BasicJsonStringifier::Result BasicJsonStringifier::SerializeArrayLikeSlow(
461 Handle<JSReceiver> object, uint32_t start, uint32_t length) { 464 Handle<JSReceiver> object, uint32_t start, uint32_t length) {
462 for (uint32_t i = start; i < length; i++) { 465 for (uint32_t i = start; i < length; i++) {
463 Separator(i == 0); 466 Separator(i == 0);
464 Handle<Object> element; 467 Handle<Object> element;
465 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 468 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
466 isolate_, element, JSReceiver::GetElement(isolate_, object, i), 469 isolate_, element, JSReceiver::GetElement(isolate_, object, i),
467 EXCEPTION); 470 EXCEPTION);
468 Result result = SerializeElement(isolate_, element, i); 471 if (element->IsUndefined()) {
469 if (result == SUCCESS) continue;
470 if (result == UNCHANGED) {
471 builder_.AppendCString("null"); 472 builder_.AppendCString("null");
472 } else { 473 } else {
473 return result; 474 Result result = SerializeElement(isolate_, element, i);
475 if (result == SUCCESS) continue;
476 if (result == UNCHANGED) {
477 builder_.AppendCString("null");
478 } else {
479 return result;
480 }
474 } 481 }
475 } 482 }
476 return SUCCESS; 483 return SUCCESS;
477 } 484 }
478 485
479 JsonStringifier::Result JsonStringifier::SerializeJSObject( 486 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject(
480 Handle<JSObject> object) { 487 Handle<JSObject> object) {
481 HandleScope handle_scope(isolate_); 488 HandleScope handle_scope(isolate_);
482 Result stack_push = StackPush(object); 489 Result stack_push = StackPush(object);
483 if (stack_push != SUCCESS) return stack_push; 490 if (stack_push != SUCCESS) return stack_push;
484 491
485 if (property_list_.is_null() && 492 if (property_list_.is_null() &&
486 object->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER && 493 object->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER &&
487 object->HasFastProperties() && 494 object->HasFastProperties() &&
488 Handle<JSObject>::cast(object)->elements()->length() == 0) { 495 Handle<JSObject>::cast(object)->elements()->length() == 0) {
489 DCHECK(object->IsJSObject()); 496 DCHECK(object->IsJSObject());
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 if (comma) NewLine(); 531 if (comma) NewLine();
525 builder_.AppendCharacter('}'); 532 builder_.AppendCharacter('}');
526 } else { 533 } else {
527 Result result = SerializeJSReceiverSlow(object); 534 Result result = SerializeJSReceiverSlow(object);
528 if (result != SUCCESS) return result; 535 if (result != SUCCESS) return result;
529 } 536 }
530 StackPop(); 537 StackPop();
531 return SUCCESS; 538 return SUCCESS;
532 } 539 }
533 540
534 JsonStringifier::Result JsonStringifier::SerializeJSReceiverSlow( 541 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSReceiverSlow(
535 Handle<JSReceiver> object) { 542 Handle<JSReceiver> object) {
536 Handle<FixedArray> contents = property_list_; 543 Handle<FixedArray> contents = property_list_;
537 if (contents.is_null()) { 544 if (contents.is_null()) {
538 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 545 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
539 isolate_, contents, 546 isolate_, contents,
540 JSReceiver::GetKeys(object, OWN_ONLY, ENUMERABLE_STRINGS), EXCEPTION); 547 JSReceiver::GetKeys(object, OWN_ONLY, ENUMERABLE_STRINGS), EXCEPTION);
541 } 548 }
542 549
543 builder_.AppendCharacter('{'); 550 builder_.AppendCharacter('{');
544 Indent(); 551 Indent();
(...skipping 21 matching lines...) Expand all
566 Result result = SerializeProperty(property, comma, key_handle); 573 Result result = SerializeProperty(property, comma, key_handle);
567 if (!comma && result == SUCCESS) comma = true; 574 if (!comma && result == SUCCESS) comma = true;
568 if (result == EXCEPTION) return result; 575 if (result == EXCEPTION) return result;
569 } 576 }
570 Unindent(); 577 Unindent();
571 if (comma) NewLine(); 578 if (comma) NewLine();
572 builder_.AppendCharacter('}'); 579 builder_.AppendCharacter('}');
573 return SUCCESS; 580 return SUCCESS;
574 } 581 }
575 582
576 JsonStringifier::Result JsonStringifier::SerializeJSProxy( 583 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSProxy(
577 Handle<JSProxy> object) { 584 Handle<JSProxy> object) {
578 Result stack_push = StackPush(object); 585 Result stack_push = StackPush(object);
579 if (stack_push != SUCCESS) return stack_push; 586 if (stack_push != SUCCESS) return stack_push;
580 Maybe<bool> is_array = Object::IsArray(object); 587 Maybe<bool> is_array = Object::IsArray(object);
581 if (is_array.IsNothing()) return EXCEPTION; 588 if (is_array.IsNothing()) return EXCEPTION;
582 if (is_array.FromJust()) { 589 if (is_array.FromJust()) {
583 Handle<Object> length_object; 590 Handle<Object> length_object;
584 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 591 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
585 isolate_, length_object, 592 isolate_, length_object,
586 Object::GetLengthFromArrayLike(isolate_, object), EXCEPTION); 593 Object::GetLengthFromArrayLike(isolate_, object), EXCEPTION);
(...skipping 14 matching lines...) Expand all
601 builder_.AppendCharacter(']'); 608 builder_.AppendCharacter(']');
602 } else { 609 } else {
603 Result result = SerializeJSReceiverSlow(object); 610 Result result = SerializeJSReceiverSlow(object);
604 if (result != SUCCESS) return result; 611 if (result != SUCCESS) return result;
605 } 612 }
606 StackPop(); 613 StackPop();
607 return SUCCESS; 614 return SUCCESS;
608 } 615 }
609 616
610 template <typename SrcChar, typename DestChar> 617 template <typename SrcChar, typename DestChar>
611 void JsonStringifier::SerializeStringUnchecked_( 618 void BasicJsonStringifier::SerializeStringUnchecked_(
612 Vector<const SrcChar> src, 619 Vector<const SrcChar> src,
613 IncrementalStringBuilder::NoExtend<DestChar>* dest) { 620 IncrementalStringBuilder::NoExtend<DestChar>* dest) {
614 // Assert that uc16 character is not truncated down to 8 bit. 621 // Assert that uc16 character is not truncated down to 8 bit.
615 // The <uc16, char> version of this method must not be called. 622 // The <uc16, char> version of this method must not be called.
616 DCHECK(sizeof(DestChar) >= sizeof(SrcChar)); 623 DCHECK(sizeof(DestChar) >= sizeof(SrcChar));
617 624
618 for (int i = 0; i < src.length(); i++) { 625 for (int i = 0; i < src.length(); i++) {
619 SrcChar c = src[i]; 626 SrcChar c = src[i];
620 if (DoNotEscape(c)) { 627 if (DoNotEscape(c)) {
621 dest->Append(c); 628 dest->Append(c);
622 } else { 629 } else {
623 dest->AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]); 630 dest->AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
624 } 631 }
625 } 632 }
626 } 633 }
627 634
628 template <typename SrcChar, typename DestChar> 635 template <typename SrcChar, typename DestChar>
629 void JsonStringifier::SerializeString_(Handle<String> string) { 636 void BasicJsonStringifier::SerializeString_(Handle<String> string) {
630 int length = string->length(); 637 int length = string->length();
631 builder_.Append<uint8_t, DestChar>('"'); 638 builder_.Append<uint8_t, DestChar>('"');
632 // We make a rough estimate to find out if the current string can be 639 // We make a rough estimate to find out if the current string can be
633 // serialized without allocating a new string part. The worst case length of 640 // serialized without allocating a new string part. The worst case length of
634 // an escaped character is 6. Shifting the remainin string length right by 3 641 // an escaped character is 6. Shifting the remainin string length right by 3
635 // is a more pessimistic estimate, but faster to calculate. 642 // is a more pessimistic estimate, but faster to calculate.
636 int worst_case_length = length << 3; 643 int worst_case_length = length << 3;
637 if (builder_.CurrentPartCanFit(worst_case_length)) { 644 if (builder_.CurrentPartCanFit(worst_case_length)) {
638 DisallowHeapAllocation no_gc; 645 DisallowHeapAllocation no_gc;
639 Vector<const SrcChar> vector = string->GetCharVector<SrcChar>(); 646 Vector<const SrcChar> vector = string->GetCharVector<SrcChar>();
640 IncrementalStringBuilder::NoExtendBuilder<DestChar> no_extend( 647 IncrementalStringBuilder::NoExtendBuilder<DestChar> no_extend(
641 &builder_, worst_case_length); 648 &builder_, worst_case_length);
642 SerializeStringUnchecked_(vector, &no_extend); 649 SerializeStringUnchecked_(vector, &no_extend);
643 } else { 650 } else {
644 FlatStringReader reader(isolate_, string); 651 FlatStringReader reader(isolate_, string);
645 for (int i = 0; i < reader.length(); i++) { 652 for (int i = 0; i < reader.length(); i++) {
646 SrcChar c = reader.Get<SrcChar>(i); 653 SrcChar c = reader.Get<SrcChar>(i);
647 if (DoNotEscape(c)) { 654 if (DoNotEscape(c)) {
648 builder_.Append<SrcChar, DestChar>(c); 655 builder_.Append<SrcChar, DestChar>(c);
649 } else { 656 } else {
650 builder_.AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]); 657 builder_.AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
651 } 658 }
652 } 659 }
653 } 660 }
654 661
655 builder_.Append<uint8_t, DestChar>('"'); 662 builder_.Append<uint8_t, DestChar>('"');
656 } 663 }
657 664
658 template <> 665 template <>
659 bool JsonStringifier::DoNotEscape(uint8_t c) { 666 bool BasicJsonStringifier::DoNotEscape(uint8_t c) {
660 return c >= '#' && c <= '~' && c != '\\'; 667 return c >= '#' && c <= '~' && c != '\\';
661 } 668 }
662 669
663 template <> 670 template <>
664 bool JsonStringifier::DoNotEscape(uint16_t c) { 671 bool BasicJsonStringifier::DoNotEscape(uint16_t c) {
665 return c >= '#' && c != '\\' && c != 0x7f; 672 return c >= '#' && c != '\\' && c != 0x7f;
666 } 673 }
667 674
668 void JsonStringifier::NewLine() { 675 void BasicJsonStringifier::NewLine() {
669 if (gap_ == nullptr) return; 676 if (gap_ == nullptr) return;
670 builder_.AppendCharacter('\n'); 677 builder_.AppendCharacter('\n');
671 for (int i = 0; i < indent_; i++) builder_.AppendCString(gap_); 678 for (int i = 0; i < indent_; i++) builder_.AppendCString(gap_);
672 } 679 }
673 680
674 void JsonStringifier::Separator(bool first) { 681 void BasicJsonStringifier::Separator(bool first) {
675 if (!first) builder_.AppendCharacter(','); 682 if (!first) builder_.AppendCharacter(',');
676 NewLine(); 683 NewLine();
677 } 684 }
678 685
679 void JsonStringifier::SerializeDeferredKey(bool deferred_comma, 686 void BasicJsonStringifier::SerializeDeferredKey(bool deferred_comma,
680 Handle<Object> deferred_key) { 687 Handle<Object> deferred_key) {
681 Separator(!deferred_comma); 688 Separator(!deferred_comma);
682 SerializeString(Handle<String>::cast(deferred_key)); 689 SerializeString(Handle<String>::cast(deferred_key));
683 builder_.AppendCharacter(':'); 690 builder_.AppendCharacter(':');
684 if (gap_ != nullptr) builder_.AppendCharacter(' '); 691 if (gap_ != nullptr) builder_.AppendCharacter(' ');
685 } 692 }
686 693
687 void JsonStringifier::SerializeString(Handle<String> object) { 694 void BasicJsonStringifier::SerializeString(Handle<String> object) {
688 object = String::Flatten(object); 695 object = String::Flatten(object);
689 if (builder_.CurrentEncoding() == String::ONE_BYTE_ENCODING) { 696 if (builder_.CurrentEncoding() == String::ONE_BYTE_ENCODING) {
690 if (object->IsOneByteRepresentationUnderneath()) { 697 if (object->IsOneByteRepresentationUnderneath()) {
691 SerializeString_<uint8_t, uint8_t>(object); 698 SerializeString_<uint8_t, uint8_t>(object);
692 } else { 699 } else {
693 builder_.ChangeEncoding(); 700 builder_.ChangeEncoding();
694 SerializeString(object); 701 SerializeString(object);
695 } 702 }
696 } else { 703 } else {
697 if (object->IsOneByteRepresentationUnderneath()) { 704 if (object->IsOneByteRepresentationUnderneath()) {
698 SerializeString_<uint8_t, uc16>(object); 705 SerializeString_<uint8_t, uc16>(object);
699 } else { 706 } else {
700 SerializeString_<uc16, uc16>(object); 707 SerializeString_<uc16, uc16>(object);
701 } 708 }
702 } 709 }
703 } 710 }
704 711
705 } // namespace internal 712 } // namespace internal
706 } // namespace v8 713 } // namespace v8
OLDNEW
« no previous file with comments | « src/json-stringifier.h ('k') | src/runtime/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698