Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/style/nsCSSValue.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
/* representation of simple property values within CSS declarations */
8
9
#include "nsCSSValue.h"
10
11
#include "mozilla/CORSMode.h"
12
#include "mozilla/FontPropertyTypes.h"
13
#include "mozilla/ServoBindings.h"
14
#include "mozilla/ServoStyleSet.h"
15
#include "mozilla/ServoTypes.h"
16
#include "mozilla/StyleSheetInlines.h"
17
#include "mozilla/Likely.h"
18
#include "mozilla/MemoryReporting.h"
19
#include "mozilla/css/ImageLoader.h"
20
#include "gfxFontConstants.h"
21
#include "imgIRequest.h"
22
#include "imgRequestProxy.h"
23
#include "nsIDocument.h"
24
#include "nsIURIMutator.h"
25
#include "nsCSSProps.h"
26
#include "nsNetUtil.h"
27
#include "nsPresContext.h"
28
#include "nsStyleUtil.h"
29
#include "nsDeviceContext.h"
30
#include "nsContentUtils.h"
31
32
using namespace mozilla;
33
using namespace mozilla::css;
34
35
template<class T>
36
static bool MightHaveRef(const T& aString)
37
0
{
38
0
  const typename T::char_type* current = aString.BeginReading();
39
0
  for (; current != aString.EndReading(); current++) {
40
0
    if (*current == '#') {
41
0
      return true;
42
0
    }
43
0
  }
44
0
45
0
  return false;
46
0
}
47
48
nsCSSValue::nsCSSValue(int32_t aValue, nsCSSUnit aUnit)
49
  : mUnit(aUnit)
50
0
{
51
0
  MOZ_ASSERT(aUnit == eCSSUnit_Integer || aUnit == eCSSUnit_Enumerated,
52
0
             "not an int value");
53
0
  if (aUnit == eCSSUnit_Integer || aUnit == eCSSUnit_Enumerated) {
54
0
    mValue.mInt = aValue;
55
0
  }
56
0
  else {
57
0
    mUnit = eCSSUnit_Null;
58
0
    mValue.mInt = 0;
59
0
  }
60
0
}
61
62
nsCSSValue::nsCSSValue(float aValue, nsCSSUnit aUnit)
63
  : mUnit(aUnit)
64
0
{
65
0
  MOZ_ASSERT(eCSSUnit_Percent <= aUnit, "not a float value");
66
0
  if (eCSSUnit_Percent <= aUnit) {
67
0
    mValue.mFloat = aValue;
68
0
    MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
69
0
  }
70
0
  else {
71
0
    mUnit = eCSSUnit_Null;
72
0
    mValue.mInt = 0;
73
0
  }
74
0
}
75
76
nsCSSValue::nsCSSValue(const nsString& aValue, nsCSSUnit aUnit)
77
  : mUnit(aUnit)
78
0
{
79
0
  MOZ_ASSERT(UnitHasStringValue(), "not a string value");
80
0
  if (UnitHasStringValue()) {
81
0
    mValue.mString = BufferFromString(aValue).take();
82
0
  }
83
0
  else {
84
0
    mUnit = eCSSUnit_Null;
85
0
    mValue.mInt = 0;
86
0
  }
87
0
}
88
89
nsCSSValue::nsCSSValue(nsCSSValue::Array* aValue, nsCSSUnit aUnit)
90
  : mUnit(aUnit)
91
0
{
92
0
  MOZ_ASSERT(UnitHasArrayValue(), "bad unit");
93
0
  mValue.mArray = aValue;
94
0
  mValue.mArray->AddRef();
95
0
}
96
97
nsCSSValue::nsCSSValue(mozilla::css::URLValue* aValue)
98
  : mUnit(eCSSUnit_URL)
99
0
{
100
0
  mValue.mURL = aValue;
101
0
  mValue.mURL->AddRef();
102
0
}
103
104
nsCSSValue::nsCSSValue(mozilla::css::GridTemplateAreasValue* aValue)
105
  : mUnit(eCSSUnit_GridTemplateAreas)
106
0
{
107
0
  mValue.mGridTemplateAreas = aValue;
108
0
  mValue.mGridTemplateAreas->AddRef();
109
0
}
110
111
nsCSSValue::nsCSSValue(SharedFontList* aValue)
112
  : mUnit(eCSSUnit_FontFamilyList)
113
0
{
114
0
  mValue.mFontFamilyList = aValue;
115
0
  mValue.mFontFamilyList->AddRef();
116
0
}
117
118
nsCSSValue::nsCSSValue(FontStretch aStretch)
119
  : mUnit(eCSSUnit_FontStretch)
120
0
{
121
0
  mValue.mFontStretch = aStretch;
122
0
}
123
124
nsCSSValue::nsCSSValue(FontSlantStyle aStyle)
125
  : mUnit(eCSSUnit_FontSlantStyle)
126
0
{
127
0
  mValue.mFontSlantStyle = aStyle;
128
0
}
129
130
nsCSSValue::nsCSSValue(FontWeight aWeight)
131
  : mUnit(eCSSUnit_FontWeight)
132
0
{
133
0
  mValue.mFontWeight = aWeight;
134
0
}
135
136
nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
137
  : mUnit(aCopy.mUnit)
