summaryrefslogtreecommitdiffstats
path: root/layout/style/CSSVariableResolver.h
blob: f9758ca3a21a2163732ff8cc868b04ff04cca1b0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
/* 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/. */

/* object that resolves CSS variables using specified and inherited variable
 * values
 */

#ifndef mozilla_CSSVariableResolver_h
#define mozilla_CSSVariableResolver_h

#include "mozilla/DebugOnly.h"
#include "nsCSSParser.h"
#include "nsCSSScanner.h"
#include "nsDataHashtable.h"
#include "nsTArray.h"

namespace mozilla {

class CSSVariableDeclarations;
class CSSVariableValues;
class EnumerateVariableReferencesData;

class CSSVariableResolver
{
  friend class CSSVariableDeclarations;
  friend class CSSVariableValues;
  friend class EnumerateVariableReferencesData;
public:
  /**
   * Creates a new CSSVariableResolver that will output a set of resolved,
   * computed variables into aOutput.
   */
  explicit CSSVariableResolver(CSSVariableValues* aOutput)
    : mOutput(aOutput)
#ifdef DEBUG
    , mResolved(false)
#endif
  {
    MOZ_ASSERT(aOutput);
  }

  /**
   * Resolves the set of inherited variables from aInherited and the
   * set of specified variables from aSpecified.  The resolved variables
   * are written into mOutput.
   */
  void Resolve(const CSSVariableValues* aInherited,
               const CSSVariableDeclarations* aSpecified);

private:
  struct Variable
  {
    Variable(const nsAString& aVariableName,
             nsString aValue,
             nsCSSTokenSerializationType aFirstToken,
             nsCSSTokenSerializationType aLastToken,
             bool aWasInherited)
      : mVariableName(aVariableName)
      , mValue(aValue)
      , mFirstToken(aFirstToken)
      , mLastToken(aLastToken)
      , mWasInherited(aWasInherited)
      , mResolved(false)
      , mReferencesNonExistentVariable(false)
      , mInStack(false)
      , mIndex(0)
      , mLowLink(0) { }

    nsString mVariableName;
    nsString mValue;
    nsCSSTokenSerializationType mFirstToken;
    nsCSSTokenSerializationType mLastToken;

    // Whether this variable came from the set of inherited variables.
    bool mWasInherited;

    // Whether this variable has been resolved yet.
    bool mResolved;

    // Whether this variables includes any references to non-existent variables.
    bool mReferencesNonExistentVariable;

    // Bookkeeping for the cycle remover algorithm.
    bool mInStack;
    size_t mIndex;
    size_t mLowLink;
  };

  /**
   * Adds or modifies an existing entry in the set of variables to be resolved.
   * This is intended to be called by the AddVariablesToResolver functions on
   * the CSSVariableDeclarations and CSSVariableValues objects passed in to
   * Resolve.
   *
   * @param aName The variable name (not including any "--" prefix that would
   *   be part of the custom property name) whose value is to be set.
   * @param aValue The variable value.
   * @param aFirstToken The type of token at the start of the variable value.
   * @param aLastToken The type of token at the en of the variable value.
   * @param aWasInherited Whether this variable came from the set of inherited
   *   variables.
   */
  void Put(const nsAString& aVariableName,
           nsString aValue,
           nsCSSTokenSerializationType aFirstToken,
           nsCSSTokenSerializationType aLastToken,
           bool aWasInherited);

  // Helper functions for Resolve.
  void RemoveCycles(size_t aID);
  void ResolveVariable(size_t aID);

  // A mapping of variable names to an ID that indexes into mVariables
  // and mReferences.
  nsDataHashtable<nsStringHashKey, size_t> mVariableIDs;

  // The set of variables.
  nsTArray<Variable> mVariables;

  // The list of variables that each variable references.
  nsTArray<nsTArray<size_t> > mReferences;

  // The next index to assign to a variable found during the cycle removing
  // algorithm's traversal of the variable reference graph.
  size_t mNextIndex;

  // Stack of variable IDs that we push to as we traverse the variable reference
  // graph while looking for cycles.  Variable::mInStack reflects whether a
  // given variable has its ID in mStack.
  nsTArray<size_t> mStack;

  // CSS parser to use for parsing property values with variable references.
  nsCSSParser mParser;

  // The object to output the resolved variables into.
  CSSVariableValues* mOutput;

#ifdef DEBUG
  // Whether Resolve has been called.
  bool mResolved;
#endif
};

} // namespace mozilla

#endif