Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dom/bindings/IntlUtilsBinding.cpp
Line
Count
Source (jump to first uncovered line)
1
/* THIS FILE IS AUTOGENERATED FROM IntlUtils.webidl BY Codegen.py - DO NOT EDIT */
2
3
#include "AtomList.h"
4
#include "IntlUtilsBinding.h"
5
#include "WrapperFactory.h"
6
#include "mozilla/OwningNonNull.h"
7
#include "mozilla/dom/BindingUtils.h"
8
#include "mozilla/dom/DOMJSClass.h"
9
#include "mozilla/dom/IntlUtils.h"
10
#include "mozilla/dom/NonRefcountedDOMObject.h"
11
#include "mozilla/dom/ScriptSettings.h"
12
#include "mozilla/dom/SimpleGlobalObject.h"
13
#include "mozilla/dom/XrayExpandoClass.h"
14
15
namespace mozilla {
16
namespace dom {
17
18
namespace binding_detail {}; // Just to make sure it's known as a namespace
19
using namespace mozilla::dom::binding_detail;
20
21
22
23
DisplayNameOptions::DisplayNameOptions()
24
0
{
25
0
  // Safe to pass a null context if we pass a null value
26
0
  Init(nullptr, JS::NullHandleValue);
27
0
}
28
29
30
31
bool
32
DisplayNameOptions::InitIds(JSContext* cx, DisplayNameOptionsAtoms* atomsCache)
33
0
{
34
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
35
0
36
0
  // Initialize these in reverse order so that any failure leaves the first one
37
0
  // uninitialized.
38
0
  if (!atomsCache->style_id.init(cx, "style") ||
39
0
      !atomsCache->keys_id.init(cx, "keys")) {
40
0
    return false;
41
0
  }
42
0
  return true;
43
0
}
44
45
bool
46
DisplayNameOptions::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
47
0
{
48
0
  // Passing a null JSContext is OK only if we're initing from null,
49
0
  // Since in that case we will not have to do any property gets
50
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
51
0
  // checkers by static analysis tools
52
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
53
0
  DisplayNameOptionsAtoms* atomsCache = nullptr;
54
0
  if (cx) {
55
0
    atomsCache = GetAtomCache<DisplayNameOptionsAtoms>(cx);
56
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
57
0
      return false;
58
0
    }
59
0
  }
60
0
61
0
  if (!IsConvertibleToDictionary(val)) {
62
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
63
0
  }
64
0
65
0
  bool isNull = val.isNullOrUndefined();
66
0
  // We only need these if !isNull, in which case we have |cx|.
67
0
  Maybe<JS::Rooted<JSObject *> > object;
68
0
  Maybe<JS::Rooted<JS::Value> > temp;
69
0
  if (!isNull) {
70
0
    MOZ_ASSERT(cx);
71
0
    object.emplace(cx, &val.toObject());
72
0
    temp.emplace(cx);
73
0
  }
74
0
  if (!isNull) {
75
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->keys_id, temp.ptr())) {
76
0
      return false;
77
0
    }
78
0
  }
79
0
  if (!isNull && !temp->isUndefined()) {
80
0
    mKeys.Construct();
81
0
    if (temp.ref().isObject()) {
82
0
      JS::ForOfIterator iter(cx);
83
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
84
0
        return false;
85
0
      }
86
0
      if (!iter.valueIsIterable()) {
87
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'keys' member of DisplayNameOptions");
88
0
        return false;
89
0
      }
90
0
      Sequence<nsString> &arr = (mKeys.Value());
91
0
      JS::Rooted<JS::Value> temp(cx);
92
0
      while (true) {
93
0
        bool done;
94
0
        if (!iter.next(&temp, &done)) {
95
0
          return false;
96
0
        }
97
0
        if (done) {
98
0
          break;
99
0
        }
100
0
        nsString* slotPtr = arr.AppendElement(mozilla::fallible);
101
0
        if (!slotPtr) {
102
0
          JS_ReportOutOfMemory(cx);
103
0
          return false;
104
0
        }
105
0
        nsString& slot = *slotPtr;
106
0
        if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) {
107
0
          return false;
108
0
        }
109
0
      }
110
0
    } else {
111
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'keys' member of DisplayNameOptions");
112
0
      return false;
113
0
    }
114
0
    mIsAnyMemberPresent = true;
115
0
  }
116
0
117
0
  if (!isNull) {
118
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->style_id, temp.ptr())) {
119
0
      return false;
120
0
    }
121
0
  }
122
0
  if (!isNull && !temp->isUndefined()) {
123
0
    mStyle.Construct();
124
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mStyle.Value()))) {
125
0
      return false;
126
0
    }
127
0
    mIsAnyMemberPresent = true;
128
0
  }
129
0
  return true;
130
0
}
131
132
bool
133
DisplayNameOptions::Init(const nsAString& aJSON)
134
0
{
135
0
  AutoJSAPI jsapi;
136
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
137
0
  if (!cleanGlobal) {
138
0
    return false;
139
0
  }
140
0
  if (!jsapi.Init(cleanGlobal)) {
141
0
    return false;
142
0
  }
143
0
  JSContext* cx = jsapi.cx();
144
0
  JS::Rooted<JS::Value> json(cx);
145
0
  bool ok = ParseJSON(cx, aJSON, &json);
146
0
  NS_ENSURE_TRUE(ok, false);
147
0
  return Init(cx, json);
148
0
}
149
150
bool
151
DisplayNameOptions::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
152
0
{
153
0
  DisplayNameOptionsAtoms* atomsCache = GetAtomCache<DisplayNameOptionsAtoms>(cx);
154
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
155
0
    return false;
156
0
  }