138
0
{
139
0
  if (mUnit <= eCSSUnit_DummyInherit) {
140
0
    // nothing to do, but put this important case first
141
0
  }
142
0
  else if (eCSSUnit_Percent <= mUnit) {
143
0
    mValue.mFloat = aCopy.mValue.mFloat;
144
0
    MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
145
0
  }
146
0
  else if (UnitHasStringValue()) {
147
0
    mValue.mString = aCopy.mValue.mString;
148
0
    mValue.mString->AddRef();
149
0
  }
150
0
  else if (eCSSUnit_Integer <= mUnit && mUnit <= eCSSUnit_Enumerated) {
151
0
    mValue.mInt = aCopy.mValue.mInt;
152
0
  }
153
0
  else if (UnitHasArrayValue()) {
154
0
    mValue.mArray = aCopy.mValue.mArray;
155
0
    mValue.mArray->AddRef();
156
0
  }
157
0
  else if (eCSSUnit_URL == mUnit) {
158
0
    mValue.mURL = aCopy.mValue.mURL;
159
0
    mValue.mURL->AddRef();
160
0
  }
161
0
  else if (eCSSUnit_Pair == mUnit) {
162
0
    mValue.mPair = aCopy.mValue.mPair;
163
0
    mValue.mPair->AddRef();
164
0
  }
165
0
  else if (eCSSUnit_List == mUnit) {
166
0
    mValue.mList = aCopy.mValue.mList;
167
0
    mValue.mList->AddRef();
168
0
  }
169
0
  else if (eCSSUnit_ListDep == mUnit) {
170
0
    mValue.mListDependent = aCopy.mValue.mListDependent;
171
0
  }
172
0
  else if (eCSSUnit_SharedList == mUnit) {
173
0
    mValue.mSharedList = aCopy.mValue.mSharedList;
174
0
    mValue.mSharedList->AddRef();
175
0
  }
176
0
  else if (eCSSUnit_PairList == mUnit) {
177
0
    mValue.mPairList = aCopy.mValue.mPairList;
178
0
    mValue.mPairList->AddRef();
179
0
  }
180
0
  else if (eCSSUnit_PairListDep == mUnit) {
181
0
    mValue.mPairListDependent = aCopy.mValue.mPairListDependent;
182
0
  }
183
0
  else if (eCSSUnit_GridTemplateAreas == mUnit) {
184
0
    mValue.mGridTemplateAreas = aCopy.mValue.mGridTemplateAreas;
185
0
    mValue.mGridTemplateAreas->AddRef();
186
0
  }
187
0
  else if (eCSSUnit_FontFamilyList == mUnit) {
188
0
    mValue.mFontFamilyList = aCopy.mValue.mFontFamilyList;
189
0
    mValue.mFontFamilyList->AddRef();
190
0
  }
191
0
  else if (eCSSUnit_FontStretch == mUnit) {
192
0
    mValue.mFontStretch = aCopy.mValue.mFontStretch;
193
0
  }
194
0
  else if (eCSSUnit_FontSlantStyle == mUnit) {
195
0
    mValue.mFontSlantStyle = aCopy.mValue.mFontSlantStyle;
196
0
  }
197
0
  else if (eCSSUnit_FontWeight == mUnit) {
198
0
    mValue.mFontWeight = aCopy.mValue.mFontWeight;
199
0
  }
200
0
  else if (eCSSUnit_AtomIdent == mUnit) {
201
0
    mValue.mAtom = aCopy.mValue.mAtom;
202
0
    mValue.mAtom->AddRef();
203
0
  }
204
0
  else {
205
0
    MOZ_ASSERT(false, "unknown unit");
206
0
  }
207
0
}
208
209
nsCSSValue& nsCSSValue::operator=(const nsCSSValue& aCopy)
210
0
{
211
0
  if (this != &aCopy) {
212
0
    Reset();
213
0
    new (this) nsCSSValue(aCopy);
214
0
  }
215
0
  return *this;
216
0
}
217
218
nsCSSValue&
219
nsCSSValue::operator=(nsCSSValue&& aOther)
220
0
{
221
0
  MOZ_ASSERT(this != &aOther, "Self assigment with rvalue reference");
222
0
223
0
  Reset();
224
0
  mUnit = aOther.mUnit;
225
0
  mValue = aOther.mValue;
226
0
  aOther.mUnit = eCSSUnit_Null;
227
0
228
0
  return *this;
229
0
}
230
231
bool nsCSSValue::operator==(const nsCSSValue& aOther) const
232
0
{
233
0
  MOZ_ASSERT(mUnit != eCSSUnit_ListDep &&
234
0
             aOther.mUnit != eCSSUnit_ListDep &&
235
0
             mUnit != eCSSUnit_PairListDep &&
236
0
             aOther.mUnit != eCSSUnit_PairListDep,
237
0
             "don't use operator== with dependent lists");
238
0
239
0
  if (mUnit == aOther.mUnit) {
240
0
    if (mUnit <= eCSSUnit_DummyInherit) {
241
0
      return true;
242
0
    }
243
0
    else if (UnitHasStringValue()) {
244
0
      return (NS_strcmp(GetBufferValue(mValue.mString),
245
0
                        GetBufferValue(aOther.mValue.mString)) == 0);
246
0
    }
247
0
    else if ((eCSSUnit_Integer <= mUnit) && (mUnit <= eCSSUnit_Enumerated)) {
248
0
      return mValue.mInt == aOther.mValue.mInt;
249
0
    }
250
0
    else if (UnitHasArrayValue()) {
251
0
      return *mValue.mArray == *aOther.mValue.mArray;
252
0
    }
253
0
    else if (eCSSUnit_URL == mUnit) {
254
0
      return mValue.mURL->Equals(*aOther.mValue.mURL);
255
0
    }
256
0
    else if (eCSSUnit_Pair == mUnit) {
257
0
      return *mValue.mPair == *aOther.mValue.mPair;
258
0
    }
259
0
    else if (eCSSUnit_List == mUnit) {
260
0
      return nsCSSValueList::Equal(mValue.mList, aOther.mValue.mList);
261
0
    }
262
0
    else if (eCSSUnit_SharedList == mUnit) {
263
0
      return *mValue.mSharedList == *aOther.mValue.mSharedList;
264
0
    }
265
0
    else if (eCSSUnit_PairList == mUnit) {
266
0
      return nsCSSValuePairList::Equal(mValue.mPairList,
267
0
                                       aOther.mValue.mPairList);
268
0
    }
269
0
    else if (eCSSUnit_GridTemplateAreas == mUnit) {
270
0
      return *mValue.mGridTemplateAreas == *aOther.mValue.mGridTemplateAreas;
271
0
    }
272
0
    else if (eCSSUnit_FontFamilyList == mUnit) {
273
0
      return mValue.mFontFamilyList->mNames ==
274
0
             aOther.mValue.mFontFamilyList->mNames;
275
0
    }
276
0
    else if (eCSSUnit_FontStretch == mUnit) {
277
0
      return mValue.mFontStretch == aOther.mValue.mFontStretch;
278
0
    }
279
0
    else if (eCSSUnit_FontSlantStyle == mUnit) {
280
0
      return mValue.mFontSlantStyle == aOther.mValue.mFontSlantStyle;
281
0
    }
282
0
    else if (eCSSUnit_FontWeight == mUnit) {
283
0
      return mValue.mFontWeight == aOther.mValue.mFontWeight;
284
0
    }
285
0
    else if (eCSSUnit_AtomIdent == mUnit) {
286
0
      return mValue.mAtom == aOther.mValue.mAtom;
287
0
    }
288
0
    else {
289
0
      return mValue.mFloat == aOther.mValue.mFloat;
290
0
    }
291
0
  }
292
0
  return false;
293
0
}
294
295
double
296
nsCSSValue::GetAngleValueInRadians() const
297
0
{
298
0
  double angle = GetFloatValue();
299
0
300
0
  switch (GetUnit()) {
301
0
    case eCSSUnit_Radian: return angle;
302
0
    case eCSSUnit_Turn:   return angle * 2 * M_PI;
303
0
    case eCSSUnit_Degree: return angle * M_PI / 180.0;
304
0
    case eCSSUnit_Grad:   return angle * M_PI / 200.0;
305
0
306
0
    default:
307
0
      MOZ_ASSERT(false, "unrecognized angular unit");
308
0
      return 0.0;
309
0
  }
310
0
}
311
312
double
313
nsCSSValue::GetAngleValueInDegrees() const
314
0
{
315
0
  double angle = GetFloatValue();
316
0
317
0
  switch (GetUnit()) {
318
0
    case eCSSUnit_Degree: return angle;
319
0
    case eCSSUnit_Grad:   return angle * 0.9; // grad / 400 * 360
320
0
    case eCSSUnit_Radian: return angle * 180.0 / M_PI;  // rad / 2pi * 360
321
0
    case eCSSUnit_Turn:   return angle * 360.0;
322
0
323
0
    default:
324
0
      MOZ_ASSERT(false, "unrecognized angular unit");
325
0
      return 0.0;
326
0
  }
327
0
}
328
329
nscoord nsCSSValue::GetPixelLength() const
330
0
{
331
0
  MOZ_ASSERT(IsPixelLengthUnit(), "not a fixed length unit");
332
0
333
0
  double scaleFactor;
334
0
  switch (mUnit) {
335
0
  case eCSSUnit_Pixel: return nsPresContext::CSSPixelsToAppUnits(mValue.mFloat);
336
0
  case eCSSUnit_Pica: scaleFactor = 16.0; break;
337
0
  case eCSSUnit_Point: scaleFactor = 4/3.0; break;
338
0
  case eCSSUnit_Inch: scaleFactor = 96.0; break;
339
0
  case eCSSUnit_Millimeter: scaleFactor = 96/25.4; break;
340
0
  case eCSSUnit_Centimeter: scaleFactor = 96/2.54; break;
341
0
  case eCSSUnit_Quarter: scaleFactor = 96/101.6; break;
342
0
  default:
343
0
    NS_ERROR("should never get here");
344
0
    return 0;
345
0
  }
346
0
  return nsPresContext::CSSPixelsToAppUnits(float(mValue.mFloat*scaleFactor));
347
0
}
348
349
// Assert against resetting non-trivial CSS values from the parallel Servo
350
// traversal, since the refcounts aren't thread-safe.
351
// Note that the caller might be an OMTA thread, which is allowed to operate off
352
// main thread because it owns all of the corresponding nsCSSValues and any that
353
// they might be sharing members with. Since this can happen concurrently with
354
// the servo traversal, we have to use a more-precise (but slower) test.
355
0
#define DO_RELEASE(member) {                                     \
356
0
  MOZ_ASSERT(!ServoStyleSet::IsCurrentThreadInServoTraversal()); \
