Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dom/bindings/L10nUtilsBinding.cpp
Line
Count
Source (jump to first uncovered line)
1
/* THIS FILE IS AUTOGENERATED FROM L10nUtils.webidl BY Codegen.py - DO NOT EDIT */
2
3
#include "AtomList.h"
4
#include "L10nUtilsBinding.h"
5
#include "mozilla/OwningNonNull.h"
6
#include "mozilla/dom/BindingUtils.h"
7
#include "mozilla/dom/NonRefcountedDOMObject.h"
8
#include "mozilla/dom/Promise.h"
9
#include "mozilla/dom/ScriptSettings.h"
10
#include "mozilla/dom/SimpleGlobalObject.h"
11
#include "mozilla/dom/ToJSValue.h"
12
13
namespace mozilla {
14
namespace dom {
15
16
namespace binding_detail {}; // Just to make sure it's known as a namespace
17
using namespace mozilla::dom::binding_detail;
18
19
20
21
AttributeNameValue::AttributeNameValue()
22
0
{
23
0
  // Safe to pass a null context if we pass a null value
24
0
  Init(nullptr, JS::NullHandleValue);
25
0
}
26
27
28
29
bool
30
AttributeNameValue::InitIds(JSContext* cx, AttributeNameValueAtoms* atomsCache)
31
0
{
32
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
33
0
34
0
  // Initialize these in reverse order so that any failure leaves the first one
35
0
  // uninitialized.
36
0
  if (!atomsCache->value_id.init(cx, "value") ||
37
0
      !atomsCache->name_id.init(cx, "name")) {
38
0
    return false;
39
0
  }
40
0
  return true;
41
0
}
42
43
bool
44
AttributeNameValue::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
45
0
{
46
0
  // Passing a null JSContext is OK only if we're initing from null,
47
0
  // Since in that case we will not have to do any property gets
48
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
49
0
  // checkers by static analysis tools
50
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
51
0
  AttributeNameValueAtoms* atomsCache = nullptr;
52
0
  if (cx) {
53
0
    atomsCache = GetAtomCache<AttributeNameValueAtoms>(cx);
54
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
55
0
      return false;
56
0
    }
57
0
  }
58
0
59
0
  if (!IsConvertibleToDictionary(val)) {
60
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
61
0
  }
62
0
63
0
  bool isNull = val.isNullOrUndefined();
64
0
  // We only need these if !isNull, in which case we have |cx|.
65
0
  Maybe<JS::Rooted<JSObject *> > object;
66
0
  Maybe<JS::Rooted<JS::Value> > temp;
67
0
  if (!isNull) {
68
0
    MOZ_ASSERT(cx);
69
0
    object.emplace(cx, &val.toObject());
70
0
    temp.emplace(cx);
71
0
  }
72
0
  if (!isNull) {
73
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->name_id, temp.ptr())) {
74
0
      return false;
75
0
    }
76
0
  }
77
0
  if (!isNull && !temp->isUndefined()) {
78
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mName)) {
79
0
      return false;
80
0
    }
81
0
    mIsAnyMemberPresent = true;
82
0
  } else if (cx) {
83
0
    // Don't error out if we have no cx.  In that
84
0
    // situation the caller is default-constructing us and we'll
85
0
    // just assume they know what they're doing.
86
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
87
0
                             "'name' member of AttributeNameValue");
88
0
  }
89
0
90
0
  if (!isNull) {
91
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->value_id, temp.ptr())) {
92
0
      return false;
93
0
    }
94
0
  }
95
0
  if (!isNull && !temp->isUndefined()) {
96
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mValue)) {
97
0
      return false;
98
0
    }
99
0
    mIsAnyMemberPresent = true;
100
0
  } else if (cx) {
101
0
    // Don't error out if we have no cx.  In that
102
0
    // situation the caller is default-constructing us and we'll
103
0
    // just assume they know what they're doing.
104
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
105
0
                             "'value' member of AttributeNameValue");
106
0
  }
107
0
  return true;
