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

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, 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 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)),
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
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
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
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
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