357
0
  mValue.member->Release();                                      \
358
0
}
359
360
void nsCSSValue::DoReset()
361
0
{
362
0
  if (UnitHasStringValue()) {
363
0
    mValue.mString->Release();
364
0
  } else if (UnitHasArrayValue()) {
365
0
    DO_RELEASE(mArray);
366
0
  } else if (eCSSUnit_URL == mUnit) {
367
0
    DO_RELEASE(mURL);
368
0
  } else if (eCSSUnit_Pair == mUnit) {
369
0
    DO_RELEASE(mPair);
370
0
  } else if (eCSSUnit_List == mUnit) {
371
0
    DO_RELEASE(mList);
372
0
  } else if (eCSSUnit_SharedList == mUnit) {
373
0
    DO_RELEASE(mSharedList);
374
0
  } else if (eCSSUnit_PairList == mUnit) {
375
0
    DO_RELEASE(mPairList);
376
0
  } else if (eCSSUnit_GridTemplateAreas == mUnit) {
377
0
    DO_RELEASE(mGridTemplateAreas);
378
0
  } else if (eCSSUnit_FontFamilyList == mUnit) {
379
0
    DO_RELEASE(mFontFamilyList);
380
0
  } else if (eCSSUnit_AtomIdent == mUnit) {
381
0
    DO_RELEASE(mAtom);
382
0
  }
383
0
  mUnit = eCSSUnit_Null;
384
0
}
385
386
#undef DO_RELEASE
387
388
void nsCSSValue::SetIntValue(int32_t aValue, nsCSSUnit aUnit)
389
0
{
390
0
  MOZ_ASSERT(aUnit == eCSSUnit_Integer || aUnit == eCSSUnit_Enumerated,
391
0
             "not an int value");
392
0
  Reset();
393
0
  if (aUnit == eCSSUnit_Integer || aUnit == eCSSUnit_Enumerated) {
394
0
    mUnit = aUnit;
395
0
    mValue.mInt = aValue;
396
0
  }
397
0
}
398
399
void nsCSSValue::SetPercentValue(float aValue)
400
0
{
401
0
  Reset();
402
0
  mUnit = eCSSUnit_Percent;
403
0
  mValue.mFloat = aValue;
404
0
  MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
405
0
}
406
407
void nsCSSValue::SetFloatValue(float aValue, nsCSSUnit aUnit)
408
0
{
409
0
  MOZ_ASSERT(IsFloatUnit(aUnit), "not a float value");
410
0
  Reset();
411
0
  if (IsFloatUnit(aUnit)) {
412
0
    mUnit = aUnit;
413
0
    mValue.mFloat = aValue;
414
0
    MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
415
0
  }
416
0
}
417
418
void nsCSSValue::SetStringValue(const nsString& aValue,
419
                                nsCSSUnit aUnit)
420
0
{
421
0
  Reset();
422
0
  mUnit = aUnit;
423
0
  MOZ_ASSERT(UnitHasStringValue(), "not a string unit");
424
0
  if (UnitHasStringValue()) {
425
0
    mValue.mString = BufferFromString(aValue).take();
426
0
  } else
427
0
    mUnit = eCSSUnit_Null;
428
0
}
429
430
void
431
nsCSSValue::SetAtomIdentValue(already_AddRefed<nsAtom> aValue)
432
0
{
433
0
  Reset();
434
0
  mUnit = eCSSUnit_AtomIdent;
435
0
  mValue.mAtom = aValue.take();
436
0
}
437
438
void nsCSSValue::SetIntegerCoordValue(nscoord aValue)
439
0
{
440
0
  SetFloatValue(nsPresContext::AppUnitsToFloatCSSPixels(aValue),
441
0
                eCSSUnit_Pixel);
442
0
}
443
444
void nsCSSValue::SetArrayValue(nsCSSValue::Array* aValue, nsCSSUnit aUnit)
445
0
{
446
0
  Reset();
447
0
  mUnit = aUnit;
448
0
  MOZ_ASSERT(UnitHasArrayValue(), "bad unit");
449
0
  mValue.mArray = aValue;
450
0
  mValue.mArray->AddRef();
451
0
}
452
453
void nsCSSValue::SetURLValue(mozilla::css::URLValue* aValue)
454
0
{
455
0
  Reset();
456
0
  mUnit = eCSSUnit_URL;
457
0
  mValue.mURL = aValue;
458
0
  mValue.mURL->AddRef();
459
0
}
460
461
void nsCSSValue::SetGridTemplateAreas(mozilla::css::GridTemplateAreasValue* aValue)
462
0
{
463
0
  Reset();
464
0
  mUnit = eCSSUnit_GridTemplateAreas;
465
0
  mValue.mGridTemplateAreas = aValue;
466
0
  mValue.mGridTemplateAreas->AddRef();
467
0
}
468
469
void nsCSSValue::SetFontFamilyListValue(already_AddRefed<SharedFontList> aValue)
470
0
{
471
0
  Reset();
472
0
  mUnit = eCSSUnit_FontFamilyList;
473
0
  mValue.mFontFamilyList = aValue.take();
474
0
}
475
476
void nsCSSValue::SetFontStretch(FontStretch aStretch)
477
0
{
478
0
  Reset();
479
0
  mUnit = eCSSUnit_FontStretch;
480
0
  mValue.mFontStretch = aStretch;
481
0
}
482
483
void nsCSSValue::SetFontSlantStyle(FontSlantStyle aStyle)
484
0
{
485
0
  Reset();
486
0
  mUnit = eCSSUnit_FontSlantStyle;
487
0
  mValue.mFontSlantStyle = aStyle;
488
0
}
489
490
void nsCSSValue::SetFontWeight(FontWeight aWeight)
491
0
{
492
0
  Reset();
493
0
  mUnit = eCSSUnit_FontWeight;
494
0
  mValue.mFontWeight = aWeight;
495
0
}
496
497
void nsCSSValue::SetPairValue(const nsCSSValuePair* aValue)
498
0
{
499
0
  // pairs should not be used for null/inherit/initial values
500
0
  MOZ_ASSERT(aValue &&
501
0
             aValue->mXValue.GetUnit() != eCSSUnit_Null &&
502
0
             aValue->mYValue.GetUnit() != eCSSUnit_Null &&
503
0
             aValue->mXValue.GetUnit() != eCSSUnit_Inherit &&
504
0
             aValue->mYValue.GetUnit() != eCSSUnit_Inherit &&
505
0
             aValue->mXValue.GetUnit() != eCSSUnit_Initial &&
506
0
             aValue->mYValue.GetUnit() != eCSSUnit_Initial &&
507
0
             aValue->mXValue.GetUnit() != eCSSUnit_Unset &&
508
0
             aValue->mYValue.GetUnit() != eCSSUnit_Unset,
509
0
             "missing or inappropriate pair value");
510
0
  Reset();
511
0
  mUnit = eCSSUnit_Pair;
512
0
  mValue.mPair = new nsCSSValuePair_heap(aValue->mXValue, aValue->mYValue);
513
0
  mValue.mPair->AddRef();
514
0
}
515
516
void nsCSSValue::SetPairValue(const nsCSSValue& xValue,
517
                              const nsCSSValue& yValue)
