layout/style/ServoBindingTypes.h
author Nika Layzell <nika@thelayzells.com>
Tue, 25 Sep 2018 17:34:53 +0200
changeset 507828 5e6dae0c1e5a4939ccd406f14607f7fafffd45a7
parent 499658 8819dd315519624abe75cb340aa1ae8cfd62ca86
child 508163 6f3709b3878117466168c40affa7bca0b60cf75b
permissions -rw-r--r--
Bug 1448426 - Wrap windows.h to avoid problematic define statements, r=froydnj,glandium By default, windows.h exposes a large number of problematic define statements which are UpperCamelCase, such as a define from `CreateWindow` to `CreateWindow{A,W}`. As many of these names are generic (e.g. CreateFile, CreateWindow), they can mess up Gecko code that may legitimately have its own methods with the same names. The header also defines some traditional SCREAMING_SNAKE_CASE defines which can mess up our code by conflicting with local values. This patch adds a simple code generator which generates wrappers for these defines, and uses them to wrap the windows.h wrapper using the `stl_wrappers` mechanism, allowing us to use windows.h in more places. Differential Revision: https://phabricator.services.mozilla.com/D10932

/* -*- 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 borrowed,
// 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:
//
//   Raw{Gecko,Servo}{Type}Borrowed
//   Raw{Gecko,Servo}{Type}BorrowedOrNull
//     immutable, borrowed reference (or null)
//
//   Raw{Gecko,Servo}{Type}BorrowedMut
//   Raw{Gecko,Servo}{Type}BorrowedMutOrNull
//     mutable, borrowed reference (or null)
//
//   RawServo{Type}Strong
//     strong reference to an Arc-managed value
//
//   RawServo{Type}Owned
//   RawServo{Type}OwnedOrNull
//     owned reference to a Box-managed value (or null)
//
// All of these borrowed, strong, and owned types are generated by adding
// entries to one of these files:
//
//   BorrowedTypeList.h
//     generates some or all of the Borrowed types
//
//   ServoArcTypeList.h
//     generates all of the Borrowed types and the Strong type
//
//   ServoBoxedTypeList.h
//     generates all of the Borrowed types and the Owned & OwnedNull types
//
// The borrowed, 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++
// ========================
//
// All of the Borrowed types are C++ typedefs for raw pointers, and can be used
// directly.  Since the types they point to are opaque, there isn't much that
// can be done with these apart from passing them around, holding on to them,
// checking them for equality, etc.  If they are Arc-managed or Box-managed
// Servo types, they can be assigned to a RefPtr<> or UniquePtr<>.
//
// 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<RawServo{Type}>, 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<RawServo{Type}>, but it's probably easier just to pass a Borrowed
// value and let the Rust code turn it into an Arc.
//
// The Owned types are C++ typedefs for raw pointers.  When receiving an Owned
// value from a Servo_* FFI function, it should be assigned to a UniquePtr<>,
// otherwise it will leak.
//
// To pass an Owned value to Servo, call `release()` on the UniquePtr<> it's
// living in (to take ownership of it), and pass that pointer in directly.
//
// 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.
//
// The Borrowed types are defined as Rust reference types.
//
// Borrowed types for Gecko values are references to the bindgened versions of
// the C++ types, so when receiving references over FFI into a Servo_* function,
// they can be used directly, and when returning them back to Gecko, the
// reference can be returned directly.
//
// Borrowed types for Servo values are references to an opaque type, which must
// be converted to or from the appropriate Rust type:
//
//   For an Arc-owned value, a RawServoFooBorrowed received from FFI can be
//   converted into a `&Arc<Foo>` by calling `Foo::as_arc(&raw_servo_foo)`.
//   Returning a RawServoFooBorrowed over FFI back to Gecko can be done by
//   calling `as_borrowed()` on the `Arc<Foo>`.
//
//   For a Box-owned value, a RawServoFooBorrowed received from FFI can be
//   converted into a `&Foo` by calling `Foo::from_ffi(&raw_servo_foo)`.
//   Returning a RawServoFooBorrowed over FFI back to Gecko can be done by
//   calling `as_ffi()` on the `Foo`.
//
// The Strong types are defined as gecko_bindings::sugar::ownership::Strong<T>.
//
// This is an FFI safe type that represents the value with a strong reference
// already added to it.  Dropping a Strong<T> will leak the strong reference.
//
// A RawServoFooStrong received from FFI can be converted into a
// `RawOffsetArc<Foo>` by calling `into_arc()` or `into_arc_opt()` on it.
// To pass a RawServoFooStrong back to Gecko, call `into_strong()` on the
// `Arc<Foo>`.
//
// The Owned types are defined as gecko_bindings::sugar::ownership::Owned<T>
// (or OwnedOrNull<T>).
//
// This is another FFI safe type that represents the owning reference to the
// value.  Dropping an Owned<T> will leak the value.
//
// A RawServoFooOwned received from FFI can be converted into a `Box<Foo>`
// by calling `into_box()` or `into_box_opt()` on it.  To pass a
// RawServoFooOwned back to Gecko, call `HasBoxFFI::into_ffi()` passing in
// the `Box<Foo>` 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/ServoComputedData.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_BOXED_TYPE(name_, type_) struct type_;
#include "mozilla/ServoBoxedTypeList.h"
#undef SERVO_BOXED_TYPE

#define SERVO_ARC_TYPE(name_, type_) struct type_;
#include "mozilla/ServoArcTypeList.h"
#undef SERVO_ARC_TYPE

class nsCSSPropertyIDSet;
class nsCSSValue;
class nsIDocument;
class nsINode;
class nsPresContext;
class nsXBLBinding;
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<PropertyStyleAnimationValuePair>;
using GfxMatrix4x4 = mozilla::gfx::Float[16];

namespace dom {
class StyleChildrenIterator;
class Element;
} // namespace dom
} // namespace mozilla

#define DECL_BORROWED_REF_TYPE_FOR(type_) typedef type_ const* type_##Borrowed;
#define DECL_NULLABLE_BORROWED_REF_TYPE_FOR(type_) typedef type_ const* type_##BorrowedOrNull;
#define DECL_BORROWED_MUT_REF_TYPE_FOR(type_) typedef type_* type_##BorrowedMut;
#define DECL_NULLABLE_BORROWED_MUT_REF_TYPE_FOR(type_) typedef type_* type_##BorrowedMutOrNull;

#define DECL_OWNED_REF_TYPE_FOR(type_)    \
  typedef type_* type_##Owned;            \
  DECL_BORROWED_REF_TYPE_FOR(type_)       \
  DECL_BORROWED_MUT_REF_TYPE_FOR(type_)

#define DECL_NULLABLE_OWNED_REF_TYPE_FOR(type_)    \
  typedef type_* type_##OwnedOrNull;               \
  DECL_NULLABLE_BORROWED_REF_TYPE_FOR(type_)       \
  DECL_NULLABLE_BORROWED_MUT_REF_TYPE_FOR(type_)

#define GECKO_BORROWED_TYPE(geckotype_, ffitype_)      \
  using ffitype_ = geckotype_;                         \
  using ffitype_##Borrowed = const ffitype_*;          \
  using ffitype_##BorrowedOrNull = const ffitype_*;
#define GECKO_BORROWED_TYPE_MUT(geckotype_, ffitype_)  \
  GECKO_BORROWED_TYPE(geckotype_, ffitype_)            \
  using ffitype_##BorrowedMut = ffitype_*;             \
  using ffitype_##BorrowedMutOrNull = ffitype_*;
#include "mozilla/BorrowedTypeList.h"
#undef GECKO_BORROWED_TYPE_MUT
#undef GECKO_BORROWED_TYPE

#define SERVO_ARC_TYPE(name_, type_)                 \
  DECL_NULLABLE_BORROWED_REF_TYPE_FOR(type_)         \
  DECL_BORROWED_REF_TYPE_FOR(type_)                  \
  DECL_BORROWED_MUT_REF_TYPE_FOR(type_)              \
  struct MOZ_MUST_USE_TYPE type_##Strong             \
  {                                                  \
    type_* mPtr;                                     \
    already_AddRefed<type_> Consume();               \
  };                                                 \
  extern "C" {                                       \
  void Servo_##name_##_AddRef(type_##Borrowed ptr);  \
  void Servo_##name_##_Release(type_##Borrowed ptr); \
  }                                                  \
  namespace mozilla {                                \
  template<> struct RefPtrTraits<type_> {            \
    static void AddRef(type_* aPtr) {                \
      Servo_##name_##_AddRef(aPtr);                  \
    }                                                \
    static void Release(type_* aPtr) {               \
      Servo_##name_##_Release(aPtr);                 \
    }                                                \
  };                                                 \
  }
#include "mozilla/ServoArcTypeList.h"
#undef SERVO_ARC_TYPE

#define SERVO_BOXED_TYPE(name_, type_)                      \
  DECL_OWNED_REF_TYPE_FOR(type_)                            \
  DECL_NULLABLE_OWNED_REF_TYPE_FOR(type_)                   \
  extern "C" void Servo_##name_##_Drop(type_##Owned ptr);   \
  namespace mozilla {                                       \
  template<>                                                \
  class DefaultDelete<type_>                                \
  {                                                         \
  public:                                                   \
    void operator()(type_* aPtr) const                      \
    {                                                       \
      Servo_##name_##_Drop(aPtr);                           \
    }                                                       \
  };                                                        \
  }
#include "mozilla/ServoBoxedTypeList.h"
#undef SERVO_BOXED_TYPE

#define DEFINE_ARRAY_TYPE_FOR(type_)                                \
  struct nsTArrayBorrowed_##type_ {                                 \
    nsTArray<type_>* mArray;                                        \
    MOZ_IMPLICIT nsTArrayBorrowed_##type_(nsTArray<type_>* aArray)  \
      : mArray(aArray) {}                                           \
  }
DEFINE_ARRAY_TYPE_FOR(uintptr_t);
#undef DEFINE_ARRAY_TYPE_FOR


// Other special cases.

typedef void* RawServoAnimationValueTableBorrowed;

// TODO(heycam): Handle these elsewhere.
struct RawServoAnimationValueMap;
DECL_NULLABLE_BORROWED_REF_TYPE_FOR(RawServoAnimationValueMap)
DECL_BORROWED_REF_TYPE_FOR(RawServoAnimationValueMap)
DECL_BORROWED_MUT_REF_TYPE_FOR(RawServoAnimationValueMap)

typedef mozilla::ComputedStyle const* ComputedStyleBorrowed;
typedef mozilla::ComputedStyle const* ComputedStyleBorrowedOrNull;
typedef ServoComputedData const* ServoComputedDataBorrowed;

struct MOZ_MUST_USE_TYPE ComputedStyleStrong
{
  mozilla::ComputedStyle* mPtr;
  already_AddRefed<mozilla::ComputedStyle> Consume();
};

// This is a reference to a reference of RawServoDeclarationBlock, which
// corresponds to Option<&Arc<Locked<RawServoDeclarationBlock>>> in Servo side.
DECL_NULLABLE_BORROWED_REF_TYPE_FOR(RawServoDeclarationBlockStrong)

#undef DECL_ARC_REF_TYPE_FOR
#undef DECL_OWNED_REF_TYPE_FOR
#undef DECL_NULLABLE_OWNED_REF_TYPE_FOR
#undef DECL_BORROWED_REF_TYPE_FOR
#undef DECL_NULLABLE_BORROWED_REF_TYPE_FOR
#undef DECL_BORROWED_MUT_REF_TYPE_FOR
#undef DECL_NULLABLE_BORROWED_MUT_REF_TYPE_FOR

#endif // mozilla_ServoBindingTypes_h