108
0
}
109
110
bool
111
AttributeNameValue::Init(const nsAString& aJSON)
112
0
{
113
0
  AutoJSAPI jsapi;
114
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
115
0
  if (!cleanGlobal) {
116
0
    return false;
117
0
  }
118
0
  if (!jsapi.Init(cleanGlobal)) {
119
0
    return false;
120
0
  }
121
0
  JSContext* cx = jsapi.cx();
122
0
  JS::Rooted<JS::Value> json(cx);
123
0
  bool ok = ParseJSON(cx, aJSON, &json);
124
0
  NS_ENSURE_TRUE(ok, false);
125
0
  return Init(cx, json);
126
0
}
127
128
bool
129
AttributeNameValue::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
130
0
{
131
0
  AttributeNameValueAtoms* atomsCache = GetAtomCache<AttributeNameValueAtoms>(cx);
132
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
133
0
    return false;
134
0
  }
135
0
136
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
137
0
  if (!obj) {
138
0
    return false;
139
0
  }
140
0
  rval.set(JS::ObjectValue(*obj));
141
0
142
0
  do {
143
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
144
0
    JS::Rooted<JS::Value> temp(cx);
145
0
    nsString const & currentValue = mName;
146
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
147
0
      return false;
148
0
    }
149
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->name_id, temp, JSPROP_ENUMERATE)) {
150
0
      return false;
151
0
    }
152
0
    break;
153
0
  } while(false);
154
0
155
0
  do {
156
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
157
0
    JS::Rooted<JS::Value> temp(cx);
158
0
    nsString const & currentValue = mValue;
159
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
160
0
      return false;
161
0
    }
162
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->value_id, temp, JSPROP_ENUMERATE)) {
163
0
      return false;
164
0
    }
165
0
    break;
166
0
  } while(false);
167
0
168
0
  return true;
169
0
}
170
171
bool
172
AttributeNameValue::ToJSON(nsAString& aJSON) const
173
0
{
174
0
  AutoJSAPI jsapi;
175
0
  jsapi.Init();
176
0
  JSContext *cx = jsapi.cx();
177
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
178
0
  // because we'll only be creating objects, in ways that have no
179
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
180
0
  // which likewise guarantees no side-effects for the sorts of
181
0
  // things we will pass it.
182
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
183
0
  JS::Rooted<JS::Value> val(cx);
184
0
  if (!ToObjectInternal(cx, &val)) {
185
0
    return false;
186
0
  }
187
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
188
0
  return StringifyToJSON(cx, obj, aJSON);
189
0
}
190
191
void
192
AttributeNameValue::TraceDictionary(JSTracer* trc)
193
0
{
194
0
}
195
196
AttributeNameValue&
197
AttributeNameValue::operator=(const AttributeNameValue& aOther)
198
0
{
199
0
  DictionaryBase::operator=(aOther);
200
0
  mName = aOther.mName;
201
0
  mValue = aOther.mValue;
202
0
  return *this;
203
0
}
204
205
namespace binding_detail {
206
} // namespace binding_detail
207
208
209
210
L10nElement::L10nElement()
211
  : mL10nArgs(nullptr)
212
0
{
213
0
  // Safe to pass a null context if we pass a null value
214
0
  Init(nullptr, JS::NullHandleValue);
215
0
}
216
217
218
bool
219
L10nElement::InitIds(JSContext* cx, L10nElementAtoms* atomsCache)
220
0
{
221
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
222
0
223
0
  // Initialize these in reverse order so that any failure leaves the first one
224
0
  // uninitialized.
225
0
  if (!atomsCache->type_id.init(cx, "type") ||
226
0
      !atomsCache->namespaceURI_id.init(cx, "namespaceURI") ||
227
0
      !atomsCache->localName_id.init(cx, "localName") ||
228
0
      !atomsCache->l10nId_id.init(cx, "l10nId") ||
229
0
      !atomsCache->l10nAttrs_id.init(cx, "l10nAttrs") ||
230
0
      !atomsCache->l10nArgs_id.init(cx, "l10nArgs")) {
231
0
    return false;
232
0
  }
233
0
  return true;
234
0
}
235
236
bool
237
L10nElement::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
238
0
{
239
0
  // Passing a null JSContext is OK only if we're initing from null,
240
0
  // Since in that case we will not have to do any property gets
241
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
242
0
  // checkers by static analysis tools
243
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
244
0
  L10nElementAtoms* atomsCache = nullptr;
245
0
  if (cx) {
246
0
    atomsCache = GetAtomCache<L10nElementAtoms>(cx);
247
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
248
0
      return false;
249
0
    }
250
0
  }
