RefPtr<API::Object> UserData::transform(API::Object* object, const std::function<RefPtr<API::Object> (const API::Object&)> transformer) { if (!object) return nullptr; if (object->type() == API::Object::Type::Array) { auto& array = static_cast<API::Array&>(*object); Vector<RefPtr<API::Object>> elements; elements.reserveInitialCapacity(array.elements().size()); for (const auto& element : array.elements()) elements.uncheckedAppend(transform(element.get(), transformer)); return API::Array::create(std::move(elements)); } if (object->type() == API::Object::Type::Dictionary) { auto& dictionary = static_cast<ImmutableDictionary&>(*object); ImmutableDictionary::MapType map; for (const auto& keyValuePair : dictionary.map()) map.add(keyValuePair.key, transform(keyValuePair.value.get(), transformer)); return ImmutableDictionary::create(std::move(map)); } if (auto transformedObject = transformer(*object)) return transformedObject; return object; }
bool UserData::decode(IPC::ArgumentDecoder& decoder, RefPtr<API::Object>& result) { API::Object::Type type; if (!decoder.decodeEnum(type)) return false; switch (type) { case API::Object::Type::Array: { uint64_t size; if (!decoder.decode(size)) return false; Vector<RefPtr<API::Object>> elements; for (size_t i = 0; i < size; ++i) { RefPtr<API::Object> element; if (!decode(decoder, element)) return false; elements.append(std::move(element)); } result = API::Array::create(std::move(elements)); break; } case API::Object::Type::Boolean: if (!API::Boolean::decode(decoder, result)) return false; break; case API::Object::Type::Data: if (!API::Data::decode(decoder, result)) return false; break; case API::Object::Type::Dictionary: { uint64_t size; if (!decoder.decode(size)) return false; ImmutableDictionary::MapType map; for (size_t i = 0; i < size; ++i) { String key; if (!decoder.decode(key)) return false; RefPtr<API::Object> value; if (!decode(decoder, value)) return false; if (!map.add(std::move(key), std::move(value)).isNewEntry) return false; } result = ImmutableDictionary::create(std::move(map)); break; } case API::Object::Type::Double: if (!API::Double::decode(decoder, result)) return false; break; case API::Object::Type::Error: if (!API::Error::decode(decoder, result)) return false; break; case API::Object::Type::FrameHandle: { uint64_t frameID; if (!decoder.decode(frameID)) return false; result = API::FrameHandle::create(frameID); break; } case API::Object::Type::Null: result = nullptr; break; case API::Object::Type::Point: if (!API::Point::decode(decoder, result)) return false; break; case API::Object::Type::Rect: if (!API::Rect::decode(decoder, result)) return false; break; case API::Object::Type::SerializedScriptValue: { IPC::DataReference dataReference; if (!decoder.decode(dataReference)) return false; auto vector = dataReference.vector(); result = WebSerializedScriptValue::adopt(vector); break; } case API::Object::Type::Size: if (!API::Size::decode(decoder, result)) return false; break; case API::Object::Type::String: { String string; if (!decoder.decode(string)) return false; result = API::String::create(string); break; } case API::Object::Type::URL: if (!API::URL::decode(decoder, result)) return false; break; case API::Object::Type::URLRequest: if (!API::URLRequest::decode(decoder, result)) return false; break; case API::Object::Type::URLResponse: if (!API::URLResponse::decode(decoder, result)) return false; break; case API::Object::Type::UInt64: if (!API::UInt64::decode(decoder, result)) return false; break; default: ASSERT_NOT_REACHED(); } return true; }