518
0
{
519
0
  MOZ_ASSERT(xValue.GetUnit() != eCSSUnit_Null &&
520
0
             yValue.GetUnit() != eCSSUnit_Null &&
521
0
             xValue.GetUnit() != eCSSUnit_Inherit &&
522
0
             yValue.GetUnit() != eCSSUnit_Inherit &&
523
0
             xValue.GetUnit() != eCSSUnit_Initial &&
524
0
             yValue.GetUnit() != eCSSUnit_Initial &&
525
0
             xValue.GetUnit() != eCSSUnit_Unset &&
526
0
             yValue.GetUnit() != eCSSUnit_Unset,
527
0
             "inappropriate pair value");
528
0
  Reset();
529
0
  mUnit = eCSSUnit_Pair;
530
0
  mValue.mPair = new nsCSSValuePair_heap(xValue, yValue);
531
0
  mValue.mPair->AddRef();
532
0
}
533
534
nsCSSValueList* nsCSSValue::SetListValue()
535
0
{
536
0
  Reset();
537
0
  mUnit = eCSSUnit_List;
538
0
  mValue.mList = new nsCSSValueList_heap;
539
0
  mValue.mList->AddRef();
540
0
  return mValue.mList;
541
0
}
542
543
void nsCSSValue::SetSharedListValue(nsCSSValueSharedList* aList)
544
0
{
545
0
  Reset();
546
0
  mUnit = eCSSUnit_SharedList;
547
0
  mValue.mSharedList = aList;
548
0
  mValue.mSharedList->AddRef();
549
0
}
550
551
void nsCSSValue::SetDependentListValue(nsCSSValueList* aList)
552
0
{
553
0
  Reset();
554
0
  if (aList) {
555
0
    mUnit = eCSSUnit_ListDep;
556
0
    mValue.mListDependent = aList;
557
0
  }
558
0
}
559
560
void
561
nsCSSValue::AdoptListValue(UniquePtr<nsCSSValueList> aValue)
562
0
{
563
0
  // We have to copy the first element since for owned lists the first
564
0
  // element should be an nsCSSValueList_heap object.
565
0
  SetListValue();
566
0
  mValue.mList->mValue = std::move(aValue->mValue);
567
0
  mValue.mList->mNext  = aValue->mNext;
568
0
  aValue->mNext = nullptr;
569
0
  aValue.reset();
570
0
}
571
572
nsCSSValuePairList* nsCSSValue::SetPairListValue()
573
0
{
574
0
  Reset();
575
0
  mUnit = eCSSUnit_PairList;
576
0
  mValue.mPairList = new nsCSSValuePairList_heap;
577
0
  mValue.mPairList->AddRef();
578
0
  return mValue.mPairList;
579
0
}
580
581
void nsCSSValue::SetDependentPairListValue(nsCSSValuePairList* aList)
582
0
{
583
0
  Reset();
584
0
  if (aList) {
585
0
    mUnit = eCSSUnit_PairListDep;
586
0
    mValue.mPairListDependent = aList;
587
0
  }
588
0
}
589
590
void
591
nsCSSValue::AdoptPairListValue(UniquePtr<nsCSSValuePairList> aValue)
592
0
{
593
0
  // We have to copy the first element, since for owned pair lists, the first
594
0
  // element should be an nsCSSValuePairList_heap object.
595
0
  SetPairListValue();
596
0
  mValue.mPairList->mXValue = std::move(aValue->mXValue);
597
0
  mValue.mPairList->mYValue = std::move(aValue->mYValue);
598
0
  mValue.mPairList->mNext   = aValue->mNext;
599
0
  aValue->mNext = nullptr;
600
0
  aValue.reset();
601
0
}
602
603
void nsCSSValue::SetAutoValue()
604
0
{
605
0
  Reset();
606
0
  mUnit = eCSSUnit_Auto;
607
0
}
608
609
void nsCSSValue::SetInheritValue()
610
0
{
611
0
  Reset();
612
0
  mUnit = eCSSUnit_Inherit;
613
0
}
614
615
void nsCSSValue::SetInitialValue()
616
0
{
617
0
  Reset();
618
0
  mUnit = eCSSUnit_Initial;
619
0
}
620
621
void nsCSSValue::SetUnsetValue()
622
0
{
623
0
  Reset();
624
0
  mUnit = eCSSUnit_Unset;
625
0
}
626
627
void nsCSSValue::SetNoneValue()
628
0
{
629
0
  Reset();
630
0
  mUnit = eCSSUnit_None;
631
0
}
632
633
void nsCSSValue::SetAllValue()
634
0
{
635
0
  Reset();
636
0
  mUnit = eCSSUnit_All;
637
0
}
638
639
void nsCSSValue::SetNormalValue()
640
0
{
641
0
  Reset();
642
0
  mUnit = eCSSUnit_Normal;
643
0
}
644
645
void nsCSSValue::SetSystemFontValue()
646
0
{
647
0
  Reset();
648
0
  mUnit = eCSSUnit_System_Font;
649
0
}
650
651
void nsCSSValue::SetDummyValue()
652
0
{
653
0
  Reset();
654
0
  mUnit = eCSSUnit_Dummy;
655
0
}
656
657
void nsCSSValue::SetDummyInheritValue()
658
0
{
659
0
  Reset();
660
0
  mUnit = eCSSUnit_DummyInherit;
661
0
}
662
663
void nsCSSValue::SetCalcValue(const nsStyleCoord::CalcValue* aCalc)
664
0
{
665
0
  RefPtr<nsCSSValue::Array> arr = nsCSSValue::Array::Create(1);
666
0
  if (!aCalc->mHasPercent) {
667
0
    arr->Item(0).SetIntegerCoordValue(aCalc->mLength);
668
0
  } else {
669
0
    nsCSSValue::Array *arr2 = nsCSSValue::Array::Create(2);
670
0
    arr->Item(0).SetArrayValue(arr2, eCSSUnit_Calc_Plus);
671
0
    arr2->Item(0).SetIntegerCoordValue(aCalc->mLength);
672
0
    arr2->Item(1).SetPercentValue(aCalc->mPercent);
673
0
  }
674
0
675
0
  SetArrayValue(arr, eCSSUnit_Calc);
676
0
}
677
678
nsStyleCoord::CalcValue
679
nsCSSValue::GetCalcValue() const
680
0
{
681
0
  MOZ_ASSERT(mUnit == eCSSUnit_Calc,
682
0
             "The unit should be eCSSUnit_Calc");
683
0
684
0
  const nsCSSValue::Array* array = GetArrayValue();
685
0
  MOZ_ASSERT(array->Count() == 1,
686
0
             "There should be a 1-length array");
687
0
688
0
  const nsCSSValue& rootValue = array->Item(0);
689
0
690
0
  nsStyleCoord::CalcValue result;
691
0
692
0
  if (rootValue.GetUnit() == eCSSUnit_Pixel) {
693
0
    result.mLength = rootValue.GetPixelLength();
694
0
    result.mPercent = 0.0f;
695
0
    result.mHasPercent = false;
696
0
  } else {
697
0
    MOZ_ASSERT(rootValue.GetUnit() == eCSSUnit_Calc_Plus,
698
0
               "Calc unit should be eCSSUnit_Calc_Plus");
699
0
700
0
    const nsCSSValue::Array *calcPlusArray = rootValue.GetArrayValue();
701
0
    MOZ_ASSERT(calcPlusArray->Count() == 2,
702
0
               "eCSSUnit_Calc_Plus should have a 2-length array");
703
0
704
0
    const nsCSSValue& length = calcPlusArray->Item(0);
705
0
    const nsCSSValue& percent = calcPlusArray->Item(1);
706
0
    MOZ_ASSERT(length.GetUnit() == eCSSUnit_Pixel,
707
0
               "The first value should be eCSSUnit_Pixel");
708
0
    MOZ_ASSERT(percent.GetUnit() == eCSSUnit_Percent,
709
0
               "The first value should be eCSSUnit_Percent");
710
0
    result.mLength = length.GetPixelLength();
711
0
    result.mPercent = percent.GetPercentValue();
712
0
    result.mHasPercent = true;
713
0
  }
714
0
715
0
  return result;
716
0
}
717
718
nsCSSValue::Array*
719
nsCSSValue::InitFunction(nsCSSKeyword aFunctionId, uint32_t aNumArgs)
720
0
{
721
0
  RefPtr<nsCSSValue::Array> func = Array::Create(aNumArgs + 1);
722
0
  func->Item(0).SetIntValue(aFunctionId, eCSSUnit_Enumerated);
723
0
  SetArrayValue(func, eCSSUnit_Function);
724
0
  return func;
725
0
}
726
727
bool
728
nsCSSValue::EqualsFunction(nsCSSKeyword aFunctionId) const
729
0
{
730
0
  if (mUnit != eCSSUnit_Function) {
731
0
    return false;
732
0
  }
733
0
734
0
  nsCSSValue::Array* func = mValue.mArray;
735
0
  MOZ_ASSERT(func && func->Count() >= 1 &&
736
0
             func->Item(0).GetUnit() == eCSSUnit_Enumerated,
737
0
             "illegally structured function value");
738
0
739
0
  nsCSSKeyword thisFunctionId = func->Item(0).GetKeywordValue();
740
0
  return thisFunctionId == aFunctionId;
741
0
}
742
743
// static
744
already_AddRefed<nsStringBuffer>
745
nsCSSValue::BufferFromString(const nsString& aValue)
746
0
{
747
0
  RefPtr<nsStringBuffer> buffer = nsStringBuffer::FromString(aValue);
748
0
  if (buffer) {
749
0
    return buffer.forget();
750
0
  }
751
0
752
0
  nsString::size_type length = aValue.Length();
753
0
754
0
  // NOTE: Alloc prouduces a new, already-addref'd (refcnt = 1) buffer.
755
0
  // NOTE: String buffer allocation is currently fallible.
756
0
  size_t sz = (length + 1) * sizeof(char16_t);
757
0
  buffer = nsStringBuffer::Alloc(sz);
758
0
  if (MOZ_UNLIKELY(!buffer)) {
759
0
    NS_ABORT_OOM(sz);
760
0
  }
761
0
762
0
  char16_t* data = static_cast<char16_t*>(buffer->Data());
763
0
  nsCharTraits<char16_t>::copy(data, aValue.get(), length);
764
0
  // Null-terminate.
765
0
  data[length] = 0;
766
0
  return buffer.forget();
767
0
}
768
769
void
770
nsCSSValue::AtomizeIdentValue()
771
0
{
772
0
  MOZ_ASSERT(mUnit == eCSSUnit_Ident);
773
0
  RefPtr<nsAtom> atom = NS_Atomize(GetStringBufferValue());
774
0
  Reset();
775
0
  mUnit = eCSSUnit_AtomIdent;
776
0
  mValue.mAtom = atom.forget().take();
777
0
}
778
779
/* static */ void
780
nsCSSValue::AppendAlignJustifyValueToString(int32_t aValue, nsAString& aResult)
781
0
{
782
0
  auto legacy = aValue & NS_STYLE_ALIGN_LEGACY;
783
0
  if (legacy) {
784
0
    aValue &= ~legacy;
785
0
    aResult.AppendLiteral("legacy");
786
0
    if (!aValue) {
787
0
      return;
788
0
    }
789
0
    aResult.AppendLiteral(" ");
790
0
  }
791
0
  // Don't serialize the 'unsafe' keyword; it's the default.
792
0
  auto overflowPos = aValue & (NS_STYLE_ALIGN_SAFE | NS_STYLE_ALIGN_UNSAFE);
793
0
  if (MOZ_UNLIKELY(overflowPos == NS_STYLE_ALIGN_SAFE)) {
794
0
    aResult.AppendLiteral("safe ");
795
0
  }
796
0
  aValue &= ~overflowPos;
797
0
  MOZ_ASSERT(!(aValue & NS_STYLE_ALIGN_FLAG_BITS),
798
0
             "unknown bits in align/justify value");
799
0
  MOZ_ASSERT((aValue != NS_STYLE_ALIGN_AUTO &&
800
0
              aValue != NS_STYLE_ALIGN_NORMAL &&
801
0
              aValue != NS_STYLE_ALIGN_BASELINE &&
802
0
              aValue != NS_STYLE_ALIGN_LAST_BASELINE) ||
803
0
             (!legacy && !overflowPos),
804
0
             "auto/normal/baseline/'last baseline' never have any flags");
805
0
  MOZ_ASSERT(legacy == 0 || overflowPos == 0,
806
0
             "'legacy' together with <overflow-position>");
807
0
  if (aValue == NS_STYLE_ALIGN_LAST_BASELINE) {
808
0
    aResult.AppendLiteral("last ");
809
0
    aValue = NS_STYLE_ALIGN_BASELINE;
810
0
  }
811
0
  const auto& kwtable(nsCSSProps::kAlignAllKeywords);
812
0
  AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(aValue, kwtable), aResult);