251
0
252
0
  if (!IsConvertibleToDictionary(val)) {
253
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
254
0
  }
255
0
256
0
  bool isNull = val.isNullOrUndefined();
257
0
  // We only need these if !isNull, in which case we have |cx|.
258
0
  Maybe<JS::Rooted<JSObject *> > object;
259
0
  Maybe<JS::Rooted<JS::Value> > temp;
260
0
  if (!isNull) {
261
0
    MOZ_ASSERT(cx);
262
0
    object.emplace(cx, &val.toObject());
263
0
    temp.emplace(cx);
264
0
  }
265
0
  if (!isNull) {
266
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->l10nArgs_id, temp.ptr())) {
267
0
      return false;
268
0
    }
269
0
  }
270
0
  if (!isNull && !temp->isUndefined()) {
271
0
    if (temp.ref().isObject()) {
272
0
#ifdef __clang__
273
0
#pragma clang diagnostic push
274
0
#pragma clang diagnostic ignored "-Wunreachable-code"
275
0
#pragma clang diagnostic ignored "-Wunreachable-code-return"
276
0
#endif // __clang__
277
0
      if ((passedToJSImpl) && !CallerSubsumes(temp.ref())) {
278
0
        ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "'l10nArgs' member of L10nElement");
279
0
        return false;
280
0
      }
281
0
#ifdef __clang__
282
0
#pragma clang diagnostic pop
283
0
#endif // __clang__
284
0
      mL10nArgs = &temp.ref().toObject();
285
0
    } else if (temp.ref().isNullOrUndefined()) {
286
0
      mL10nArgs = nullptr;
287
0
    } else {
288
0
      ThrowErrorMessage(cx, MSG_NOT_OBJECT, "'l10nArgs' member of L10nElement");
289
0
      return false;
290
0
    }
291
0
  } else {
292
0
    mL10nArgs = nullptr;
293
0
  }
294
0
  mIsAnyMemberPresent = true;
295
0
296
0
  if (!isNull) {
297
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->l10nAttrs_id, temp.ptr())) {
298
0
      return false;
299
0
    }
300
0
  }
301
0
  if (!isNull && !temp->isUndefined()) {
302
0
    if (!ConvertJSValueToString(cx, temp.ref(), eNull, eNull, mL10nAttrs)) {
303
0
      return false;
304
0
    }
305
0
  } else {
306
0
    mL10nAttrs.SetIsVoid(true);
307
0
  }
308
0
  mIsAnyMemberPresent = true;
309
0
310
0
  if (!isNull) {
311
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->l10nId_id, temp.ptr())) {
312
0
      return false;
313
0
    }
314
0
  }
315
0
  if (!isNull && !temp->isUndefined()) {
316
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mL10nId)) {
317
0
      return false;
318
0
    }
319
0
    mIsAnyMemberPresent = true;
320
0
  } else if (cx) {
321
0
    // Don't error out if we have no cx.  In that
322
0
    // situation the caller is default-constructing us and we'll
323
0
    // just assume they know what they're doing.
324
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
325
0
                             "'l10nId' member of L10nElement");
326
0
  }
327
0
328
0
  if (!isNull) {
329
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->localName_id, temp.ptr())) {
330
0
      return false;
331
0
    }
332
0
  }
333
0
  if (!isNull && !temp->isUndefined()) {
334
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mLocalName)) {
335
0
      return false;
336
0
    }
337
0
    mIsAnyMemberPresent = true;
338
0
  } else if (cx) {
339
0
    // Don't error out if we have no cx.  In that
340
0
    // situation the caller is default-constructing us and we'll
341
0
    // just assume they know what they're doing.
342
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
343
0
                             "'localName' member of L10nElement");
344
0
  }
345
0
346
0
  if (!isNull) {
347
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->namespaceURI_id, temp.ptr())) {
348
0
      return false;
349
0
    }
350
0
  }