157
0
158
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
159
0
  if (!obj) {
160
0
    return false;
161
0
  }
162
0
  rval.set(JS::ObjectValue(*obj));
163
0
164
0
  if (mKeys.WasPassed()) {
165
0
    do {
166
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
167
0
      JS::Rooted<JS::Value> temp(cx);
168
0
      Sequence<nsString> const & currentValue = mKeys.InternalValue();
169
0
170
0
      uint32_t length = currentValue.Length();
171
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
172
0
      if (!returnArray) {
173
0
        return false;
174
0
      }
175
0
      // Scope for 'tmp'
176
0
      {
177
0
        JS::Rooted<JS::Value> tmp(cx);
178
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
179
0
          // Control block to let us common up the JS_DefineElement calls when there
180
0
          // are different ways to succeed at wrapping the object.
181
0
          do {
182
0
            if (!xpc::NonVoidStringToJsval(cx, currentValue[sequenceIdx0], &tmp)) {
183
0
              return false;
184
0
            }
185
0
            break;
186
0
          } while (false);
187
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
188
0
                                JSPROP_ENUMERATE)) {
189
0
            return false;
190
0
          }
191
0
        }
192
0
      }
193
0
      temp.setObject(*returnArray);
194
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->keys_id, temp, JSPROP_ENUMERATE)) {
195
0
        return false;
196
0
      }
197
0
      break;
198
0
    } while(false);
199
0
  }
200
0
201
0
  if (mStyle.WasPassed()) {
202
0
    do {
203
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
204
0
      JS::Rooted<JS::Value> temp(cx);
205
0
      nsString const & currentValue = mStyle.InternalValue();
206
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
207
0
        return false;
208
0
      }
209
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->style_id, temp, JSPROP_ENUMERATE)) {
210
0
        return false;
211
0
      }
212
0
      break;
213
0
    } while(false);
214
0
  }
215
0
216
0
  return true;
217
0
}
218
219
bool
220
DisplayNameOptions::ToJSON(nsAString& aJSON) const
221
0
{
222
0
  AutoJSAPI jsapi;
223
0
  jsapi.Init();
224
0
  JSContext *cx = jsapi.cx();
225
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
226
0
  // because we'll only be creating objects, in ways that have no
227
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
228
0
  // which likewise guarantees no side-effects for the sorts of
229
0
  // things we will pass it.
230
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
231
0
  JS::Rooted<JS::Value> val(cx);
232
0
  if (!ToObjectInternal(cx, &val)) {
233
0
    return false;
234
0
  }
235
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
236
0
  return StringifyToJSON(cx, obj, aJSON);
237
0
}
238
239
void
240
DisplayNameOptions::TraceDictionary(JSTracer* trc)
241
0
{
242
0
}
243
244
DisplayNameOptions&
245
DisplayNameOptions::operator=(const DisplayNameOptions& aOther)
246
0
{
247
0
  DictionaryBase::operator=(aOther);
248
0
  mKeys.Reset();
249
0
  if (aOther.mKeys.WasPassed()) {
250
0
    mKeys.Construct(aOther.mKeys.Value());
251
0
  }
252
0
  mStyle.Reset();
253
0
  if (aOther.mStyle.WasPassed()) {
254
0
    mStyle.Construct(aOther.mStyle.Value());
255
0
  }
256
0
  return *this;
257
0
}
258
259
namespace binding_detail {
260
} // namespace binding_detail
261
262
263
264
DisplayNameResult::DisplayNameResult()
265
0
{
266
0
  // Safe to pass a null context if we pass a null value
267
0
  Init(nullptr, JS::NullHandleValue);
268
0
}
269
270
271
bool
272
DisplayNameResult::InitIds(JSContext* cx, DisplayNameResultAtoms* atomsCache)
273
0
{
274
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
275
0
276
0
  // Initialize these in reverse order so that any failure leaves the first one
277
0
  // uninitialized.
278
0
  if (!atomsCache->values_id.init(cx, "values") ||
279
0
      !atomsCache->style_id.init(cx, "style") ||
280
0
      !atomsCache->locale_id.init(cx, "locale")) {
281
0
    return false;
282
0
  }
283
0
  return true;
284
0
}
285
286
bool
287
DisplayNameResult::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
288
0
{
289
0
  // Passing a null JSContext is OK only if we're initing from null,
290
0
  // Since in that case we will not have to do any property gets
291
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
292
0
  // checkers by static analysis tools
293
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
294
0
  DisplayNameResultAtoms* atomsCache = nullptr;
295
0
  if (cx) {
296
0
    atomsCache = GetAtomCache<DisplayNameResultAtoms>(cx);
297
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
298
0
      return false;
299
0
    }
300
0
  }
301
0
302
0
  if (!IsConvertibleToDictionary(val)) {
303
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
304
0
  }
305
0
306
0
  bool isNull = val.isNullOrUndefined();
307
0
  // We only need these if !isNull, in which case we have |cx|.
