mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 09:52:44 +00:00 
			
		
		
		
	LibWeb: Add ability to {,de}serialize platform objects
This adds the ability to serialize and deserialize serializable platform object in structured_serialize() and structured_deserialize().
This commit is contained in:
		
							parent
							
								
									394c38729f
								
							
						
					
					
						commit
						27445f3132
					
				
					 1 changed files with 45 additions and 3 deletions
				
			
		|  | @ -31,7 +31,9 @@ | |||
| #include <LibJS/Runtime/VM.h> | ||||
| #include <LibWeb/Bindings/ExceptionOrUtils.h> | ||||
| #include <LibWeb/Bindings/Intrinsics.h> | ||||
| #include <LibWeb/Bindings/Serializable.h> | ||||
| #include <LibWeb/Bindings/Transferable.h> | ||||
| #include <LibWeb/FileAPI/Blob.h> | ||||
| #include <LibWeb/HTML/MessagePort.h> | ||||
| #include <LibWeb/HTML/StructuredSerialize.h> | ||||
| #include <LibWeb/WebIDL/ExceptionOr.h> | ||||
|  | @ -105,6 +107,8 @@ enum ValueTag { | |||
| 
 | ||||
|     ObjectReference, | ||||
| 
 | ||||
|     SerializableObject, | ||||
| 
 | ||||
|     // TODO: Define many more types
 | ||||
| 
 | ||||
|     // This tag or higher are understood to be errors
 | ||||
|  | @ -310,6 +314,14 @@ public: | |||
|         } | ||||
| 
 | ||||
|         // FIXME: 19. Otherwise, if value is a platform object that is a serializable object:
 | ||||
|         else if (value.is_object() && is<Bindings::Serializable>(value.as_object())) { | ||||
|             auto& serializable = dynamic_cast<Bindings::Serializable&>(value.as_object()); | ||||
| 
 | ||||
|             m_serialized.append(ValueTag::SerializableObject); | ||||
| 
 | ||||
|             // 1. Perform the serialization steps for value's primary interface, given value, serialized, and forStorage.
 | ||||
|             TRY(serializable.serialization_steps(m_serialized, m_for_storage)); | ||||
|         } | ||||
| 
 | ||||
|         // 20. Otherwise, if value is a platform object, then throw a "DataCloneError" DOMException.
 | ||||
|         else if (value.is_object() && is<Bindings::PlatformObject>(value.as_object())) { | ||||
|  | @ -812,7 +824,20 @@ public: | |||
|         } | ||||
|         // 22. Otherwise:
 | ||||
|         default: | ||||
|             return WebIDL::DataCloneError::create(*m_vm.current_realm(), "Unsupported type"_fly_string); | ||||
|             VERIFY(tag == ValueTag::SerializableObject); | ||||
| 
 | ||||
|             auto& realm = *m_vm.current_realm(); | ||||
|             // 1. Let interfaceName be serialized.[[Type]].
 | ||||
|             auto interface_name = TRY(deserialize_string(m_vm, m_serialized, m_position)); | ||||
|             // 2. If the interface identified by interfaceName is not exposed in targetRealm, then throw a "DataCloneError" DOMException.
 | ||||
|             if (!is_interface_exposed_on_target_realm(interface_name, realm)) | ||||
|                 return WebIDL::DataCloneError::create(realm, "Unsupported type"_fly_string); | ||||
| 
 | ||||
|             // 3. Set value to a new instance of the interface identified by interfaceName, created in targetRealm.
 | ||||
|             value = TRY(create_serialized_type(interface_name, realm)); | ||||
| 
 | ||||
|             // 4. Set deep to true.
 | ||||
|             deep = true; | ||||
|         } | ||||
| 
 | ||||
|         // 23. Set memory[serialized] to value.
 | ||||
|  | @ -874,8 +899,9 @@ public: | |||
| 
 | ||||
|             // 4. Otherwise:
 | ||||
|             else { | ||||
|                 // FIXME: 1. Perform the appropriate deserialization steps for the interface identified by serialized.[[Type]], given serialized, value, and targetRealm.
 | ||||
|                 VERIFY_NOT_REACHED(); | ||||
|                 // 1. Perform the appropriate deserialization steps for the interface identified by serialized.[[Type]], given serialized, value, and targetRealm.
 | ||||
|                 auto& serializable = dynamic_cast<Bindings::Serializable&>(value.as_object()); | ||||
|                 TRY(serializable.deserialization_steps(m_serialized, m_position)); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -896,6 +922,22 @@ private: | |||
|         m_position += 2; | ||||
|         return value; | ||||
|     } | ||||
| 
 | ||||
|     static WebIDL::ExceptionOr<JS::NonnullGCPtr<Bindings::PlatformObject>> create_serialized_type(StringView interface_name, JS::Realm& realm) | ||||
|     { | ||||
|         if (interface_name == "Blob"sv) | ||||
|             return FileAPI::Blob::create(realm); | ||||
| 
 | ||||
|         VERIFY_NOT_REACHED(); | ||||
|     } | ||||
| 
 | ||||
|     // FIXME: Consolidate this function with the similar is_interface_exposed_on_target_realm() used when transferring objects.
 | ||||
|     //        Also, the name parameter would be better off being the interface name (as a string) so that we don't need a switch statement.
 | ||||
|     static bool is_interface_exposed_on_target_realm(StringView interface_name, JS::Realm& realm) | ||||
|     { | ||||
|         auto const& intrinsics = Bindings::host_defined_intrinsics(realm); | ||||
|         return intrinsics.is_exposed(interface_name); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| WebIDL::ExceptionOr<ByteBuffer> deserialize_bytes(JS::VM& vm, ReadonlySpan<u32> vector, size_t& position) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Kenneth Myhra
						Kenneth Myhra