351
0
  if (!isNull && !temp->isUndefined()) {
352
0
    if (!ConvertJSValueToString(cx, temp.ref(), eStringify, eStringify, mNamespaceURI)) {
353
0
      return false;
354
0
    }
355
0
    mIsAnyMemberPresent = true;
356
0
  } else if (cx) {
357
0
    // Don't error out if we have no cx.  In that
358
0
    // situation the caller is default-constructing us and we'll
359
0
    // just assume they know what they're doing.
360
0
    return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
361
0
                             "'namespaceURI' member of L10nElement");
362
0
  }
363
0
364
0
  if (!isNull) {
365
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->type_id, temp.ptr())) {
366
0
      return false;
367
0
    }
368
0
  }
369
0
  if (!isNull && !temp->isUndefined()) {
370
0
    if (!ConvertJSValueToString(cx, temp.ref(), eNull, eNull, mType)) {
371
0
      return false;
372
0
    }
373
0
  } else {
374
0
    mType.SetIsVoid(true);
375
0
  }
376
0
  mIsAnyMemberPresent = true;
377
0
  return true;
378
0
}
379
380
bool
381
L10nElement::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
382
0
{
383
0
  L10nElementAtoms* atomsCache = GetAtomCache<L10nElementAtoms>(cx);
384
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
385
0
    return false;
386
0
  }
387
0
388
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
389
0
  if (!obj) {
390
0
    return false;
391
0
  }
392
0
  rval.set(JS::ObjectValue(*obj));
393
0
394
0
  do {
395
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
396
0
    JS::Rooted<JS::Value> temp(cx);
397
0
    JSObject* const & currentValue = mL10nArgs;
398
0
    if (currentValue) {
399
0
                  JS::ExposeObjectToActiveJS(currentValue);
400
0
                }
401
0
                temp.setObjectOrNull(currentValue);
402
0
    if (!MaybeWrapObjectOrNullValue(cx, &temp)) {
403
0
      return false;
404
0
    }
405
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->l10nArgs_id, temp, JSPROP_ENUMERATE)) {
406
0
      return false;
407
0
    }
408
0
    break;
409
0
  } while(false);
410
0
411
0
  do {
412
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
413
0
    JS::Rooted<JS::Value> temp(cx);
414
0
    nsString const & currentValue = mL10nAttrs;
415
0
    if (!xpc::StringToJsval(cx, currentValue, &temp)) {
416
0
      return false;
417
0
    }
418
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->l10nAttrs_id, temp, JSPROP_ENUMERATE)) {
419
0
      return false;
420
0
    }
421
0
    break;
422
0
  } while(false);
423
0
424
0
  do {
425
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
426
0
    JS::Rooted<JS::Value> temp(cx);
427
0
    nsString const & currentValue = mL10nId;
428
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
429
0
      return false;
430
0
    }
431
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->l10nId_id, temp, JSPROP_ENUMERATE)) {
432
0
      return false;
433
0
    }
434
0
    break;
435
0
  } while(false);
436
0
437
0
  do {
438
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
439
0
    JS::Rooted<JS::Value> temp(cx);
440
0
    nsString const & currentValue = mLocalName;
441
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
442
0
      return false;
443
0
    }
444
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->localName_id, temp, JSPROP_ENUMERATE)) {
445
0
      return false;
446
0
    }
447
0
    break;
448
0
  } while(false);
449
0
450
0
  do {
451
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
452
0
    JS::Rooted<JS::Value> temp(cx);
453
0
    nsString const & currentValue = mNamespaceURI;
454
0
    if (!xpc::NonVoidStringToJsval(cx, currentValue, &temp)) {
455
0
      return false;
456
0
    }
457
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->namespaceURI_id, temp, JSPROP_ENUMERATE)) {
458
0
      return false;
459
0
    }
460
0
    break;
461
0
  } while(false);
462
0
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 = mType;
467
0
    if (!xpc::StringToJsval(cx, currentValue, &temp)) {
468
0
      return false;
469
0
    }
470
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->type_id, temp, JSPROP_ENUMERATE)) {
471
0
      return false;
472
0
    }
473
0
    break;
474
0
  } while(false);
475
0
476
0
  return true;