308
0
  Maybe<JS::Rooted<JSObject *> > object;
309
0
  Maybe<JS::Rooted<JS::Value> > temp;
310
0
  if (!isNull) {
311
0
    MOZ_ASSERT(cx);
312
0
    object.emplace(cx, &val.toObject());
313
0
    temp.emplace(cx);
314
0
  }
315
0
  if (!isNull) {
316
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->locale_id, temp.ptr())) {
317
0
      return false;
318
0
    }
319
0
  }
320
0
  if (!isNull && !temp->isUndefined()) {
321
0
    mLocale.Construct();
322
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mLocale.Value()))) {
323
0
      return false;
324
0
    }
325
0
    mIsAnyMemberPresent = true;
326
0
  }
327
0
328
0
  if (!isNull) {
329
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->style_id, temp.ptr())) {
330
0
      return false;
331
0
    }
332
0
  }
333
0
  if (!isNull && !temp->isUndefined()) {
334
0
    mStyle.Construct();
335
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mStyle.Value()))) {
336
0
      return false;
337
0
    }
338
0
    mIsAnyMemberPresent = true;
339
0
  }
340
0
341
0
  if (!isNull) {
342
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->values_id, temp.ptr())) {
343
0
      return false;
344
0
    }
345
0
  }
346
0
  if (!isNull && !temp->isUndefined()) {
347
0
    mValues.Construct();
348
0
    if (temp.ref().isObject()) {
349
0
      auto& recordEntries = (mValues.Value()).Entries();
350
0
351
0
      JS::Rooted<JSObject*> recordObj(cx, &temp.ref().toObject());
352
0
      JS::AutoIdVector ids(cx);
353
0
      if (!js::GetPropertyKeys(cx, recordObj,
354
0
                               JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, &ids)) {
355
0
        return false;
356
0
      }
357
0
      if (!recordEntries.SetCapacity(ids.length(), mozilla::fallible)) {
358
0
        JS_ReportOutOfMemory(cx);
359
0
        return false;
360
0
      }
361
0
      JS::Rooted<JS::Value> propNameValue(cx);
362
0
      JS::Rooted<JS::Value> temp(cx);
363
0
      JS::Rooted<jsid> curId(cx);
364
0
      JS::Rooted<JS::Value> idVal(cx);
365
0
      // Use a hashset to keep track of ids seen, to avoid
366
0
      // introducing nasty O(N^2) behavior scanning for them all the
367
0
      // time.  Ideally we'd use a data structure with O(1) lookup
368
0
      // _and_ ordering for the MozMap, but we don't have one lying
369
0
      // around.
370
0
      nsTHashtable<nsStringHashKey> idsSeen;
371
0
      for (size_t i = 0; i < ids.length(); ++i) {
372
0
        curId = ids[i];
373
0
374
0
        JS::Rooted<JS::PropertyDescriptor> desc(cx);
375
0
        if (!JS_GetOwnPropertyDescriptorById(cx, recordObj, curId,
376
0
                                             &desc)) {
377
0
          return false;
378
0
        }
379
0
380
0
        if (!desc.object() /* == undefined in spec terms */ ||
381
0
            !desc.enumerable()) {
382
0
          continue;
383
0
        }
384
0
385
0
        idVal = js::IdToValue(curId);
386
0
        nsString propName;
387
0
        // This will just throw if idVal is a Symbol, like the spec says
388
0
        // to do.
389
0
        if (!ConvertJSValueToString(cx, idVal, propName)) {
390
0
          return false;
391
0
        }
392
0
393
0
        if (!JS_GetPropertyById(cx, recordObj, curId, &temp)) {
394
0
          return false;
395
0
        }
396
0
397
0
        Record<nsString, nsString>::EntryType* entry;
398
0
        if (!idsSeen.EnsureInserted(propName)) {
399
0
          // Find the existing entry.
400
0
          auto idx = recordEntries.IndexOf(propName);
401
0
          MOZ_ASSERT(idx != recordEntries.NoIndex,
402
0
                     "Why is it not found?");
403
0
          // Now blow it away to make it look like it was just added
404
0
          // to the array, because it's not obvious that it's
405
0
          // safe to write to its already-initialized mValue via our
406
0
          // normal codegen conversions.  For example, the value
407
0
          // could be a union and this would change its type, but
408
0
          // codegen assumes we won't do that.
409
0
          entry = recordEntries.ReconstructElementAt(idx);
410
0
        } else {
411
0
          // Safe to do an infallible append here, because we did a
412
0
          // SetCapacity above to the right capacity.
413
0
          entry = recordEntries.AppendElement();
414
0
        }
415
0
        entry->mKey = propName;
416
0
        nsString& slot = entry->mValue;
417
0
        if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) {
418
0
          return false;
419
0
        }
420
0
      }
421
0
    } else {
422
0
      ThrowErrorMessage(cx, MSG_NOT_OBJECT, "'values' member of DisplayNameResult");
423
0
      return false;
424
0
    }
425
0
    mIsAnyMemberPresent = true;
426
0
  }
427
0
  return true;