813
0
}
814
815
size_t
816
nsCSSValue::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
817
0
{
818
0
  size_t n = 0;
819
0
820
0
  switch (GetUnit()) {
821
0
    // No value: nothing extra to measure.
822
0
    case eCSSUnit_Null:
823
0
    case eCSSUnit_Auto:
824
0
    case eCSSUnit_Inherit:
825
0
    case eCSSUnit_Initial:
826
0
    case eCSSUnit_Unset:
827
0
    case eCSSUnit_None:
828
0
    case eCSSUnit_Normal:
829
0
    case eCSSUnit_System_Font:
830
0
    case eCSSUnit_All:
831
0
    case eCSSUnit_Dummy:
832
0
    case eCSSUnit_DummyInherit:
833
0
      break;
834
0
835
0
    // String
836
0
    case eCSSUnit_String:
837
0
    case eCSSUnit_Ident:
838
0
    case eCSSUnit_Attr:
839
0
    case eCSSUnit_Local_Font:
840
0
    case eCSSUnit_Font_Format:
841
0
    case eCSSUnit_Element:
842
0
      n += mValue.mString->SizeOfIncludingThisIfUnshared(aMallocSizeOf);
843
0
      break;
844
0
845
0
    // Array
846
0
    case eCSSUnit_Array:
847
0
    case eCSSUnit_Counter:
848
0
    case eCSSUnit_Counters:
849
0
    case eCSSUnit_Cubic_Bezier:
850
0
    case eCSSUnit_Steps:
851
0
    case eCSSUnit_Symbols:
852
0
    case eCSSUnit_Function:
853
0
    case eCSSUnit_Calc:
854
0
    case eCSSUnit_Calc_Plus:
855
0
    case eCSSUnit_Calc_Minus:
856
0
    case eCSSUnit_Calc_Times_L:
857
0
    case eCSSUnit_Calc_Times_R:
858
0
    case eCSSUnit_Calc_Divided:
859
0
      break;
860
0
861
0
    // URL
862
0
    case eCSSUnit_URL:
863
0
      n += mValue.mURL->SizeOfIncludingThis(aMallocSizeOf);
864
0
      break;
865
0
866
0
    // Pair
867
0
    case eCSSUnit_Pair:
868
0
      n += mValue.mPair->SizeOfIncludingThis(aMallocSizeOf);
869
0
      break;
870
0
871
0
    // List
872
0
    case eCSSUnit_List:
873
0
      n += mValue.mList->SizeOfIncludingThis(aMallocSizeOf);
874
0
      break;
875
0
876
0
    // ListDep: not measured because it's non-owning.
877
0
    case eCSSUnit_ListDep:
878
0
      break;
879
0
880
0
    // SharedList
881
0
    case eCSSUnit_SharedList:
882
0
      // Makes more sense not to measure, since it most cases the list
883
0
      // will be shared.
884
0
      break;
885
0
886
0
    // PairList
887
0
    case eCSSUnit_PairList:
888
0
      n += mValue.mPairList->SizeOfIncludingThis(aMallocSizeOf);
889
0
      break;
890
0
891
0
    // PairListDep: not measured because it's non-owning.
892
0
    case eCSSUnit_PairListDep:
893
0
      break;
894
0
895
0
    // GridTemplateAreas
896
0
    case eCSSUnit_GridTemplateAreas:
897
0
      n += mValue.mGridTemplateAreas->SizeOfIncludingThis(aMallocSizeOf);
898
0
      break;
899
0
900
0
    case eCSSUnit_FontFamilyList:
901
0
      // The SharedFontList is a refcounted object, but is unique per
902
0
      // declaration. We don't measure the references from computed
903
0
      // values.
904
0
      n += mValue.mFontFamilyList->SizeOfIncludingThis(aMallocSizeOf);
905
0
      break;
906
0
907
0
    // Atom is always shared, and thus should not be counted.
908
0
    case eCSSUnit_AtomIdent:
909
0
      break;
910
0
911
0
    // Int: nothing extra to measure.
912
0
    case eCSSUnit_Integer:
913
0
    case eCSSUnit_Enumerated:
914
0
    case eCSSUnit_FontStretch:
915
0
    case eCSSUnit_FontSlantStyle:
916
0
    case eCSSUnit_FontWeight:
917
0
      break;
918
0
919
0
    // Float: nothing extra to measure.
920
0
    case eCSSUnit_Percent:
921
0
    case eCSSUnit_Number:
922
0
    case eCSSUnit_ViewportWidth:
923
0
    case eCSSUnit_ViewportHeight:
924
0
    case eCSSUnit_ViewportMin:
925
0
    case eCSSUnit_ViewportMax:
926
0
    case eCSSUnit_EM:
927
0
    case eCSSUnit_XHeight:
928
0
    case eCSSUnit_Char:
929
0
    case eCSSUnit_RootEM:
930
0
    case eCSSUnit_Point:
931
0
    case eCSSUnit_Inch:
932
0
    case eCSSUnit_Millimeter:
933
0
    case eCSSUnit_Centimeter:
934
0
    case eCSSUnit_Pica:
935
0
    case eCSSUnit_Pixel:
936
0
    case eCSSUnit_Quarter:
937
0
    case eCSSUnit_Degree:
938
0
    case eCSSUnit_Grad:
939
0
    case eCSSUnit_Turn:
940
0
    case eCSSUnit_Radian:
941
0
    case eCSSUnit_Hertz:
942
0
    case eCSSUnit_Kilohertz:
943
0
    case eCSSUnit_Seconds:
944
0
    case eCSSUnit_Milliseconds:
945
0
    case eCSSUnit_FlexFraction:
946
0
      break;
947
0
948
0
    default:
949
0
      MOZ_ASSERT(false, "bad nsCSSUnit");
950
0
      break;
951
0
  }
952
0
953
0
  return n;
954
0
}
955
956
// --- nsCSSValueList -----------------
957
958
nsCSSValueList::~nsCSSValueList()
959
0
{
960
0
  MOZ_COUNT_DTOR(nsCSSValueList);
961
0
  NS_CSS_DELETE_LIST_MEMBER(nsCSSValueList, this, mNext);
962
0
}
963
964
nsCSSValueList*
965
nsCSSValueList::Clone() const
966
0
{
967
0
  nsCSSValueList* result = new nsCSSValueList(*this);
968
0
  nsCSSValueList* dest = result;
969
0
  const nsCSSValueList* src = this->mNext;
970
0
  while (src) {
971
0
    dest->mNext = new nsCSSValueList(*src);
972
0
    dest = dest->mNext;
973
0
    src = src->mNext;
974
0
  }
975
0
976
0
  MOZ_ASSERT(result, "shouldn't return null; supposed to be infallible");
977
0
  return result;
978
0
}
979
980
void
981
nsCSSValueList::CloneInto(nsCSSValueList* aList) const
982
0
{
983
0
  NS_ASSERTION(!aList->mNext, "Must be an empty list!");
984
0
  aList->mValue = mValue;
985
0
  aList->mNext = mNext ? mNext->Clone() : nullptr;
986
0
}
987
988
/* static */ bool
989
nsCSSValueList::Equal(const nsCSSValueList* aList1,
990
                      const nsCSSValueList* aList2)
