dom/smil/nsSMILInstanceTime.cpp
author Mike Shal <mshal@mozilla.com>
Thu, 24 Aug 2017 22:52:01 -0400
changeset 434519 cb773c661e0ca0bf297e977343076bef34411523
parent 389913 33f49f751b63cde40ffe16d4c5fee0b4a64a6a79
child 505383 6f3709b3878117466168c40affa7bca0b60cf75b
permissions -rw-r--r--
Bug 1402012 - Update buildconfig.py to use PartialConfigEnvironment; r=glandium By using the PartialConfigEnvironment, the clients of buildconfig will depend on config.statusd/ files instead of config.status directly. Clients can access substs and defines using buildconfig.substs['FOO'] or buildconfig.defines['BAR'], and then collect file-level dependencies for make using buildconfig.get_dependencies(). All GENERATED_FILES rules already make use of this because file_generate.py automatically includes these dependencies (along with all python modules loaded). As a result of this commit, re-running configure will no longer cause the world to be rebuilt. Although config.status is updated, no build steps use config.status directly and instead depend on values in config.statusd/, which are written with FileAvoidWrite. Since those files are not official targets according to the make backend, make won't try to continually rebuild the backend when those files are out of date. And since they are FileAvoidWrite, make will only re-run dependent steps if the actual configure value has changed. As a result of using JSON to load data from the config.statusd directory, substs can be unicode (instead of a bare string type). generate_certdata.py converts the subst manually to a string so the value can be exported to the environment without issue on Windows. Additionally, patching the buildconfig.substs dict no longer works, so the unit-symbolstore.py test was modified to patch the underlying buildconfig.substs._dict instead. The other files that needed to be modified make use of all the defines for the preprocessor. Those that are used during 'mach build' now use buildconfig.defines['ALLDEFINES'], which maps to a special FileAvoidWrite file generated for the PartialConfigEnvironment. MozReview-Commit-ID: 2pJ4s3TVeS8

/* -*- 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/. */

#include "nsSMILInstanceTime.h"
#include "nsSMILInterval.h"
#include "nsSMILTimeValueSpec.h"
#include "mozilla/AutoRestore.h"

//----------------------------------------------------------------------
// Implementation

nsSMILInstanceTime::nsSMILInstanceTime(const nsSMILTimeValue& aTime,
                                       nsSMILInstanceTimeSource aSource,
                                       nsSMILTimeValueSpec* aCreator,
                                       nsSMILInterval* aBaseInterval)
  : mTime(aTime),
    mFlags(0),
    mVisited(false),
    mFixedEndpointRefCnt(0),
    mSerial(0),
    mCreator(aCreator),
    mBaseInterval(nullptr) // This will get set to aBaseInterval in a call to
                          // SetBaseInterval() at end of constructor
{
  switch (aSource) {
    case SOURCE_NONE:
      // No special flags
      break;

    case SOURCE_DOM:
      mFlags = kDynamic | kFromDOM;
      break;

    case SOURCE_SYNCBASE:
      mFlags = kMayUpdate;
      break;

    case SOURCE_EVENT:
      mFlags = kDynamic;
      break;
  }

  SetBaseInterval(aBaseInterval);
}

nsSMILInstanceTime::~nsSMILInstanceTime()
{
  MOZ_ASSERT(!mBaseInterval,
             "Destroying instance time without first calling Unlink()");
  MOZ_ASSERT(mFixedEndpointRefCnt == 0,
             "Destroying instance time that is still used as the fixed "
             "endpoint of an interval");
}

void
nsSMILInstanceTime::Unlink()
{
  RefPtr<nsSMILInstanceTime> deathGrip(this);
  if (mBaseInterval) {
    mBaseInterval->RemoveDependentTime(*this);
    mBaseInterval = nullptr;
  }
  mCreator = nullptr;
}