428
0
}
429
430
bool
431
DisplayNameResult::Init(const nsAString& aJSON)
432
0
{
433
0
  AutoJSAPI jsapi;
434
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
435
0
  if (!cleanGlobal) {
436
0
    return false;
437
0
  }
438
0
  if (!jsapi.Init(cleanGlobal)) {
439
0
    return false;
440
0
  }
441
0
  JSContext* cx = jsapi.cx();
442
0
  JS::Rooted<JS::Value> json(cx);
443
0
  bool ok = ParseJSON(cx, aJSON, &json);
444
0
  NS_ENSURE_TRUE(ok, false);
445
0
  return Init(cx, json);
446
0
}
447
448
bool
449
DisplayNameResult::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
450
0
{
451
0
  DisplayNameResultAtoms* atomsCache = GetAtomCache<DisplayNameResultAtoms>(cx);
452
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
453
0
    return false;
454
0
  }
455
0
456
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
457
0
  if (!obj) {
458
0
    return false;
459
0
  }
460
0
  rval.set(JS::ObjectValue(*obj));
461
0
462
0
  if (mLocale.WasPassed()) {
463
0
    do {
464
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
465
0
      JS::Rooted<JS::Value> temp(cx);
466
0
      nsString const & currentValue = mLocale.InternalValue();
467
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
468
0
        return false;
469
0
      }
470
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->locale_id, temp, JSPROP_ENUMERATE)) {
471
0
        return false;
472
0
      }
473
0
      break;
474
0
    } while(false);
475
0
  }
476
0
477
0
  if (mStyle.WasPassed()) {
478
0
    do {
479
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
480
0
      JS::Rooted<JS::Value> temp(cx);
481
0
      nsString const & currentValue = mStyle.InternalValue();
482
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
483
0
        return false;
484
0
      }
485
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->style_id, temp, JSPROP_ENUMERATE)) {
486
0
        return false;
487
0
      }
488
0
      break;
489
0
    } while(false);
490
0
  }
491
0
492
0
  if (mValues.WasPassed()) {
493
0
    do {
494
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
495
0
      JS::Rooted<JS::Value> temp(cx);
496
0
      Record<nsString, nsString> const & currentValue = mValues.InternalValue();
497
0
498
0
      JS::Rooted<JSObject*> returnObj(cx, JS_NewPlainObject(cx));
499
0
      if (!returnObj) {
500
0
        return false;
501
0
      }
502
0
      // Scope for 'tmp'
503
0
      {
504
0
        JS::Rooted<JS::Value> tmp(cx);
505
0
        for (auto& entry : currentValue.Entries()) {
506
0
          auto& recordValue0 = entry.mValue;
507
0
          // Control block to let us common up the JS_DefineUCProperty calls when there
508
0
          // are different ways to succeed at wrapping the value.
509
0
          do {
510
0
            if (!xpc::NonVoidStringToJsval(cx, recordValue0, &tmp)) {
511
0
              return false;
512
0
            }
513
0
            break;
514
0
          } while (false);
515
0
          if (!JS_DefineUCProperty(cx, returnObj,
516
0
                                   entry.mKey.BeginReading(),
517
0
                                   entry.mKey.Length(), tmp,
518
0
                                   JSPROP_ENUMERATE)) {
519
0
            return false;
520
0
          }
521
0
        }
522
0
      }
523
0
      temp.setObject(*returnObj);
524
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->values_id, temp, JSPROP_ENUMERATE)) {
525
0
        return false;
526
0
      }
527
0
      break;
528
0
    } while(false);
529
0
  }
530
0
531
0
  return true;
532
0
}
533
534
bool
535
DisplayNameResult::ToJSON(nsAString& aJSON) const
536
0
{
537
0
  AutoJSAPI jsapi;
538
0
  jsapi.Init();
539
0
  JSContext *cx = jsapi.cx();
540
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
541
0
  // because we'll only be creating objects, in ways that have no
542
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
543
0
  // which likewise guarantees no side-effects for the sorts of
544
0
  // things we will pass it.
545
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
546
0
  JS::Rooted<JS::Value> val(cx);
547
0
  if (!ToObjectInternal(cx, &val)) {
548
0
    return false;
549
0
  }
550
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
551
0
  return StringifyToJSON(cx, obj, aJSON);
552
0
}
553
554
void
555
DisplayNameResult::TraceDictionary(JSTracer* trc)
556
0
{
557
0
}
558
559
namespace binding_detail {
560
} // namespace binding_detail
561
562
563
564
LocaleInfo::LocaleInfo()
565
0
{
566
0
  // Safe to pass a null context if we pass a null value
567
0
  Init(nullptr, JS::NullHandleValue);
568
0
}
569
570
571
572
bool
573
LocaleInfo::InitIds(JSContext* cx, LocaleInfoAtoms* atomsCache)
574
0
{
575
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
576
0
577
0
  // Initialize these in reverse order so that any failure leaves the first one
578
0
  // uninitialized.
579
0
  if (!atomsCache->locale_id.init(cx, "locale") ||
580
0
      !atomsCache->direction_id.init(cx, "direction")) {
581
0
    return false;
582
0
  }
583
0
  return true;
584
0
}
585
586
bool
587
LocaleInfo::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
588
0
{
589
0
  // Passing a null JSContext is OK only if we're initing from null,
590
0
  // Since in that case we will not have to do any property gets
591
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
592
0
  // checkers by static analysis tools
593
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
594
0
  LocaleInfoAtoms* atomsCache = nullptr;
595
0
  if (cx) {
596
0
    atomsCache = GetAtomCache<LocaleInfoAtoms>(cx);
597
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
598
0
      return false;
599
0
    }
600
0
  }