991
0
{
992
0
  if (aList1 == aList2) {
993
0
    return true;
994
0
  }
995
0
996
0
  const nsCSSValueList *p1 = aList1, *p2 = aList2;
997
0
  for ( ; p1 && p2; p1 = p1->mNext, p2 = p2->mNext) {
998
0
    if (p1->mValue != p2->mValue)
999
0
      return false;
1000
0
  }
1001
0
  return !p1 && !p2; // true if same length, false otherwise
1002
0
}
1003
1004
size_t
1005
nsCSSValueList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
1006
0
{
1007
0
  size_t n = 0;
1008
0
  const nsCSSValueList* v = this;
1009
0
  while (v) {
1010
0
    n += aMallocSizeOf(v);
1011
0
    n += v->mValue.SizeOfExcludingThis(aMallocSizeOf);
1012
0
    v = v->mNext;
1013
0
  }
1014
0
  return n;
1015
0
}
1016
1017
size_t
1018
nsCSSValueList_heap::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
1019
0
{
1020
0
  // Only measure it if it's unshared, to avoid double-counting.
1021
0
  size_t n = 0;
1022
0
  if (mRefCnt <= 1) {
1023
0
    n += aMallocSizeOf(this);
1024
0
    n += mValue.SizeOfExcludingThis(aMallocSizeOf);
1025
0
    n += mNext ? mNext->SizeOfIncludingThis(aMallocSizeOf) : 0;
1026
0
  }
1027
0
  return n;
1028
0
}
1029
1030
// --- nsCSSValueSharedList -----------------
1031
1032
nsCSSValueSharedList::~nsCSSValueSharedList()
1033
0
{
1034
0
  if (mHead) {
1035
0
    NS_CSS_DELETE_LIST_MEMBER(nsCSSValueList, mHead, mNext);
1036
0
    delete mHead;
1037
0
  }
1038
0
}
1039
1040
bool
1041
nsCSSValueSharedList::operator==(const nsCSSValueSharedList& aOther) const
1042
0
{
1043
0
  return nsCSSValueList::Equal(mHead, aOther.mHead);
1044
0
}
1045
1046
size_t
1047
nsCSSValueSharedList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
1048
0
{
1049
0
  // Only measure it if it's unshared, to avoid double-counting.
1050
0
  size_t n = 0;
1051
0
  if (mRefCnt <= 1) {
1052
0
    n += aMallocSizeOf(this);
1053
0
    n += mHead->SizeOfIncludingThis(aMallocSizeOf);
1054
0
  }
1055
0
  return n;
1056
0
}
1057
1058
// --- nsCSSValuePair -----------------
1059
1060
size_t
1061
nsCSSValuePair::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
1062
0
{
1063
0
  size_t n = 0;
1064
0
  n += mXValue.SizeOfExcludingThis(aMallocSizeOf);
1065
0
  n += mYValue.SizeOfExcludingThis(aMallocSizeOf);
1066
0
  return n;
1067
0
}
1068
1069
size_t
1070
nsCSSValuePair_heap::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
1071
0
{
1072
0
  // Only measure it if it's unshared, to avoid double-counting.
1073
0
  size_t n = 0;
1074
0
  if (mRefCnt <= 1) {
1075
0
    n += aMallocSizeOf(this);
1076
0
    n += mXValue.SizeOfExcludingThis(aMallocSizeOf);
1077
0
    n += mYValue.SizeOfExcludingThis(aMallocSizeOf);
1078
0
  }
1079
0
  return n;
1080
0
}
1081
1082
// --- nsCSSValuePairList -----------------
1083
1084
nsCSSValuePairList::~nsCSSValuePairList()
1085
0
{
1086
0
  MOZ_COUNT_DTOR(nsCSSValuePairList);
1087
0
  NS_CSS_DELETE_LIST_MEMBER(nsCSSValuePairList, this, mNext);
1088
0
}
1089
1090
nsCSSValuePairList*
1091
nsCSSValuePairList::Clone() const
1092
0
{
1093
0
  nsCSSValuePairList* result = new nsCSSValuePairList(*this);
1094
0
  nsCSSValuePairList* dest = result;
1095
0
  const nsCSSValuePairList* src = this->mNext;
1096
0
  while (src) {
1097
0
    dest->mNext = new nsCSSValuePairList(*src);
1098
0
    dest = dest->mNext;
1099
0
    src = src->mNext;
1100
0
  }
1101
0
1102
0
  MOZ_ASSERT(result, "shouldn't return null; supposed to be infallible");
1103
0
  return result;
1104
0
}
1105
1106
/* static */ bool
1107
nsCSSValuePairList::Equal(const nsCSSValuePairList* aList1,
1108
                          const nsCSSValuePairList* aList2)