void
nsSMILInstanceTime::HandleChangedInterval(
    const nsSMILTimeContainer* aSrcContainer,
    bool aBeginObjectChanged,
    bool aEndObjectChanged)
{
  // It's possible a sequence of notifications might cause our base interval to
  // be updated and then deleted. Furthermore, the delete might happen whilst
  // we're still in the queue to be notified of the change. In any case, if we
  // don't have a base interval, just ignore the change.
  if (!mBaseInterval)
    return;

  MOZ_ASSERT(mCreator, "Base interval is set but creator is not.");

  if (mVisited) {
    // Break the cycle here
    Unlink();
    return;
  }

  bool objectChanged = mCreator->DependsOnBegin() ? aBeginObjectChanged :
                                                      aEndObjectChanged;

  RefPtr<nsSMILInstanceTime> deathGrip(this);
  mozilla::AutoRestore<bool> setVisited(mVisited);
  mVisited = true;

  mCreator->HandleChangedInstanceTime(*GetBaseTime(), aSrcContainer, *this,
                                      objectChanged);
}

void
nsSMILInstanceTime::HandleDeletedInterval()
{
  MOZ_ASSERT(mBaseInterval,
             "Got call to HandleDeletedInterval on an independent instance "
             "time");
  MOZ_ASSERT(mCreator, "Base interval is set but creator is not");

  mBaseInterval = nullptr;
  mFlags &= ~kMayUpdate; // Can't update without a base interval

  RefPtr<nsSMILInstanceTime> deathGrip(this);
  mCreator->HandleDeletedInstanceTime(*this);
  mCreator = nullptr;
}

void
nsSMILInstanceTime::HandleFilteredInterval()
{
  MOZ_ASSERT(mBaseInterval,
             "Got call to HandleFilteredInterval on an independent instance "
             "time");

  mBaseInterval = nullptr;
  mFlags &= ~kMayUpdate; // Can't update without a base interval
  mCreator = nullptr;
}

bool
nsSMILInstanceTime::ShouldPreserve() const
{
  return mFixedEndpointRefCnt > 0 || (mFlags & kWasDynamicEndpoint);
}

void
nsSMILInstanceTime::UnmarkShouldPreserve()
{
  mFlags &= ~kWasDynamicEndpoint;
}

void
nsSMILInstanceTime::AddRefFixedEndpoint()
{
  MOZ_ASSERT(mFixedEndpointRefCnt < UINT16_MAX,
             "Fixed endpoint reference count upper limit reached");
  ++mFixedEndpointRefCnt;
  mFlags &= ~kMayUpdate; // Once fixed, always fixed
}

void
nsSMILInstanceTime::ReleaseFixedEndpoint()
{
  MOZ_ASSERT(mFixedEndpointRefCnt > 0, "Duplicate release");
  --mFixedEndpointRefCnt;
  if (mFixedEndpointRefCnt == 0 && IsDynamic()) {
    mFlags |= kWasDynamicEndpoint;
  }
}

bool
nsSMILInstanceTime::IsDependentOn(const nsSMILInstanceTime& aOther) const
{
  if (mVisited)
    return false;

  const nsSMILInstanceTime* myBaseTime = GetBaseTime();
  if (!myBaseTime)
    return false;

  if (myBaseTime == &aOther)
    return true;

  mozilla::AutoRestore<bool> setVisited(mVisited);
  mVisited = true;
  return myBaseTime->IsDependentOn(aOther);
}

const nsSMILInstanceTime*
nsSMILInstanceTime::GetBaseTime() const
{
  if (!mBaseInterval) {
    return nullptr;
  }

  MOZ_ASSERT(mCreator, "Base interval is set but there is no creator.");
  if (!mCreator) {
    return nullptr;
  }

  return mCreator->DependsOnBegin() ? mBaseInterval->Begin() :
                                      mBaseInterval->End();
}

void
nsSMILInstanceTime::SetBaseInterval(nsSMILInterval* aBaseInterval)
{
  MOZ_ASSERT(!mBaseInterval,
             "Attempting to reassociate an instance time with a different "
             "interval.");

  if (aBaseInterval) {
    MOZ_ASSERT(mCreator,
               "Attempting to create a dependent instance time without "
               "reference to the creating nsSMILTimeValueSpec object.");
    if (!mCreator)
      return;

    aBaseInterval->AddDependentTime(*this);
  }

  mBaseInterval = aBaseInterval;
}