601
0
602
0
  if (!IsConvertibleToDictionary(val)) {
603
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
604
0
  }
605
0
606
0
  bool isNull = val.isNullOrUndefined();
607
0
  // We only need these if !isNull, in which case we have |cx|.
608
0
  Maybe<JS::Rooted<JSObject *> > object;
609
0
  Maybe<JS::Rooted<JS::Value> > temp;
610
0
  if (!isNull) {
611
0
    MOZ_ASSERT(cx);
612
0
    object.emplace(cx, &val.toObject());
613
0
    temp.emplace(cx);
614
0
  }
615
0
  if (!isNull) {
616
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->direction_id, temp.ptr())) {
617
0
      return false;
618
0
    }
619
0
  }
620
0
  if (!isNull && !temp->isUndefined()) {
621
0
    mDirection.Construct();
622
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mDirection.Value()))) {
623
0
      return false;
624
0
    }
625
0
    mIsAnyMemberPresent = true;
626
0
  }
627
0
628
0
  if (!isNull) {
629
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->locale_id, temp.ptr())) {
630
0
      return false;
631
0
    }
632
0
  }
633
0
  if (!isNull && !temp->isUndefined()) {
634
0
    mLocale.Construct();
635
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, (mLocale.Value()))) {
636
0
      return false;
637
0
    }
638
0
    mIsAnyMemberPresent = true;
639
0
  }
640
0
  return true;
641
0
}
642
643
bool
644
LocaleInfo::Init(const nsAString& aJSON)
645
0
{
646
0
  AutoJSAPI jsapi;
647
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
648
0
  if (!cleanGlobal) {
649
0
    return false;
650
0
  }
651
0
  if (!jsapi.Init(cleanGlobal)) {
652
0
    return false;
653
0
  }
654
0
  JSContext* cx = jsapi.cx();
655
0
  JS::Rooted<JS::Value> json(cx);
656
0
  bool ok = ParseJSON(cx, aJSON, &json);
657
0
  NS_ENSURE_TRUE(ok, false);
658
0
  return Init(cx, json);
659
0
}
660
661
bool
662
LocaleInfo::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
663
0
{
664
0
  LocaleInfoAtoms* atomsCache = GetAtomCache<LocaleInfoAtoms>(cx);
665
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
666
0
    return false;
667
0
  }
668
0
669
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
670
0
  if (!obj) {
671
0
    return false;
672
0
  }
673
0
  rval.set(JS::ObjectValue(*obj));
674
0
675
0
  if (mDirection.WasPassed()) {
676
0
    do {
677
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
678
0
      JS::Rooted<JS::Value> temp(cx);
679
0
      nsString const & currentValue = mDirection.InternalValue();
680
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
681
0
        return false;
682
0
      }
683
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->direction_id, temp, JSPROP_ENUMERATE)) {
684
0
        return false;
685
0
      }
686
0
      break;
687
0
    } while(false);
688
0
  }
689
0
690
0
  if (mLocale.WasPassed()) {
691
0
    do {
692
0
      // block for our 'break' successCode and scope for 'temp' and 'currentValue'
693
0
      JS::Rooted<JS::Value> temp(cx);
694
0
      nsString const & currentValue = mLocale.InternalValue();
695
0
      if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
696
0
        return false;
697
0
      }
698
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->locale_id, temp, JSPROP_ENUMERATE)) {
699
0
        return false;
700
0
      }
701
0
      break;
702
0
    } while(false);
703
0
  }
704
0
705
0
  return true;
706
0
}
707
708
bool
709
LocaleInfo::ToJSON(nsAString& aJSON) const
710
0
{
711
0
  AutoJSAPI jsapi;
712
0
  jsapi.Init();
713
0
  JSContext *cx = jsapi.cx();
714
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
715
0
  // because we'll only be creating objects, in ways that have no
716
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
717
0
  // which likewise guarantees no side-effects for the sorts of
718
0
  // things we will pass it.
719
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
720
0
  JS::Rooted<JS::Value> val(cx);
721
0
  if (!ToObjectInternal(cx, &val)) {
722
0
    return false;
723
0
  }
724
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
725
0
  return StringifyToJSON(cx, obj, aJSON);
726
0
}
727
728
void
729
LocaleInfo::TraceDictionary(JSTracer* trc)
730
0
{
731
0
}
732
733
LocaleInfo&
734
LocaleInfo::operator=(const LocaleInfo& aOther)
735
0
{
736
0
  DictionaryBase::operator=(aOther);
737
0
  mDirection.Reset();
738
0
  if (aOther.mDirection.WasPassed()) {
739
0
    mDirection.Construct(aOther.mDirection.Value());
740
0
  }
741
0
  mLocale.Reset();
742
0
  if (aOther.mLocale.WasPassed()) {
743
0
    mLocale.Construct(aOther.mLocale.Value());
744
0
  }
745
0
  return *this;
746
0
}
747
748
namespace binding_detail {
749
} // namespace binding_detail
750
751
752
namespace IntlUtils_Binding {
753
754
MOZ_CAN_RUN_SCRIPT static bool
755
getDisplayNames(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::IntlUtils* self, const JSJitMethodCallArgs& args)
756
0
{
757
0
  AUTO_PROFILER_LABEL_FAST("IntlUtils.getDisplayNames", DOM, cx);
758
0
759
0
  if (MOZ_UNLIKELY(args.length() < 1)) {
760
0
    return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "IntlUtils.getDisplayNames");
761
0
  }
762
0
  binding_detail::AutoSequence<nsString> arg0;
763
0
  if (args[0].isObject()) {
764
0
    JS::ForOfIterator iter(cx);
765
0
    if (!iter.init(args[0], JS::ForOfIterator::AllowNonIterable)) {
766
0
      return false;
767
0
    }
768
0
    if (!iter.valueIsIterable()) {
769
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 1 of IntlUtils.getDisplayNames");
770
0
      return false;
771
0
    }
772
0
    binding_detail::AutoSequence<nsString> &arr = arg0;
773
0
    JS::Rooted<JS::Value> temp(cx);
774
0
    while (true) {
775
0
      bool done;
776
0
      if (!iter.next(&temp, &done)) {
777
0
        return false;
778
0
      }
779
0
      if (done) {
780
0
        break;
781
0
      }
782
0
      nsString* slotPtr = arr.AppendElement(mozilla::fallible);
783
0
      if (!slotPtr) {
784
0
        JS_ReportOutOfMemory(cx);
785
0
        return false;
786
0
      }
787
0
      nsString& slot = *slotPtr;
788
0
      if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) {
789
0
        return false;
790
0
      }
791
0
    }
792
0
  } else {
793
0
    ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 1 of IntlUtils.getDisplayNames");
794
0
    return false;
795
0
  }
