/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* C++ types corresponding to Servo and Gecko types used across bindings, with some annotations to indicate ownership expectations */ // This file defines a number of C++ types used to represent strong, and owning // references to Servo and Gecko objects that might be used across bindings and // FFI. // // By convention, the types defined here are named "RawServo{Type}" and // "RawGecko{Type}". The {Type} should be something close to the real Rust or // C++ name of the type, but need not be. The "Raw" is really just used to // avoid clashing with other names. // // For Servo types, each "RawServo{ServoTypeName}" is generated as an opaque, // declared but not defined struct. // // For Gecko types, each "RawGecko{GeckoTypeName}" is a typedef that aliases // the actual C++ type. // // Each of these types can have a number of different typedefs generated for // them, representing different notions of ownership when passing or receiving // these values across bindings and FFI: // // RawServo{Type}Strong // strong reference to an Arc-managed value // // All of these strong, and owned types are generated by adding // entries to one of these files: // // ServoArcTypeList.h // generates the Strong type // // // The strong, and owned reference types should be used in FFI function // signatures where possible, to help indicate the ownership properties that // both sides of the function call must adhere to. // // There are some special cases defined at the bottom of this file that don't // fit neatly into these three categories. // // // Using these types in C++ ======================== // // The Strong types are a C++ struct that wraps a raw pointer. When receiving a // Strong value from a Servo_* FFI function, you must call Consume() on it to // convert it into an already_AddRefed, otherwise it will leak. // // We don't currently have any cases where we pass a Strong value to Servo; this // could be done by creating a RawServo{Type}Strong struct value whose mPtr is // initialized to the result of calling `.forget().take()` on a // RefPtr, but it's probably easier just to pass a raw pointer // and let the Rust code turn it into an Arc. // // TODO(heycam): We should perhaps have a similar struct for Owned types with a // Consume() method to convert them into a UniquePtr. The struct for Strong // types at least have MOZ_MUST_USE_TYPE on them. // // // Using these types in Rust ========================= // // The FFI type names are available in Rust in the gecko_bindings::bindings mod, // which is generated by servo/components/style/build_gecko.rs. // // Borrowed types in rust are represented by &T, Option<&T>, &mut T, and // Option<&mut T>. // // In C++ you should write them as const pointers (for &T and Option<&T>) or // non-const pointers (for &mut T and Option<&mut T>). // // The Strong types are defined as gecko_bindings::sugar::ownership::Strong. // // This is an FFI safe type that represents the value with a strong reference // already added to it. Dropping a Strong will leak the strong reference. // // A RawServoFooStrong received from FFI can be converted into a // `RawOffsetArc` by calling `into_arc()` or `into_arc_opt()` on it. // To pass a RawServoFooStrong back to Gecko, call `into_strong()` on the // `Arc`. // // The Owned types are defined as gecko_bindings::sugar::ownership::Owned // (or OwnedOrNull). // // This is another FFI safe type that represents the owning reference to the // value. Dropping an Owned will leak the value. // // An Owned received from FFI can be converted into a `Box` // by calling `into_box()`. To pass an Owned back to Gecko, call // `HasBoxFFI::into_ffi()` passing in the `Box` value. // // Reading through servo/components/style/gecko_bindings/sugar/ownership.rs // is also instructive in understanding all this. #ifndef mozilla_ServoBindingTypes_h #define mozilla_ServoBindingTypes_h #include "mozilla/RefPtr.h" #include "mozilla/ServoTypes.h" #include "mozilla/UniquePtr.h" #include "mozilla/gfx/Types.h" #include "nsCSSPropertyID.h" #include "nsStyleAutoArray.h" #include "nsTArray.h" // Forward declarations. #define SERVO_ARC_TYPE(name_, type_) struct type_; #include "mozilla/ServoArcTypeList.h" #undef SERVO_ARC_TYPE class nsCSSPropertyIDSet; class nsCSSValue; class nsINode; class nsPresContext; struct nsFontFaceRuleContainer; struct nsTimingFunction; namespace mozilla { class ComputedStyle; class ServoElementSnapshot; struct AnimationPropertySegment; struct ComputedTiming; struct Keyframe; struct PropertyStyleAnimationValuePair; struct PropertyValuePair; struct StyleAnimation; struct URLExtraData; using ComputedKeyframeValues = nsTArray; using GfxMatrix4x4 = mozilla::gfx::Float[16]; namespace dom { class StyleChildrenIterator; class Document; class Element; } // namespace dom } // namespace mozilla #define SERVO_ARC_TYPE(name_, type_) \ extern "C" { \ void Servo_##name_##_AddRef(const type_*); \ void Servo_##name_##_Release(const type_*); \ } \ namespace mozilla { \ template <> \ struct RefPtrTraits { \ static void AddRef(type_* aPtr) { Servo_##name_##_AddRef(aPtr); } \ static void Release(type_* aPtr) { Servo_##name_##_Release(aPtr); } \ }; \ } #include "mozilla/ServoArcTypeList.h" SERVO_ARC_TYPE(ComputedStyle, mozilla::ComputedStyle) #undef SERVO_ARC_TYPE #define SERVO_BOXED_TYPE(name_, type_) \ struct type_; \ extern "C" void Servo_##name_##_Drop(type_*); \ namespace mozilla { \ template <> \ class DefaultDelete { \ public: \ void operator()(type_* aPtr) const { Servo_##name_##_Drop(aPtr); } \ }; \ } #include "mozilla/ServoBoxedTypeList.h" #undef SERVO_BOXED_TYPE // Other special cases. struct RawServoAnimationValueTable; #endif // mozilla_ServoBindingTypes_h