477
0
}
478
479
void
480
L10nElement::TraceDictionary(JSTracer* trc)
481
0
{
482
0
  if (mL10nArgs) {
483
0
    JS::UnsafeTraceRoot(trc, &mL10nArgs, "L10nElement.mL10nArgs");
484
0
  }
485
0
}
486
487
namespace binding_detail {
488
} // namespace binding_detail
489
490
491
492
L10nValue::L10nValue()
493
0
{
494
0
  // Safe to pass a null context if we pass a null value
495
0
  Init(nullptr, JS::NullHandleValue);
496
0
}
497
498
499
500
bool
501
L10nValue::InitIds(JSContext* cx, L10nValueAtoms* atomsCache)
502
0
{
503
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
504
0
505
0
  // Initialize these in reverse order so that any failure leaves the first one
506
0
  // uninitialized.
507
0
  if (!atomsCache->value_id.init(cx, "value") ||
508
0
      !atomsCache->attributes_id.init(cx, "attributes")) {
509
0
    return false;
510
0
  }
511
0
  return true;
512
0
}
513
514
bool
515
L10nValue::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
516
0
{
517
0
  // Passing a null JSContext is OK only if we're initing from null,
518
0
  // Since in that case we will not have to do any property gets
519
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
520
0
  // checkers by static analysis tools
521
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
522
0
  L10nValueAtoms* atomsCache = nullptr;
523
0
  if (cx) {
524
0
    atomsCache = GetAtomCache<L10nValueAtoms>(cx);
525
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
526
0
      return false;
527
0
    }
528
0
  }
529
0
530
0
  if (!IsConvertibleToDictionary(val)) {
531
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
532
0
  }
533
0
534
0
  bool isNull = val.isNullOrUndefined();
535
0
  // We only need these if !isNull, in which case we have |cx|.
536
0
  Maybe<JS::Rooted<JSObject *> > object;
537
0
  Maybe<JS::Rooted<JS::Value> > temp;
538
0
  if (!isNull) {
539
0
    MOZ_ASSERT(cx);
540
0
    object.emplace(cx, &val.toObject());
541
0
    temp.emplace(cx);
542
0
  }
543
0
  if (!isNull) {
544
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->attributes_id, temp.ptr())) {
545
0
      return false;
546
0
    }
547
0
  }
548
0
  if (!isNull && !temp->isUndefined()) {
549
0
    if (temp.ref().isObject()) {
550
0
      JS::ForOfIterator iter(cx);
551
0
      if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
552
0
        return false;
553
0
      }
554
0
      if (!iter.valueIsIterable()) {
555
0
        ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'attributes' member of L10nValue");
556
0
        return false;
557
0
      }
558
0
      Sequence<AttributeNameValue> &arr = mAttributes.SetValue();
559
0
      JS::Rooted<JS::Value> temp(cx);
560
0
      while (true) {
561
0
        bool done;
562
0
        if (!iter.next(&temp, &done)) {
563
0
          return false;
564
0
        }
565
0
        if (done) {
566
0
          break;
567
0
        }
568
0
        AttributeNameValue* slotPtr = arr.AppendElement(mozilla::fallible);
569
0
        if (!slotPtr) {
570
0
          JS_ReportOutOfMemory(cx);
571
0
          return false;
572
0
        }
573
0
        AttributeNameValue& slot = *slotPtr;
574
0
        if (!slot.Init(cx, temp,  "Element of 'attributes' member of L10nValue", passedToJSImpl)) {
575
0
          return false;
576
0
        }
577
0
      }
578
0
    } else if (temp.ref().isNullOrUndefined()) {
579
0
      mAttributes.SetNull();
580
0
    } else {
581
0
      ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "'attributes' member of L10nValue");
582
0
      return false;
583
0
    }
584
0
  } else {
585
0
    mAttributes.SetNull();
586
0
  }
587
0
  mIsAnyMemberPresent = true;
588
0
589
0
  if (!isNull) {
590
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->value_id, temp.ptr())) {
591
0
      return false;
592
0
    }
593
0
  }
594
0
  if (!isNull && !temp->isUndefined()) {
595
0
    if (!ConvertJSValueToString(cx, temp.ref(), eNull, eNull, mValue)) {
596
0
      return false;
597
0
    }
598
0
  } else {
599
0
    mValue.SetIsVoid(true);
600
0
  }
601
0
  mIsAnyMemberPresent = true;