796
0
  binding_detail::FastDisplayNameOptions arg1;
797
0
  if (!arg1.Init(cx, (args.hasDefined(1)) ? args[1] : JS::NullHandleValue,  "Argument 2 of IntlUtils.getDisplayNames", false)) {
798
0
    return false;
799
0
  }
800
0
  FastErrorResult rv;
801
0
  DisplayNameResult result;
802
0
  self->GetDisplayNames(Constify(arg0), Constify(arg1), result, rv);
803
0
  if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
804
0
    return false;
805
0
  }
806
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
807
0
  if (!result.ToObjectInternal(cx, args.rval())) {
808
0
    return false;
809
0
  }
810
0
  return true;
811
0
}
812
813
static const JSJitInfo getDisplayNames_methodinfo = {
814
  { (JSJitGetterOp)getDisplayNames },
815
  { prototypes::id::IntlUtils },
816
  { PrototypeTraits<prototypes::id::IntlUtils>::Depth },
817
  JSJitInfo::Method,
818
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
819
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
820
  false,  /* isInfallible. False in setters. */
821
  false,  /* isMovable.  Not relevant for setters. */
822
  false, /* isEliminatable.  Not relevant for setters. */
823
  false, /* isAlwaysInSlot.  Only relevant for getters. */
824
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
825
  false,  /* isTypedMethod.  Only relevant for methods. */
826
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
827
};
828
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
829
static_assert(0 < 1, "There is no slot for us");
830
831
MOZ_CAN_RUN_SCRIPT static bool
832
getLocaleInfo(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::IntlUtils* self, const JSJitMethodCallArgs& args)
833
0
{
834
0
  AUTO_PROFILER_LABEL_FAST("IntlUtils.getLocaleInfo", DOM, cx);
835
0
836
0
  if (MOZ_UNLIKELY(args.length() < 1)) {
837
0
    return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "IntlUtils.getLocaleInfo");
838
0
  }
839
0
  binding_detail::AutoSequence<nsString> arg0;
840
0
  if (args[0].isObject()) {
841
0
    JS::ForOfIterator iter(cx);
842
0
    if (!iter.init(args[0], JS::ForOfIterator::AllowNonIterable)) {
843
0
      return false;
844
0
    }
845
0
    if (!iter.valueIsIterable()) {
846
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 1 of IntlUtils.getLocaleInfo");
847
0
      return false;
848
0
    }
849
0
    binding_detail::AutoSequence<nsString> &arr = arg0;
850
0
    JS::Rooted<JS::Value> temp(cx);
851
0
    while (true) {
852
0
      bool done;
853
0
      if (!iter.next(&temp, &done)) {
854
0
        return false;
855
0
      }
856
0
      if (done) {
857
0
        break;
858
0
      }
859
0
      nsString* slotPtr = arr.AppendElement(mozilla::fallible);
860
0
      if (!slotPtr) {
861
0
        JS_ReportOutOfMemory(cx);
862
0
        return false;
863
0
      }
864
0
      nsString& slot = *slotPtr;
865
0
      if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) {
866
0
        return false;
867
0
      }
868
0
    }
869
0
  } else {
870
0
    ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 1 of IntlUtils.getLocaleInfo");
871
0
    return false;
872
0
  }
873
0
  FastErrorResult rv;
874
0
  LocaleInfo result;
875
0
  self->GetLocaleInfo(Constify(arg0), result, rv);
876
0
  if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
877
0
    return false;
878
0
  }
879
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
880
0
  if (!result.ToObjectInternal(cx, args.rval())) {
881
0
    return false;
882
0
  }
883
0
  return true;