1109
0
{
1110
0
  if (aList1 == aList2) {
1111
0
    return true;
1112
0
  }
1113
0
1114
0
  const nsCSSValuePairList *p1 = aList1, *p2 = aList2;
1115
0
  for ( ; p1 && p2; p1 = p1->mNext, p2 = p2->mNext) {
1116
0
    if (p1->mXValue != p2->mXValue ||
1117
0
        p1->mYValue != p2->mYValue)
1118
0
      return false;
1119
0
  }
1120
0
  return !p1 && !p2; // true if same length, false otherwise
1121
0
}
1122
1123
size_t
1124
nsCSSValuePairList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
1125
0
{
1126
0
  size_t n = 0;
1127
0
  const nsCSSValuePairList* v = this;
1128
0
  while (v) {
1129
0
    n += aMallocSizeOf(v);
1130
0
    n += v->mXValue.SizeOfExcludingThis(aMallocSizeOf);
1131
0
    n += v->mYValue.SizeOfExcludingThis(aMallocSizeOf);
1132
0
    v = v->mNext;
1133
0
  }
1134
0
  return n;
1135
0
}
1136
1137
size_t
1138
nsCSSValuePairList_heap::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
1139
0
{
1140
0
  // Only measure it if it's unshared, to avoid double-counting.
1141
0
  size_t n = 0;
1142
0
  if (mRefCnt <= 1) {
1143
0
    n += aMallocSizeOf(this);
1144
0
    n += mXValue.SizeOfExcludingThis(aMallocSizeOf);
1145
0
    n += mYValue.SizeOfExcludingThis(aMallocSizeOf);
1146
0
    n += mNext ? mNext->SizeOfIncludingThis(aMallocSizeOf) : 0;
1147
0
  }
1148
0
  return n;
1149
0
}
1150
1151
size_t
1152
nsCSSValue::Array::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
1153
0
{
1154
0
  size_t n = aMallocSizeOf(this);
1155
0
  for (size_t i = 0; i < mCount; i++) {
1156
0
    n += mArray[i].SizeOfExcludingThis(aMallocSizeOf);
1157
0
  }
1158
0
  return n;
1159
0
}
1160
1161
css::URLValueData::URLValueData(already_AddRefed<nsIURI> aURI,
1162
                                ServoRawOffsetArc<RustString> aString,
1163
                                already_AddRefed<URLExtraData> aExtraData,
1164
                                CORSMode aCORSMode)
1165
  : mURI(std::move(aURI))
1166
  , mExtraData(std::move(aExtraData))
1167
  , mURIResolved(true)
1168
  , mString(aString)
1169
  , mCORSMode(aCORSMode)
1170
0
{
1171
0
  MOZ_ASSERT(mExtraData);
1172
0
  MOZ_ASSERT(mExtraData->GetPrincipal());
1173
0
}
1174
1175
css::URLValueData::URLValueData(ServoRawOffsetArc<RustString> aString,
1176
                                already_AddRefed<URLExtraData> aExtraData,
1177
                                CORSMode aCORSMode)
1178
  : mExtraData(std::move(aExtraData))
1179
  , mURIResolved(false)
1180
  , mString(aString)
1181
  , mCORSMode(aCORSMode)
1182
0
{
1183
0
  MOZ_ASSERT(mExtraData);
1184
0
  MOZ_ASSERT(mExtraData->GetPrincipal());
1185
0
}
1186
1187
css::URLValueData::~URLValueData()
1188
0
{
1189
0
  Servo_ReleaseArcStringData(&mString);
1190
0
}
1191
1192
bool
1193
css::URLValueData::Equals(const URLValueData& aOther) const
1194
0
{
1195
0
  MOZ_ASSERT(NS_IsMainThread());
1196
0
1197
0
  bool eq;
1198
0
  const URLExtraData* self = mExtraData;
1199
0
  const URLExtraData* other = aOther.mExtraData;
1200
0
  return GetString() == aOther.GetString() &&
1201
0
          (GetURI() == aOther.GetURI() || // handles null == null
1202
0
           (mURI && aOther.mURI &&
1203
0
            NS_SUCCEEDED(mURI->Equals(aOther.mURI, &eq)) &&
1204
0
            eq)) &&
1205
0
          (self->BaseURI() == other->BaseURI() ||
1206
0
           (NS_SUCCEEDED(self->BaseURI()->Equals(other->BaseURI(), &eq)) &&
1207
0
            eq)) &&
1208
0
          (self->GetPrincipal() == other->GetPrincipal() ||
1209
0
           self->GetPrincipal()->Equals(other->GetPrincipal())) &&
1210
0
          IsLocalRef() == aOther.IsLocalRef();
1211
0
}
1212
1213
bool
1214
css::URLValueData::DefinitelyEqualURIs(const URLValueData& aOther) const
1215
0
{
1216
0
  if (mExtraData->BaseURI() != aOther.mExtraData->BaseURI()) {
1217
0
    return false;
1218
0
  }
1219
0
  return GetString() == aOther.GetString();
1220
0
}
1221
1222
bool
1223
css::URLValueData::DefinitelyEqualURIsAndPrincipal(
1224
    const URLValueData& aOther) const
1225
0
{
1226
0
  return mExtraData->GetPrincipal() == aOther.mExtraData->GetPrincipal() &&
1227
0
         DefinitelyEqualURIs(aOther);
1228
0
}
1229
1230
nsDependentCSubstring
1231
css::URLValueData::GetString() const
1232
0
{
1233
0
  const uint8_t* chars;
1234
0
  uint32_t len;
1235
0
  Servo_GetArcStringData(mString.mPtr, &chars, &len);
1236
0
  return nsDependentCSubstring(reinterpret_cast<const char*>(chars), len);
1237
0
}
1238
1239
nsIURI*
1240
css::URLValueData::GetURI() const
1241
0
{
1242
0
  MOZ_ASSERT(NS_IsMainThread());
1243
0
1244
0
  if (!mURIResolved) {
1245
0
    MOZ_ASSERT(!mURI);
1246
0
    nsCOMPtr<nsIURI> newURI;
1247
0
    NS_NewURI(getter_AddRefs(newURI),
1248
0
              GetString(),
1249
0
              nullptr, mExtraData->BaseURI());
1250
0
    mURI = newURI.forget();
1251
0
    mURIResolved = true;
1252
0
  }
1253
0
1254
0
  return mURI;
1255
0
}
1256
1257
bool
1258
css::URLValueData::IsLocalRef() const
1259
0
{
1260
0
  if (mIsLocalRef.isNothing()) {
1261
0
    // IsLocalRefURL is O(N), use it only when IsLocalRef is called.
1262
0
    mIsLocalRef.emplace(nsContentUtils::IsLocalRefURL(GetString()));
1263
0
  }
1264
0
  return mIsLocalRef.value();
1265
0
}
1266
1267
bool
1268
css::URLValueData::HasRef() const
1269
0
{
1270
0
  bool result = false;
1271
0
1272
0
  if (IsLocalRef()) {
1273
0
    result = true;
1274
0
  } else {
1275
0
    if (nsIURI* uri = GetURI()) {
1276
0
      nsAutoCString ref;
1277
0
      nsresult rv = uri->GetRef(ref);
1278
0
      if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
1279
0
        result = true;
1280
0
      }
1281
0
    }
1282
0
  }
1283
0
1284
0
  mMightHaveRef = Some(result);
1285
0
1286
0
  return result;