602
0
  return true;
603
0
}
604
605
bool
606
L10nValue::Init(const nsAString& aJSON)
607
0
{
608
0
  AutoJSAPI jsapi;
609
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
610
0
  if (!cleanGlobal) {
611
0
    return false;
612
0
  }
613
0
  if (!jsapi.Init(cleanGlobal)) {
614
0
    return false;
615
0
  }
616
0
  JSContext* cx = jsapi.cx();
617
0
  JS::Rooted<JS::Value> json(cx);
618
0
  bool ok = ParseJSON(cx, aJSON, &json);
619
0
  NS_ENSURE_TRUE(ok, false);
620
0
  return Init(cx, json);
621
0
}
622
623
bool
624
L10nValue::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
625
0
{
626
0
  L10nValueAtoms* atomsCache = GetAtomCache<L10nValueAtoms>(cx);
627
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
628
0
    return false;
629
0
  }
630
0
631
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
632
0
  if (!obj) {
633
0
    return false;
634
0
  }
635
0
  rval.set(JS::ObjectValue(*obj));
636
0
637
0
  do {
638
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
639
0
    JS::Rooted<JS::Value> temp(cx);
640
0
    Nullable<Sequence<AttributeNameValue>> const & currentValue = mAttributes;
641
0
642
0
    if (currentValue.IsNull()) {
643
0
      temp.setNull();
644
0
      if (!JS_DefinePropertyById(cx, obj, atomsCache->attributes_id, temp, JSPROP_ENUMERATE)) {
645
0
        return false;
646
0
      }
647
0
      break;
648
0
    }
649
0
650
0
    uint32_t length = currentValue.Value().Length();
651
0
    JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
652
0
    if (!returnArray) {
653
0
      return false;
654
0
    }
655
0
    // Scope for 'tmp'
656
0
    {
657
0
      JS::Rooted<JS::Value> tmp(cx);
658
0
      for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
659
0
        // Control block to let us common up the JS_DefineElement calls when there
660
0
        // are different ways to succeed at wrapping the object.
661
0
        do {
662
0
          if (!currentValue.Value()[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
663
0
            return false;
664
0
          }
665
0
          break;
666
0
        } while (false);
667
0
        if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
668
0
                              JSPROP_ENUMERATE)) {
669
0
          return false;
670
0
        }
671
0
      }
672
0
    }
673
0
    temp.setObject(*returnArray);
674
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->attributes_id, temp, JSPROP_ENUMERATE)) {
675
0
      return false;
676
0
    }
677
0
    break;
678
0
  } while(false);
679
0
680
0
  do {
681
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
682
0
    JS::Rooted<JS::Value> temp(cx);
683
0
    nsString const & currentValue = mValue;
684
0
    if (!xpc::StringToJsval(cx, currentValue, &temp)) {
685
0
      return false;
686
0
    }
687
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->value_id, temp, JSPROP_ENUMERATE)) {
688
0
      return false;
689
0
    }
690
0
    break;
691
0
  } while(false);
692
0
693
0
  return true;