884
0
}
885
886
static const JSJitInfo getLocaleInfo_methodinfo = {
887
  { (JSJitGetterOp)getLocaleInfo },
888
  { prototypes::id::IntlUtils },
889
  { PrototypeTraits<prototypes::id::IntlUtils>::Depth },
890
  JSJitInfo::Method,
891
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
892
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
893
  false,  /* isInfallible. False in setters. */
894
  false,  /* isMovable.  Not relevant for setters. */
895
  false, /* isEliminatable.  Not relevant for setters. */
896
  false, /* isAlwaysInSlot.  Only relevant for getters. */
897
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
898
  false,  /* isTypedMethod.  Only relevant for methods. */
899
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
900
};
901
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
902
static_assert(0 < 1, "There is no slot for us");
903
904
static bool
905
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
906
0
{
907
0
  mozilla::dom::IntlUtils* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::IntlUtils>(obj);
908
0
  // We don't want to preserve if we don't have a wrapper, and we
909
0
  // obviously can't preserve if we're not initialized.
910
0
  if (self && self->GetWrapperPreserveColor()) {
911
0
    PreserveWrapper(self);
912
0
  }
913
0
  return true;
914
0
}
915
916
static void
917
_finalize(js::FreeOp* fop, JSObject* obj)
918
0
{
919
0
  mozilla::dom::IntlUtils* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::IntlUtils>(obj);
920
0
  if (self) {
921
0
    ClearWrapper(self, self, obj);
922
0
    AddForDeferredFinalization<mozilla::dom::IntlUtils>(self);
923
0
  }
924
0
}
925
926
static size_t
927
_objectMoved(JSObject* obj, JSObject* old)
928
0
{
929
0
  mozilla::dom::IntlUtils* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::IntlUtils>(obj);
930
0
  if (self) {
931
0
    UpdateWrapper(self, self, obj, old);
932
0
  }
933
0
934
0
  return 0;
935
0
}
936
937
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
938
#if defined(__clang__)
939
#pragma clang diagnostic push
940
#pragma clang diagnostic ignored "-Wmissing-braces"
941
#endif
942
static const JSFunctionSpec sMethods_specs[] = {
943
  JS_FNSPEC("getDisplayNames", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&getDisplayNames_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
944
  JS_FNSPEC("getLocaleInfo", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&getLocaleInfo_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
945
  JS_FS_END
946
};
947
#if defined(__clang__)
948
#pragma clang diagnostic pop
949
#endif
950
951
952
static const Prefable<const JSFunctionSpec> sMethods[] = {
953
  { nullptr, &sMethods_specs[0] },
954
  { nullptr, nullptr }
955
};
956
957
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
958
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
959
static_assert(2 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
960
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
961
962
963
static uint16_t sNativeProperties_sortedPropertyIndices[2];
964
static PropertyInfo sNativeProperties_propertyInfos[2];
965
966
static const NativePropertiesN<1> sNativeProperties = {
967
  false, 0,
968
  false, 0,
969
  true,  0 /* sMethods */,
970
  false, 0,
971
  false, 0,
972
  false, 0,
973
  false, 0,
974
  -1,
975
  2,
976
  sNativeProperties_sortedPropertyIndices,
977
  {
978
    { sMethods, &sNativeProperties_propertyInfos[0] }
979
  }
980
};
981
static_assert(2 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
982
    "We have a property info count that is oversized");
983
984
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
985
  {
986
    "IntlUtilsPrototype",
987
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
988
    JS_NULL_CLASS_OPS,
989
    JS_NULL_CLASS_SPEC,
990
    JS_NULL_CLASS_EXT,
991
    JS_NULL_OBJECT_OPS
992
  },
993
  eInterfacePrototype,
994
  false,
995
  prototypes::id::IntlUtils,
996
  PrototypeTraits<prototypes::id::IntlUtils>::Depth,
997
  sNativePropertyHooks,
998
  "[object IntlUtilsPrototype]",
999
  JS::GetRealmObjectPrototype
1000
};
1001
1002
static const js::ClassOps sClassOps = {
1003
  _addProperty, /* addProperty */
1004
  nullptr,               /* delProperty */
1005
  nullptr,               /* enumerate */
1006
  nullptr, /* newEnumerate */
1007
  nullptr, /* resolve */
1008
  nullptr, /* mayResolve */
1009
  _finalize, /* finalize */
1010
  nullptr, /* call */
1011
  nullptr,               /* hasInstance */
1012
  nullptr,               /* construct */
1013
  nullptr, /* trace */
1014
};
1015
1016
static const js::ClassExtension sClassExtension = {
1017
  nullptr, /* weakmapKeyDelegateOp */
1018
  _objectMoved /* objectMovedOp */
1019
};
1020
1021
static const DOMJSClass sClass = {
1022
  { "IntlUtils",
1023
    JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
1024
    &sClassOps,
1025
    JS_NULL_CLASS_SPEC,
1026
    &sClassExtension,
1027
    JS_NULL_OBJECT_OPS
1028
  },
1029
  { prototypes::id::IntlUtils, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count },
1030
  IsBaseOf<nsISupports, mozilla::dom::IntlUtils >::value,
1031
  sNativePropertyHooks,
1032
  FindAssociatedGlobalForNative<mozilla::dom::IntlUtils>::Get,
1033
  GetProtoObjectHandle,
1034
  GetCCParticipant<mozilla::dom::IntlUtils>::Get()
1035
};
1036
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
1037
              "Must have the right minimal number of reserved slots.");
1038
static_assert(1 >= 1,
1039
              "Must have enough reserved slots.");
1040
1041
const JSClass*
1042
GetJSClass()
1043
0
{
1044
0
  return sClass.ToJSClass();
1045
0
}
1046
1047
bool
1048
Wrap(JSContext* aCx, mozilla::dom::IntlUtils* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
1049
0
{
1050
0
  static_assert(!IsBaseOf<NonRefcountedDOMObject, mozilla::dom::IntlUtils>::value,
1051
0
                "Shouldn't have wrappercached things that are not refcounted.");
1052
0
  MOZ_ASSERT(static_cast<mozilla::dom::IntlUtils*>(aObject) ==
1053
0
             reinterpret_cast<mozilla::dom::IntlUtils*>(aObject),
1054
0
             "Multiple inheritance for mozilla::dom::IntlUtils is broken.");
1055
0
  MOZ_ASSERT(ToSupportsIsCorrect(aObject));
1056
0
  MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
1057
0
  MOZ_ASSERT(!aCache->GetWrapper(),
1058
0
             "You should probably not be using Wrap() directly; use "
1059
0
             "GetOrCreateDOMReflector instead");
1060
0
1061
0
  MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
1062
0
             "nsISupports must be on our primary inheritance chain");
1063
0
1064
0
  JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
1065
0
  if (!global) {
1066
0
    return false;
1067
0
  }
1068
0
  MOZ_ASSERT(JS_IsGlobalObject(global));
1069
0
  MOZ_ASSERT(JS::ObjectIsNotGray(global));
1070
0
1071
0
  // That might have ended up wrapping us already, due to the wonders
1072
0
  // of XBL.  Check for that, and bail out as needed.
1073
0
  aReflector.set(aCache->GetWrapper());
1074
0
  if (aReflector) {
1075
#ifdef DEBUG
1076
    AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
1077
#endif // DEBUG
1078
    return true;
1079
0
  }
1080
0
1081
0
  JSAutoRealm ar(aCx, global);
1082
0
  JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
1083
0
  if (!canonicalProto) {
1084
0
    return false;
1085
0
  }
1086
0
  JS::Rooted<JSObject*> proto(aCx);
1087
0
  if (aGivenProto) {
1088
0
    proto = aGivenProto;
1089
0
    // Unfortunately, while aGivenProto was in the compartment of aCx
1090
0
    // coming in, we changed compartments to that of "parent" so may need
1091
0
    // to wrap the proto here.
1092
0
    if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
1093
0
      if (!JS_WrapObject(aCx, &proto)) {
1094
0
        return false;
1095
0
      }
1096
0
    }
1097
0
  } else {
1098
0
    proto = canonicalProto;
1099
0
  }
1100
0
1101
0
  BindingJSObjectCreator<mozilla::dom::IntlUtils> creator(aCx);
1102
0
  creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
1103
0
  if (!aReflector) {
1104
0
    return false;
1105
0
  }
1106
0
1107
0
  aCache->SetWrapper(aReflector);
1108
0
  creator.InitializationSucceeded();
1109
0
1110
0
  MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
1111
0
             aCache->GetWrapperPreserveColor() == aReflector);
