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

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

Issue 2010533002: [json] support replacer function in BasicJsonStringifier. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@jsonproplist
Patch Set: fix Created 4 years, 6 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
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 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
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
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
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)));
Camillo Bruni 2016/05/24 18:24:55 use isolate_ directly here, avoids the massive ;)
234 }
235 }
236
237 JsonStringifier::Result JsonStringifier::StackPush(Handle<Object> object) {
252 StackLimitCheck check(isolate_); 238 StackLimitCheck check(isolate_);
253 if (check.HasOverflowed()) { 239 if (check.HasOverflowed()) {
254 isolate_->StackOverflow(); 240 isolate_->StackOverflow();
255 return EXCEPTION; 241 return EXCEPTION;
256 } 242 }
257 243
258 int length = Smi::cast(stack_->length())->value(); 244 int length = Smi::cast(stack_->length())->value();
259 { 245 {
260 DisallowHeapAllocation no_allocation; 246 DisallowHeapAllocation no_allocation;
261 FixedArray* elements = FixedArray::cast(stack_->elements()); 247 FixedArray* elements = FixedArray::cast(stack_->elements());
262 for (int i = 0; i < length; i++) { 248 for (int i = 0; i < length; i++) {
263 if (elements->get(i) == *object) { 249 if (elements->get(i) == *object) {
264 AllowHeapAllocation allow_to_return_error; 250 AllowHeapAllocation allow_to_return_error;
265 Handle<Object> error = 251 Handle<Object> error =
266 factory()->NewTypeError(MessageTemplate::kCircularStructure); 252 factory()->NewTypeError(MessageTemplate::kCircularStructure);
267 isolate_->Throw(*error); 253 isolate_->Throw(*error);
268 return EXCEPTION; 254 return EXCEPTION;
269 } 255 }
270 } 256 }
271 } 257 }
272 JSArray::SetLength(stack_, length + 1); 258 JSArray::SetLength(stack_, length + 1);
273 FixedArray::cast(stack_->elements())->set(length, *object); 259 FixedArray::cast(stack_->elements())->set(length, *object);
274 return SUCCESS; 260 return SUCCESS;
275 } 261 }
276 262
277 void BasicJsonStringifier::StackPop() { 263 void JsonStringifier::StackPop() {
278 int length = Smi::cast(stack_->length())->value(); 264 int length = Smi::cast(stack_->length())->value();
279 stack_->set_length(Smi::FromInt(length - 1)); 265 stack_->set_length(Smi::FromInt(length - 1));
280 } 266 }
281 267
282 template <bool deferred_string_key> 268 template <bool deferred_string_key>
283 BasicJsonStringifier::Result BasicJsonStringifier::Serialize_( 269 JsonStringifier::Result JsonStringifier::Serialize_(Handle<Object> object,
284 Handle<Object> object, bool comma, Handle<Object> key) { 270 bool comma,
271 Handle<Object> key) {
285 if (object->IsJSReceiver()) { 272 if (object->IsJSReceiver()) {
286 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 273 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
287 isolate_, object, ApplyToJsonFunction(object, key), EXCEPTION); 274 isolate_, object, ApplyToJsonFunction(object, key), EXCEPTION);
288 } 275 }
276 if (!replacer_function_.is_null()) {
277 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
278 isolate_, object, ApplyReplacerFunction(object, key), EXCEPTION);
279 }
289 280
290 if (object->IsSmi()) { 281 if (object->IsSmi()) {
291 if (deferred_string_key) SerializeDeferredKey(comma, key); 282 if (deferred_string_key) SerializeDeferredKey(comma, key);
292 return SerializeSmi(Smi::cast(*object)); 283 return SerializeSmi(Smi::cast(*object));
293 } 284 }
294 285
295 switch (HeapObject::cast(*object)->map()->instance_type()) { 286 switch (HeapObject::cast(*object)->map()->instance_type()) {
296 case HEAP_NUMBER_TYPE: 287 case HEAP_NUMBER_TYPE:
297 case MUTABLE_HEAP_NUMBER_TYPE: 288 case MUTABLE_HEAP_NUMBER_TYPE:
298 if (deferred_string_key) SerializeDeferredKey(comma, key); 289 if (deferred_string_key) SerializeDeferredKey(comma, key);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 return SerializeJSProxy(Handle<JSProxy>::cast(object)); 328 return SerializeJSProxy(Handle<JSProxy>::cast(object));
338 } 329 }
339 return SerializeJSObject(Handle<JSObject>::cast(object)); 330 return SerializeJSObject(Handle<JSObject>::cast(object));
340 } 331 }
341 } 332 }
342 333
343 UNREACHABLE(); 334 UNREACHABLE();
344 return UNCHANGED; 335 return UNCHANGED;
345 } 336 }
346 337
347 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSValue( 338 JsonStringifier::Result JsonStringifier::SerializeJSValue(
348 Handle<JSValue> object) { 339 Handle<JSValue> object) {
349 String* class_name = object->class_name(); 340 String* class_name = object->class_name();
350 if (class_name == isolate_->heap()->String_string()) { 341 if (class_name == isolate_->heap()->String_string()) {
351 Handle<Object> value; 342 Handle<Object> value;
352 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 343 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
353 isolate_, value, Object::ToString(isolate_, object), EXCEPTION); 344 isolate_, value, Object::ToString(isolate_, object), EXCEPTION);
354 SerializeString(Handle<String>::cast(value)); 345 SerializeString(Handle<String>::cast(value));
355 } else if (class_name == isolate_->heap()->Number_string()) { 346 } else if (class_name == isolate_->heap()->Number_string()) {
356 Handle<Object> value; 347 Handle<Object> value;
357 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, value, Object::ToNumber(object), 348 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, value, Object::ToNumber(object),
358 EXCEPTION); 349 EXCEPTION);
359 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value)); 350 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value));
360 SerializeHeapNumber(Handle<HeapNumber>::cast(value)); 351 SerializeHeapNumber(Handle<HeapNumber>::cast(value));
361 } else if (class_name == isolate_->heap()->Boolean_string()) { 352 } else if (class_name == isolate_->heap()->Boolean_string()) {
362 Object* value = JSValue::cast(*object)->value(); 353 Object* value = JSValue::cast(*object)->value();
363 DCHECK(value->IsBoolean()); 354 DCHECK(value->IsBoolean());
364 builder_.AppendCString(value->IsTrue() ? "true" : "false"); 355 builder_.AppendCString(value->IsTrue() ? "true" : "false");
365 } else { 356 } else {
366 // ES6 24.3.2.1 step 10.c, serialize as an ordinary JSObject. 357 // ES6 24.3.2.1 step 10.c, serialize as an ordinary JSObject.
367 return SerializeJSObject(object); 358 return SerializeJSObject(object);
368 } 359 }
369 return SUCCESS; 360 return SUCCESS;
370 } 361 }
371 362
372 BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) { 363 JsonStringifier::Result JsonStringifier::SerializeSmi(Smi* object) {
373 static const int kBufferSize = 100; 364 static const int kBufferSize = 100;
374 char chars[kBufferSize]; 365 char chars[kBufferSize];
375 Vector<char> buffer(chars, kBufferSize); 366 Vector<char> buffer(chars, kBufferSize);
376 builder_.AppendCString(IntToCString(object->value(), buffer)); 367 builder_.AppendCString(IntToCString(object->value(), buffer));
377 return SUCCESS; 368 return SUCCESS;
378 } 369 }
379 370
380 BasicJsonStringifier::Result BasicJsonStringifier::SerializeDouble( 371 JsonStringifier::Result JsonStringifier::SerializeDouble(double number) {
381 double number) {
382 if (std::isinf(number) || std::isnan(number)) { 372 if (std::isinf(number) || std::isnan(number)) {
383 builder_.AppendCString("null"); 373 builder_.AppendCString("null");
384 return SUCCESS; 374 return SUCCESS;
385 } 375 }
386 static const int kBufferSize = 100; 376 static const int kBufferSize = 100;
387 char chars[kBufferSize]; 377 char chars[kBufferSize];
388 Vector<char> buffer(chars, kBufferSize); 378 Vector<char> buffer(chars, kBufferSize);
389 builder_.AppendCString(DoubleToCString(number, buffer)); 379 builder_.AppendCString(DoubleToCString(number, buffer));
390 return SUCCESS; 380 return SUCCESS;
391 } 381 }
392 382
393 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( 383 JsonStringifier::Result JsonStringifier::SerializeJSArray(
394 Handle<JSArray> object) { 384 Handle<JSArray> object) {
395 HandleScope handle_scope(isolate_); 385 HandleScope handle_scope(isolate_);
396 Result stack_push = StackPush(object); 386 Result stack_push = StackPush(object);
397 if (stack_push != SUCCESS) return stack_push; 387 if (stack_push != SUCCESS) return stack_push;
398 uint32_t length = 0; 388 uint32_t length = 0;
399 CHECK(object->length()->ToArrayLength(&length)); 389 CHECK(object->length()->ToArrayLength(&length));
400 DCHECK(!object->IsAccessCheckNeeded()); 390 DCHECK(!object->IsAccessCheckNeeded());
401 builder_.AppendCharacter('['); 391 builder_.AppendCharacter('[');
402 Indent(); 392 Indent();
403 switch (object->GetElementsKind()) { 393 uint32_t i = 0;
404 case FAST_SMI_ELEMENTS: { 394 if (replacer_function_.is_null()) {
405 Handle<FixedArray> elements(FixedArray::cast(object->elements()), 395 switch (object->GetElementsKind()) {
406 isolate_); 396 case FAST_SMI_ELEMENTS: {
407 for (uint32_t i = 0; i < length; i++) { 397 Handle<FixedArray> elements(FixedArray::cast(object->elements()),
408 Separator(i == 0); 398 isolate_);
409 SerializeSmi(Smi::cast(elements->get(i))); 399 while (i < length) {
400 Separator(i == 0);
401 SerializeSmi(Smi::cast(elements->get(i)));
402 i++;
403 }
404 break;
410 } 405 }
411 break; 406 case FAST_DOUBLE_ELEMENTS: {
407 // Empty array is FixedArray but not FixedDoubleArray.
408 if (length == 0) break;
409 Handle<FixedDoubleArray> elements(
410 FixedDoubleArray::cast(object->elements()), isolate_);
411 while (i < length) {
412 Separator(i == 0);
413 SerializeDouble(elements->get_scalar(i));
414 i++;
415 }
416 break;
417 }
418 case FAST_ELEMENTS: {
419 Handle<Object> old_length(object->length(), isolate_);
420 while (i < length) {
421 if (object->length() != *old_length ||
422 object->GetElementsKind() != FAST_ELEMENTS) {
423 // Fall back to slow path.
424 break;
425 }
426 Separator(i == 0);
427 Result result = SerializeElement(
428 isolate_,
429 Handle<Object>(FixedArray::cast(object->elements())->get(i),
430 isolate_),
431 i);
432 if (result == UNCHANGED) {
433 builder_.AppendCString("null");
434 } else if (result != SUCCESS) {
435 return result;
436 }
437 i++;
438 }
439 break;
440 }
441 // The FAST_HOLEY_* cases could be handled in a faster way. They resemble
442 // the non-holey cases except that a lookup is necessary for holes.
443 default:
444 break;
412 } 445 }
413 case FAST_DOUBLE_ELEMENTS: { 446 }
414 // Empty array is FixedArray but not FixedDoubleArray. 447 if (i < length) {
415 if (length == 0) break; 448 // Slow path for non-fast elements and fall-back in edge case.
416 Handle<FixedDoubleArray> elements( 449 Result result = SerializeArrayLikeSlow(object, i, length);
417 FixedDoubleArray::cast(object->elements()), isolate_); 450 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 } 451 }
456 Unindent(); 452 Unindent();
457 if (length > 0) NewLine(); 453 if (length > 0) NewLine();
458 builder_.AppendCharacter(']'); 454 builder_.AppendCharacter(']');
459 StackPop(); 455 StackPop();
460 return SUCCESS; 456 return SUCCESS;
461 } 457 }
462 458
463 BasicJsonStringifier::Result BasicJsonStringifier::SerializeArrayLikeSlow( 459 JsonStringifier::Result JsonStringifier::SerializeArrayLikeSlow(
464 Handle<JSReceiver> object, uint32_t start, uint32_t length) { 460 Handle<JSReceiver> object, uint32_t start, uint32_t length) {
465 for (uint32_t i = start; i < length; i++) { 461 for (uint32_t i = start; i < length; i++) {
466 Separator(i == 0); 462 Separator(i == 0);
467 Handle<Object> element; 463 Handle<Object> element;
468 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 464 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
469 isolate_, element, JSReceiver::GetElement(isolate_, object, i), 465 isolate_, element, JSReceiver::GetElement(isolate_, object, i),
470 EXCEPTION); 466 EXCEPTION);
471 if (element->IsUndefined()) { 467 Result result = SerializeElement(isolate_, element, i);
468 if (result == SUCCESS) continue;
469 if (result == UNCHANGED) {
472 builder_.AppendCString("null"); 470 builder_.AppendCString("null");
473 } else { 471 } else {
474 Result result = SerializeElement(isolate_, element, i); 472 return result;
475 if (result == SUCCESS) continue;
476 if (result == UNCHANGED) {
477 builder_.AppendCString("null");
478 } else {
479 return result;
480 }
481 } 473 }
482 } 474 }
483 return SUCCESS; 475 return SUCCESS;
484 } 476 }
485 477
486 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( 478 JsonStringifier::Result JsonStringifier::SerializeJSObject(
487 Handle<JSObject> object) { 479 Handle<JSObject> object) {
488 HandleScope handle_scope(isolate_); 480 HandleScope handle_scope(isolate_);
489 Result stack_push = StackPush(object); 481 Result stack_push = StackPush(object);
490 if (stack_push != SUCCESS) return stack_push; 482 if (stack_push != SUCCESS) return stack_push;
491 483
492 if (property_list_.is_null() && 484 if (property_list_.is_null() &&
493 object->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER && 485 object->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER &&
494 object->HasFastProperties() && 486 object->HasFastProperties() &&
495 Handle<JSObject>::cast(object)->elements()->length() == 0) { 487 Handle<JSObject>::cast(object)->elements()->length() == 0) {
496 DCHECK(object->IsJSObject()); 488 DCHECK(object->IsJSObject());
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 if (comma) NewLine(); 523 if (comma) NewLine();
532 builder_.AppendCharacter('}'); 524 builder_.AppendCharacter('}');
533 } else { 525 } else {
534 Result result = SerializeJSReceiverSlow(object); 526 Result result = SerializeJSReceiverSlow(object);
535 if (result != SUCCESS) return result; 527 if (result != SUCCESS) return result;
536 } 528 }
537 StackPop(); 529 StackPop();
538 return SUCCESS; 530 return SUCCESS;
539 } 531 }
540 532
541 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSReceiverSlow( 533 JsonStringifier::Result JsonStringifier::SerializeJSReceiverSlow(
542 Handle<JSReceiver> object) { 534 Handle<JSReceiver> object) {
543 Handle<FixedArray> contents = property_list_; 535 Handle<FixedArray> contents = property_list_;
544 if (contents.is_null()) { 536 if (contents.is_null()) {
545 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 537 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
546 isolate_, contents, 538 isolate_, contents,
547 JSReceiver::GetKeys(object, OWN_ONLY, ENUMERABLE_STRINGS), EXCEPTION); 539 JSReceiver::GetKeys(object, OWN_ONLY, ENUMERABLE_STRINGS), EXCEPTION);
548 } 540 }
549 541
550 builder_.AppendCharacter('{'); 542 builder_.AppendCharacter('{');
551 Indent(); 543 Indent();
(...skipping 21 matching lines...) Expand all
573 Result result = SerializeProperty(property, comma, key_handle); 565 Result result = SerializeProperty(property, comma, key_handle);
574 if (!comma && result == SUCCESS) comma = true; 566 if (!comma && result == SUCCESS) comma = true;
575 if (result == EXCEPTION) return result; 567 if (result == EXCEPTION) return result;
576 } 568 }
577 Unindent(); 569 Unindent();
578 if (comma) NewLine(); 570 if (comma) NewLine();
579 builder_.AppendCharacter('}'); 571 builder_.AppendCharacter('}');
580 return SUCCESS; 572 return SUCCESS;
581 } 573 }
582 574
583 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSProxy( 575 JsonStringifier::Result JsonStringifier::SerializeJSProxy(
584 Handle<JSProxy> object) { 576 Handle<JSProxy> object) {
585 Result stack_push = StackPush(object); 577 Result stack_push = StackPush(object);
586 if (stack_push != SUCCESS) return stack_push; 578 if (stack_push != SUCCESS) return stack_push;
587 Maybe<bool> is_array = Object::IsArray(object); 579 Maybe<bool> is_array = Object::IsArray(object);
588 if (is_array.IsNothing()) return EXCEPTION; 580 if (is_array.IsNothing()) return EXCEPTION;
589 if (is_array.FromJust()) { 581 if (is_array.FromJust()) {
590 Handle<Object> length_object; 582 Handle<Object> length_object;
591 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 583 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
592 isolate_, length_object, 584 isolate_, length_object,
593 Object::GetLengthFromArrayLike(isolate_, object), EXCEPTION); 585 Object::GetLengthFromArrayLike(isolate_, object), EXCEPTION);
(...skipping 14 matching lines...) Expand all
608 builder_.AppendCharacter(']'); 600 builder_.AppendCharacter(']');
609 } else { 601 } else {
610 Result result = SerializeJSReceiverSlow(object); 602 Result result = SerializeJSReceiverSlow(object);
611 if (result != SUCCESS) return result; 603 if (result != SUCCESS) return result;
612 } 604 }
613 StackPop(); 605 StackPop();
614 return SUCCESS; 606 return SUCCESS;
615 } 607 }
616 608
617 template <typename SrcChar, typename DestChar> 609 template <typename SrcChar, typename DestChar>
618 void BasicJsonStringifier::SerializeStringUnchecked_( 610 void JsonStringifier::SerializeStringUnchecked_(
619 Vector<const SrcChar> src, 611 Vector<const SrcChar> src,
620 IncrementalStringBuilder::NoExtend<DestChar>* dest) { 612 IncrementalStringBuilder::NoExtend<DestChar>* dest) {
621 // Assert that uc16 character is not truncated down to 8 bit. 613 // Assert that uc16 character is not truncated down to 8 bit.
622 // The <uc16, char> version of this method must not be called. 614 // The <uc16, char> version of this method must not be called.
623 DCHECK(sizeof(DestChar) >= sizeof(SrcChar)); 615 DCHECK(sizeof(DestChar) >= sizeof(SrcChar));
624 616
625 for (int i = 0; i < src.length(); i++) { 617 for (int i = 0; i < src.length(); i++) {
626 SrcChar c = src[i]; 618 SrcChar c = src[i];
627 if (DoNotEscape(c)) { 619 if (DoNotEscape(c)) {
628 dest->Append(c); 620 dest->Append(c);
629 } else { 621 } else {
630 dest->AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]); 622 dest->AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
631 } 623 }
632 } 624 }
633 } 625 }
634 626
635 template <typename SrcChar, typename DestChar> 627 template <typename SrcChar, typename DestChar>
636 void BasicJsonStringifier::SerializeString_(Handle<String> string) { 628 void JsonStringifier::SerializeString_(Handle<String> string) {
637 int length = string->length(); 629 int length = string->length();
638 builder_.Append<uint8_t, DestChar>('"'); 630 builder_.Append<uint8_t, DestChar>('"');
639 // We make a rough estimate to find out if the current string can be 631 // 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 632 // 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 633 // an escaped character is 6. Shifting the remainin string length right by 3
642 // is a more pessimistic estimate, but faster to calculate. 634 // is a more pessimistic estimate, but faster to calculate.
643 int worst_case_length = length << 3; 635 int worst_case_length = length << 3;
644 if (builder_.CurrentPartCanFit(worst_case_length)) { 636 if (builder_.CurrentPartCanFit(worst_case_length)) {
645 DisallowHeapAllocation no_gc; 637 DisallowHeapAllocation no_gc;
646 Vector<const SrcChar> vector = string->GetCharVector<SrcChar>(); 638 Vector<const SrcChar> vector = string->GetCharVector<SrcChar>();
647 IncrementalStringBuilder::NoExtendBuilder<DestChar> no_extend( 639 IncrementalStringBuilder::NoExtendBuilder<DestChar> no_extend(
648 &builder_, worst_case_length); 640 &builder_, worst_case_length);
649 SerializeStringUnchecked_(vector, &no_extend); 641 SerializeStringUnchecked_(vector, &no_extend);
650 } else { 642 } else {
651 FlatStringReader reader(isolate_, string); 643 FlatStringReader reader(isolate_, string);
652 for (int i = 0; i < reader.length(); i++) { 644 for (int i = 0; i < reader.length(); i++) {
653 SrcChar c = reader.Get<SrcChar>(i); 645 SrcChar c = reader.Get<SrcChar>(i);
654 if (DoNotEscape(c)) { 646 if (DoNotEscape(c)) {
655 builder_.Append<SrcChar, DestChar>(c); 647 builder_.Append<SrcChar, DestChar>(c);
656 } else { 648 } else {
657 builder_.AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]); 649 builder_.AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
658 } 650 }
659 } 651 }
660 } 652 }
661 653
662 builder_.Append<uint8_t, DestChar>('"'); 654 builder_.Append<uint8_t, DestChar>('"');
663 } 655 }
664 656
665 template <> 657 template <>
666 bool BasicJsonStringifier::DoNotEscape(uint8_t c) { 658 bool JsonStringifier::DoNotEscape(uint8_t c) {
667 return c >= '#' && c <= '~' && c != '\\'; 659 return c >= '#' && c <= '~' && c != '\\';
668 } 660 }
669 661
670 template <> 662 template <>
671 bool BasicJsonStringifier::DoNotEscape(uint16_t c) { 663 bool JsonStringifier::DoNotEscape(uint16_t c) {
672 return c >= '#' && c != '\\' && c != 0x7f; 664 return c >= '#' && c != '\\' && c != 0x7f;
673 } 665 }
674 666
675 void BasicJsonStringifier::NewLine() { 667 void JsonStringifier::NewLine() {
676 if (gap_ == nullptr) return; 668 if (gap_ == nullptr) return;
677 builder_.AppendCharacter('\n'); 669 builder_.AppendCharacter('\n');
678 for (int i = 0; i < indent_; i++) builder_.AppendCString(gap_); 670 for (int i = 0; i < indent_; i++) builder_.AppendCString(gap_);
679 } 671 }
680 672
681 void BasicJsonStringifier::Separator(bool first) { 673 void JsonStringifier::Separator(bool first) {
682 if (!first) builder_.AppendCharacter(','); 674 if (!first) builder_.AppendCharacter(',');
683 NewLine(); 675 NewLine();
684 } 676 }
685 677
686 void BasicJsonStringifier::SerializeDeferredKey(bool deferred_comma, 678 void JsonStringifier::SerializeDeferredKey(bool deferred_comma,
687 Handle<Object> deferred_key) { 679 Handle<Object> deferred_key) {
688 Separator(!deferred_comma); 680 Separator(!deferred_comma);
689 SerializeString(Handle<String>::cast(deferred_key)); 681 SerializeString(Handle<String>::cast(deferred_key));
690 builder_.AppendCharacter(':'); 682 builder_.AppendCharacter(':');
691 if (gap_ != nullptr) builder_.AppendCharacter(' '); 683 if (gap_ != nullptr) builder_.AppendCharacter(' ');
692 } 684 }
693 685
694 void BasicJsonStringifier::SerializeString(Handle<String> object) { 686 void JsonStringifier::SerializeString(Handle<String> object) {
695 object = String::Flatten(object); 687 object = String::Flatten(object);
696 if (builder_.CurrentEncoding() == String::ONE_BYTE_ENCODING) { 688 if (builder_.CurrentEncoding() == String::ONE_BYTE_ENCODING) {
697 if (object->IsOneByteRepresentationUnderneath()) { 689 if (object->IsOneByteRepresentationUnderneath()) {
698 SerializeString_<uint8_t, uint8_t>(object); 690 SerializeString_<uint8_t, uint8_t>(object);
699 } else { 691 } else {
700 builder_.ChangeEncoding(); 692 builder_.ChangeEncoding();
701 SerializeString(object); 693 SerializeString(object);
702 } 694 }
703 } else { 695 } else {
704 if (object->IsOneByteRepresentationUnderneath()) { 696 if (object->IsOneByteRepresentationUnderneath()) {
705 SerializeString_<uint8_t, uc16>(object); 697 SerializeString_<uint8_t, uc16>(object);
706 } else { 698 } else {
707 SerializeString_<uc16, uc16>(object); 699 SerializeString_<uc16, uc16>(object);
708 } 700 }
709 } 701 }
710 } 702 }
711 703
712 } // namespace internal 704 } // namespace internal
713 } // namespace v8 705 } // namespace v8
OLDNEW
« src/builtins.cc ('K') | « src/json-stringifier.h ('k') | src/runtime/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698