694
0
}
695
696
bool
697
L10nValue::ToJSON(nsAString& aJSON) const
698
0
{
699
0
  AutoJSAPI jsapi;
700
0
  jsapi.Init();
701
0
  JSContext *cx = jsapi.cx();
702
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
703
0
  // because we'll only be creating objects, in ways that have no
704
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
705
0
  // which likewise guarantees no side-effects for the sorts of
706
0
  // things we will pass it.
707
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
708
0
  JS::Rooted<JS::Value> val(cx);
709
0
  if (!ToObjectInternal(cx, &val)) {
710
0
    return false;
711
0
  }
712
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
713
0
  return StringifyToJSON(cx, obj, aJSON);
714
0
}
715
716
void
717
L10nValue::TraceDictionary(JSTracer* trc)
718
0
{
719
0
}
720
721
L10nValue&
722
L10nValue::operator=(const L10nValue& aOther)
723
0
{
724
0
  DictionaryBase::operator=(aOther);
725
0
  mAttributes = aOther.mAttributes;
726
0
  mValue = aOther.mValue;
727
0
  return *this;
728
0
}
729
730
namespace binding_detail {
731
} // namespace binding_detail
732
733
734
already_AddRefed<Promise>
735
L10nCallback::Call(JSContext* cx, JS::Handle<JS::Value> aThisVal, const Sequence<L10nElement>& l10nElements, ErrorResult& aRv)
736
0
{
737
0
  JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
738
0
  JS::AutoValueVector argv(cx);
739
0
  if (!argv.resize(1)) {
740
0
    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
741
0
    return nullptr;
742
0
  }
743
0
  unsigned argc = 1;
744
0
745
0
  do {
746
0
747
0
    uint32_t length = l10nElements.Length();
748
0
    JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
749
0
    if (!returnArray) {
750
0
      aRv.Throw(NS_ERROR_UNEXPECTED);
751
0
      return nullptr;
752
0
    }
753
0
    // Scope for 'tmp'
754
0
    {
755
0
      JS::Rooted<JS::Value> tmp(cx);
756
0
      for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
757
0
        // Control block to let us common up the JS_DefineElement calls when there
758
0
        // are different ways to succeed at wrapping the object.
759
0
        do {
760
0
          if (!l10nElements[sequenceIdx0].ToObjectInternal(cx, &tmp)) {
761
0
            aRv.Throw(NS_ERROR_UNEXPECTED);
762
0
            return nullptr;
763
0
          }
764
0
          break;
765
0
        } while (false);
766
0
        if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
767
0
                              JSPROP_ENUMERATE)) {
768
0
          aRv.Throw(NS_ERROR_UNEXPECTED);
769
0
          return nullptr;
770
0
        }
771
0
      }
772
0
    }
773
0
    argv[0].setObject(*returnArray);
774
0
    break;
775
0
  } while (false);
776
0
777
0
  JS::Rooted<JS::Value> callable(cx, JS::ObjectValue(*mCallback));
778
0
  if (!JS::Call(cx, aThisVal, callable,
779
0
                JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
780
0
    aRv.NoteJSContextException(cx);
781
0
    return nullptr;
782
0
  }
783
0
  RefPtr<Promise> rvalDecl;
784
0
  { // Scope for our GlobalObject, FastErrorResult, JSAutoRealm,
785
0
    // etc.
786
0
787
0
    JS::Rooted<JSObject*> globalObj(cx);
788
0
    // We basically want our entry global here.  Play it safe
789
0
    // and use GetEntryGlobal() to get it, with whatever
790
0
    // principal-clamping it ends up doing.
791
0
    globalObj = GetEntryGlobal()->GetGlobalJSObject();
792
0
    JSAutoRealm ar(cx, globalObj);
793
0
    GlobalObject promiseGlobal(cx, globalObj);
794
0
    if (promiseGlobal.Failed()) {
795
0
      aRv.Throw(NS_ERROR_UNEXPECTED);
796
0
      return nullptr;
797
0
    }
798
0
799
0
    JS::Rooted<JS::Value> valueToResolve(cx, rval);
800
0
    if (!JS_WrapValue(cx, &valueToResolve)) {
801
0
      aRv.Throw(NS_ERROR_UNEXPECTED);
802
0
      return nullptr;
803
0
    }
804
0
    binding_detail::FastErrorResult promiseRv;
805
0
    nsCOMPtr<nsIGlobalObject> global =
806
0
      do_QueryInterface(promiseGlobal.GetAsSupports());
807
0
    if (!global) {
808
0
      promiseRv.ThrowWithCustomCleanup(NS_ERROR_UNEXPECTED);
809
0
      MOZ_ALWAYS_TRUE(promiseRv.MaybeSetPendingException(cx));
810
0
      aRv.Throw(NS_ERROR_UNEXPECTED);
811
0
      return nullptr;
812
0
    }
813
0
    rvalDecl = Promise::Resolve(global, cx, valueToResolve,
814
0
                                    promiseRv);
815
0
    if (promiseRv.MaybeSetPendingException(cx)) {
816
0
      aRv.Throw(NS_ERROR_UNEXPECTED);
817
0
      return nullptr;
818
0
    }
819
0
  }
820
0
  return rvalDecl.forget();
821
0
}
822
823
824
825
namespace binding_detail {
826
} // namespace binding_detail
827
828
829
} // namespace dom
830
} // namespace mozilla