mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 08:32:43 +00:00 
			
		
		
		
	LibJS: Use the EnumerateObjectProperties AO to print objects
Instead of just iterating indexed properties and direct properties on the object's shape, let's walk the prototype chain and grab every non-symbol property by re-using the AO for for-in statements. We'll probably want to move this to a custom algorithm just for pretty printing that doesn't skip some property types, but this already gives a major improvement when printing LegacyPlatformObjects from LibWeb to the console.
This commit is contained in:
		
							parent
							
								
									f40094d014
								
							
						
					
					
						commit
						2bec236ea6
					
				
					 1 changed files with 34 additions and 18 deletions
				
			
		|  | @ -188,29 +188,45 @@ ErrorOr<void> print_array(JS::PrintContext& print_context, JS::Array const& arra | |||
| 
 | ||||
| ErrorOr<void> print_object(JS::PrintContext& print_context, JS::Object const& object, HashTable<JS::Object*>& seen_objects) | ||||
| { | ||||
|     TRY(js_out(print_context, "{{")); | ||||
|     TRY(js_out(print_context, "{}{{", object.class_name())); | ||||
|     bool first = true; | ||||
|     for (auto& entry : object.indexed_properties()) { | ||||
|         TRY(print_separator(print_context, first)); | ||||
|         TRY(js_out(print_context, "\"\033[33;1m{}\033[0m\": ", entry.index())); | ||||
|         auto value_or_error = object.get(entry.index()); | ||||
|         // The V8 repl doesn't throw an exception here, and instead just
 | ||||
|     static constexpr size_t max_number_of_new_objects = 20; // Arbitrary limit
 | ||||
|     size_t original_num_seen_objects = seen_objects.size(); | ||||
| 
 | ||||
|     auto maybe_completion = object.enumerate_object_properties([&](JS::Value property_key) -> Optional<JS::Completion> { | ||||
|         // The V8 repl doesn't throw an exception on accessing properties, and instead just
 | ||||
|         // prints 'undefined'. We may choose to replicate that behavior in
 | ||||
|         // the future, but for now lets just catch the error
 | ||||
|         auto error = print_separator(print_context, first); | ||||
|         if (error.is_error()) | ||||
|             return JS::js_undefined(); | ||||
|         error = js_out(print_context, "\033[33;1m"); | ||||
|         if (error.is_error()) | ||||
|             return JS::js_undefined(); | ||||
|         error = print_value(print_context, property_key, seen_objects); | ||||
|         // NOTE: Ignore this error to always print out "reset" ANSI sequence
 | ||||
|         error = js_out(print_context, "\033[0m: "); | ||||
|         if (error.is_error()) | ||||
|             return JS::js_undefined(); | ||||
|         auto maybe_property_key = JS::PropertyKey::from_value(print_context.vm, property_key); | ||||
|         if (maybe_property_key.is_error()) | ||||
|             return JS::js_undefined(); | ||||
|         auto value_or_error = object.get(maybe_property_key.value()); | ||||
|         if (value_or_error.is_error()) | ||||
|             return {}; | ||||
|             return JS::js_undefined(); | ||||
|         auto value = value_or_error.release_value(); | ||||
|         TRY(print_value(print_context, value, seen_objects)); | ||||
|     } | ||||
|     for (auto& it : object.shape().property_table_ordered()) { | ||||
|         TRY(print_separator(print_context, first)); | ||||
|         if (it.key.is_string()) { | ||||
|             TRY(js_out(print_context, "\"\033[33;1m{}\033[0m\": ", it.key.to_display_string())); | ||||
|         } else { | ||||
|             TRY(js_out(print_context, "[\033[33;1m{}\033[0m]: ", it.key.to_display_string())); | ||||
|         } | ||||
|         TRY(print_value(print_context, object.get_direct(it.value.offset), seen_objects)); | ||||
|     } | ||||
|         error = print_value(print_context, value, seen_objects); | ||||
|         // FIXME: Come up with a better way to structure the data so that we don't care about this limit
 | ||||
|         if (seen_objects.size() > original_num_seen_objects + max_number_of_new_objects) | ||||
|             return JS::js_undefined(); // Stop once we've seen a ton of objects, to prevent spamming the console.
 | ||||
|         if (error.is_error()) | ||||
|             return JS::js_undefined(); | ||||
|         return {}; | ||||
|     }); | ||||
|     // Swallow Error/undefined from printing properties
 | ||||
|     if (maybe_completion.has_value()) | ||||
|         return {}; | ||||
| 
 | ||||
|     if (!first) | ||||
|         TRY(js_out(print_context, " ")); | ||||
|     TRY(js_out(print_context, "}}")); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andrew Kaster
						Andrew Kaster