1112
0
  // If proto != canonicalProto, we have to preserve our wrapper;
1113
0
  // otherwise we won't be able to properly recreate it later, since
1114
0
  // we won't know what proto to use.  Note that we don't check
1115
0
  // aGivenProto here, since it's entirely possible (and even
1116
0
  // somewhat common) to have a non-null aGivenProto which is the
1117
0
  // same as canonicalProto.
1118
0
  if (proto != canonicalProto) {
1119
0
    PreserveWrapper(aObject);
1120
0
  }
1121
0
1122
0
  return true;
1123
0
}
1124
1125
const NativePropertyHooks sNativePropertyHooks[] = { {
1126
  nullptr,
1127
  nullptr,
1128
  nullptr,
1129
  { sNativeProperties.Upcast(), nullptr },
1130
  prototypes::id::IntlUtils,
1131
  constructors::id::_ID_Count,
1132
  nullptr,
1133
  &DefaultXrayExpandoObjectClass
1134
} };
1135
1136
void
1137
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
1138
0
{
1139
0
  JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
1140
0
  if (!parentProto) {
1141
0
    return;
1142
0
  }
1143
0
1144
0
  static bool sIdsInited = false;
1145
0
  if (!sIdsInited && NS_IsMainThread()) {
1146
0
    if (!InitIds(aCx, sNativeProperties.Upcast())) {
1147
0
      return;
1148
0
    }
1149
0
    sIdsInited = true;
1150
0
  }
1151
0
1152
0
  JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::IntlUtils);
1153
0
  JS::Heap<JSObject*>* interfaceCache = nullptr;
1154
0
  dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
1155
0
                              &sPrototypeClass.mBase, protoCache,
1156
0
                              nullptr,
1157
0
                              nullptr, nullptr, 0, nullptr,
1158
0
                              interfaceCache,
1159
0
                              sNativeProperties.Upcast(),
1160
0
                              nullptr,
1161
0
                              nullptr, aDefineOnGlobal,
1162
0
                              nullptr,
1163
0
                              false);
1164
0
}
1165
1166
} // namespace IntlUtils_Binding
1167
1168
1169
1170
} // namespace dom
1171
} // namespace mozilla