1287
0
}
1288
1289
bool
1290
css::URLValueData::MightHaveRef() const
1291
0
{
1292
0
  if (mMightHaveRef.isNothing()) {
1293
0
    bool result = ::MightHaveRef(GetString());
1294
0
    if (!ServoStyleSet::IsInServoTraversal()) {
1295
0
      // Can only cache the result if we're not on a style worker thread.
1296
0
      mMightHaveRef.emplace(result);
1297
0
    }
1298
0
    return result;
1299
0
  }
1300
0
1301
0
  return mMightHaveRef.value();
1302
0
}
1303
1304
already_AddRefed<nsIURI>
1305
css::URLValueData::ResolveLocalRef(nsIURI* aURI) const
1306
0
{
1307
0
  nsCOMPtr<nsIURI> result = GetURI();
1308
0
1309
0
  if (result && IsLocalRef()) {
1310
0
    nsCString ref;
1311
0
    mURI->GetRef(ref);
1312
0
1313
0
    nsresult rv = NS_MutateURI(aURI)
1314
0
                    .SetRef(ref)
1315
0
                    .Finalize(result);
1316
0
1317
0
    if (NS_FAILED(rv)) {
1318
0
      // If setting the ref failed, just return the original URI.
1319
0
      result = aURI;
1320
0
    }
1321
0
  }
1322
0
1323
0
  return result.forget();
1324
0
}
1325
1326
already_AddRefed<nsIURI>
1327
css::URLValueData::ResolveLocalRef(nsIContent* aContent) const
1328
0
{
1329
0
  nsCOMPtr<nsIURI> url = aContent->GetBaseURI();
1330
0
  return ResolveLocalRef(url);
1331
0
}
1332
1333
void
1334
css::URLValueData::GetSourceString(nsString& aRef) const
1335
0
{
1336
0
  nsIURI* uri = GetURI();
1337
0
  if (!uri) {
1338
0
    aRef.Truncate();
1339
0
    return;
1340
0
  }
1341
0
1342
0
  nsCString cref;
1343
0
  if (IsLocalRef()) {
1344
0
    // XXXheycam It's possible we can just return mString in this case, since
1345
0
    // it should be the "#fragment" string the URLValueData was created with.
1346
0
    uri->GetRef(cref);
1347
0
    cref.Insert('#', 0);
1348
0
  } else {
1349
0
    // It's not entirely clear how to best handle failure here. Ensuring the
1350
0
    // string is empty seems safest.
1351
0
    nsresult rv = uri->GetSpec(cref);
1352
0
    if (NS_FAILED(rv)) {
1353
0
      cref.Truncate();
1354
0
    }
1355
0
  }
1356
0
1357
0
  aRef = NS_ConvertUTF8toUTF16(cref);
1358
0
}
1359
1360
bool
1361
css::URLValueData::EqualsExceptRef(nsIURI* aURI) const
1362
0
{
1363
0
  nsIURI* uri = GetURI();
1364
0
  if (!uri) {
1365
0
    return false;
1366
0
  }
1367
0
1368
0
  bool ret = false;
1369
0
  uri->EqualsExceptRef(aURI, &ret);
1370
0
  return ret;
1371
0
}
1372
1373
size_t
1374
css::URLValueData::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
1375
0
{
1376
0
  // Measurement of the following members may be added later if DMD finds it
1377
0
  // is worthwhile:
1378
0
  // - mURI
1379
0
  // - mString
1380
0
  // - mExtraData
1381
0
  return 0;
1382
0
}
1383
1384
size_t
1385
css::URLValue::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
1386
0
{
1387
0
  // Only measure it if it's unshared, to avoid double-counting.
1388
0
  size_t n = 0;
1389
0
  if (mRefCnt <= 1) {
1390
0
    n += aMallocSizeOf(this);
1391
0
    n += URLValueData::SizeOfExcludingThis(aMallocSizeOf);
1392
0
  }
1393
0
  return n;
1394
0
}
1395
1396
css::ImageValue::ImageValue(nsIURI* aURI,
1397
                            ServoRawOffsetArc<RustString> aString,
1398
                            already_AddRefed<URLExtraData> aExtraData,
1399
                            nsIDocument* aDocument,
1400
                            CORSMode aCORSMode)
1401
  : URLValueData(do_AddRef(aURI), aString, std::move(aExtraData), aCORSMode)
1402
0
{
1403
0
  Initialize(aDocument);
1404
0
}
1405
1406
css::ImageValue::ImageValue(ServoRawOffsetArc<RustString> aString,
1407
                            already_AddRefed<URLExtraData> aExtraData,
1408
                            CORSMode aCORSMode)
1409
  : URLValueData(aString, std::move(aExtraData), aCORSMode)
1410
0
{
1411
0
}
1412
1413
/*static*/ already_AddRefed<css::ImageValue>
1414
css::ImageValue::CreateFromURLValue(URLValue* aUrl,
1415
                                    nsIDocument* aDocument,
1416
                                    CORSMode aCORSMode)
1417
0
{
1418
0
  return do_AddRef(
1419
0
    new css::ImageValue(aUrl->GetURI(),
1420
0
                        Servo_CloneArcStringData(&aUrl->mString),
1421
0
                        do_AddRef(aUrl->mExtraData),
1422
0
                        aDocument,
1423
0
                        aCORSMode));
1424
0
}
1425
1426
void
1427
css::ImageValue::Initialize(nsIDocument* aDocument)
1428
0
{
1429
0
  MOZ_ASSERT(NS_IsMainThread());
1430
0
1431
0
  // NB: If aDocument is not the original document, we may not be able to load
1432
0
  // images from aDocument.  Instead we do the image load from the original doc
1433
0
  // and clone it to aDocument.
1434
0
  nsIDocument* loadingDoc = aDocument->GetOriginalDocument();
1435
0
  if (!loadingDoc) {
1436
0
    loadingDoc = aDocument;
1437
0
  }
1438
0
1439
0
  if (!mLoadedImage) {
1440
0
    loadingDoc->StyleImageLoader()->LoadImage(GetURI(),
1441
0
                                              mExtraData->GetPrincipal(),
1442
0
                                              mExtraData->GetReferrer(),
1443
0
                                              mExtraData->GetReferrerPolicy(),
1444
0
                                              this,
1445
0
                                              mCORSMode);
1446
0
1447
0
    mLoadedImage = true;
1448
0
  }
1449
0
1450
0
  aDocument->StyleImageLoader()->MaybeRegisterCSSImage(this);
1451
0
}
1452
1453
css::ImageValue::~ImageValue()
1454
0
{
1455
0
  MOZ_ASSERT(NS_IsMainThread() || mRequests.Count() == 0,
1456
0
             "Destructor should run on main thread, or on non-main thread "
1457
0
             "when mRequest is empty!");
1458
0
1459
0
  for (auto iter = mRequests.Iter(); !iter.Done(); iter.Next()) {
1460
0
    nsIDocument* doc = iter.Key();
1461
0
    RefPtr<imgRequestProxy>& proxy = iter.Data();
1462
0
1463
0
    if (doc) {
1464
0
      doc->StyleImageLoader()->DeregisterCSSImage(this);
1465
0
    }
1466
0
1467
0
    if (proxy) {
1468
0
      proxy->CancelAndForgetObserver(NS_BINDING_ABORTED);
1469
0
    }
1470
0
1471
0
    iter.Remove();
1472
0
  }
1473
0
}
1474
1475
size_t
1476
css::ImageValue::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
1477
0
{
1478
0
  size_t n = aMallocSizeOf(this);
1479
0
  n += css::URLValueData::SizeOfExcludingThis(aMallocSizeOf);
1480
0
  n += mRequests.ShallowSizeOfExcludingThis(aMallocSizeOf);
1481
0
  return n;
1482
0
}
1483
1484
size_t
1485
mozilla::css::GridTemplateAreasValue::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
1486
0
{
1487
0
  // Only measure it if it's unshared, to avoid double-counting.
1488
0
  size_t n = 0;
1489
0
  if (mRefCnt <= 1) {
1490
0
    n += aMallocSizeOf(this);
1491
0
    n += mNamedAreas.ShallowSizeOfExcludingThis(aMallocSizeOf);
1492
0
    n += mTemplates.ShallowSizeOfExcludingThis(aMallocSizeOf);
1493
0
  }
1494
0
  return n;
1495
0
}