Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dom/bindings/TextDecoderBinding.cpp
Line
Count
Source (jump to first uncovered line)
1
/* THIS FILE IS AUTOGENERATED FROM TextDecoder.webidl BY Codegen.py - DO NOT EDIT */
2
3
#include "AtomList.h"
4
#include "TextDecoderBinding.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/NonRefcountedDOMObject.h"
10
#include "mozilla/dom/PrimitiveConversions.h"
11
#include "mozilla/dom/ScriptSettings.h"
12
#include "mozilla/dom/SimpleGlobalObject.h"
13
#include "mozilla/dom/TextDecoder.h"
14
#include "mozilla/dom/UnionConversions.h"
15
#include "mozilla/dom/UnionTypes.h"
16
#include "mozilla/dom/XrayExpandoClass.h"
17
18
namespace mozilla {
19
namespace dom {
20
21
namespace binding_detail {}; // Just to make sure it's known as a namespace
22
using namespace mozilla::dom::binding_detail;
23
24
25
26
TextDecodeOptions::TextDecodeOptions()
27
0
{
28
0
  // Safe to pass a null context if we pass a null value
29
0
  Init(nullptr, JS::NullHandleValue);
30
0
}
31
32
33
34
bool
35
TextDecodeOptions::InitIds(JSContext* cx, TextDecodeOptionsAtoms* atomsCache)
36
0
{
37
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
38
0
39
0
  // Initialize these in reverse order so that any failure leaves the first one
40
0
  // uninitialized.
41
0
  if (!atomsCache->stream_id.init(cx, "stream")) {
42
0
    return false;
43
0
  }
44
0
  return true;
45
0
}
46
47
bool
48
TextDecodeOptions::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
49
0
{
50
0
  // Passing a null JSContext is OK only if we're initing from null,
51
0
  // Since in that case we will not have to do any property gets
52
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
53
0
  // checkers by static analysis tools
54
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
55
0
  TextDecodeOptionsAtoms* atomsCache = nullptr;
56
0
  if (cx) {
57
0
    atomsCache = GetAtomCache<TextDecodeOptionsAtoms>(cx);
58
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
59
0
      return false;
60
0
    }
61
0
  }
62
0
63
0
  if (!IsConvertibleToDictionary(val)) {
64
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
65
0
  }
66
0
67
0
  bool isNull = val.isNullOrUndefined();
68
0
  // We only need these if !isNull, in which case we have |cx|.
69
0
  Maybe<JS::Rooted<JSObject *> > object;
70
0
  Maybe<JS::Rooted<JS::Value> > temp;
71
0
  if (!isNull) {
72
0
    MOZ_ASSERT(cx);
73
0
    object.emplace(cx, &val.toObject());
74
0
    temp.emplace(cx);
75
0
  }
76
0
  if (!isNull) {
77
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->stream_id, temp.ptr())) {
78
0
      return false;
79
0
    }
80
0
  }
81
0
  if (!isNull && !temp->isUndefined()) {
82
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mStream)) {
83
0
      return false;
84
0
    }
85
0
  } else {
86
0
    mStream = false;
87
0
  }
88
0
  mIsAnyMemberPresent = true;
89
0
  return true;
90
0
}
91
92
bool
93
TextDecodeOptions::Init(const nsAString& aJSON)
94
0
{
95
0
  AutoJSAPI jsapi;
96
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
97
0
  if (!cleanGlobal) {
98
0
    return false;
99
0
  }
100
0
  if (!jsapi.Init(cleanGlobal)) {
101
0
    return false;
102
0
  }
103
0
  JSContext* cx = jsapi.cx();
104
0
  JS::Rooted<JS::Value> json(cx);
105
0
  bool ok = ParseJSON(cx, aJSON, &json);
106
0
  NS_ENSURE_TRUE(ok, false);
107
0
  return Init(cx, json);
108
0
}
109
110
bool
111
TextDecodeOptions::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
112
0
{
113
0
  TextDecodeOptionsAtoms* atomsCache = GetAtomCache<TextDecodeOptionsAtoms>(cx);
114
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
115
0
    return false;
116
0
  }
117
0
118
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
119
0
  if (!obj) {
120
0
    return false;
121
0
  }
122
0
  rval.set(JS::ObjectValue(*obj));
123
0
124
0
  do {
125
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
126
0
    JS::Rooted<JS::Value> temp(cx);
127
0
    bool const & currentValue = mStream;
128
0
    temp.setBoolean(currentValue);
129
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->stream_id, temp, JSPROP_ENUMERATE)) {
130
0
      return false;
131
0
    }
132
0
    break;
133
0
  } while(false);
134
0
135
0
  return true;
136
0
}
137
138
bool
139
TextDecodeOptions::ToJSON(nsAString& aJSON) const
140
0
{
141
0
  AutoJSAPI jsapi;
142
0
  jsapi.Init();
143
0
  JSContext *cx = jsapi.cx();
144
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
145
0
  // because we'll only be creating objects, in ways that have no
146
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
147
0
  // which likewise guarantees no side-effects for the sorts of
148
0
  // things we will pass it.
149
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
150
0
  JS::Rooted<JS::Value> val(cx);
151
0
  if (!ToObjectInternal(cx, &val)) {
152
0
    return false;
153
0
  }
154
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
155
0
  return StringifyToJSON(cx, obj, aJSON);
156
0
}
157
158
void
159
TextDecodeOptions::TraceDictionary(JSTracer* trc)
160
0
{
161
0
}
162
163
TextDecodeOptions&
164
TextDecodeOptions::operator=(const TextDecodeOptions& aOther)
165
0
{
166
0
  DictionaryBase::operator=(aOther);
167
0
  mStream = aOther.mStream;
168
0
  return *this;
169
0
}
170
171
namespace binding_detail {
172
} // namespace binding_detail
173
174
175
176
TextDecoderOptions::TextDecoderOptions()
177
0
{
178
0
  // Safe to pass a null context if we pass a null value
179
0
  Init(nullptr, JS::NullHandleValue);
180
0
}
181
182
183
184
bool
185
TextDecoderOptions::InitIds(JSContext* cx, TextDecoderOptionsAtoms* atomsCache)
186
0
{
187
0
  MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
188
0
189
0
  // Initialize these in reverse order so that any failure leaves the first one
190
0
  // uninitialized.
191
0
  if (!atomsCache->ignoreBOM_id.init(cx, "ignoreBOM") ||
192
0
      !atomsCache->fatal_id.init(cx, "fatal")) {
193
0
    return false;
194
0
  }
195
0
  return true;
196
0
}
197
198
bool
199
TextDecoderOptions::Init(JSContext* cx, JS::Handle<JS::Value> val, const char* sourceDescription, bool passedToJSImpl)
200
0
{
201
0
  // Passing a null JSContext is OK only if we're initing from null,
202
0
  // Since in that case we will not have to do any property gets
203
0
  // Also evaluate isNullOrUndefined in order to avoid false-positive
204
0
  // checkers by static analysis tools
205
0
  MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined());
206
0
  TextDecoderOptionsAtoms* atomsCache = nullptr;
207
0
  if (cx) {
208
0
    atomsCache = GetAtomCache<TextDecoderOptionsAtoms>(cx);
209
0
    if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
210
0
      return false;
211
0
    }
212
0
  }
213
0
214
0
  if (!IsConvertibleToDictionary(val)) {
215
0
    return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
216
0
  }
217
0
218
0
  bool isNull = val.isNullOrUndefined();
219
0
  // We only need these if !isNull, in which case we have |cx|.
220
0
  Maybe<JS::Rooted<JSObject *> > object;
221
0
  Maybe<JS::Rooted<JS::Value> > temp;
222
0
  if (!isNull) {
223
0
    MOZ_ASSERT(cx);
224
0
    object.emplace(cx, &val.toObject());
225
0
    temp.emplace(cx);
226
0
  }
227
0
  if (!isNull) {
228
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->fatal_id, temp.ptr())) {
229
0
      return false;
230
0
    }
231
0
  }
232
0
  if (!isNull && !temp->isUndefined()) {
233
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mFatal)) {
234
0
      return false;
235
0
    }
236
0
  } else {
237
0
    mFatal = false;
238
0
  }
239
0
  mIsAnyMemberPresent = true;
240
0
241
0
  if (!isNull) {
242
0
    if (!JS_GetPropertyById(cx, *object, atomsCache->ignoreBOM_id, temp.ptr())) {
243
0
      return false;
244
0
    }
245
0
  }
246
0
  if (!isNull && !temp->isUndefined()) {
247
0
    if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), &mIgnoreBOM)) {
248
0
      return false;
249
0
    }
250
0
  } else {
251
0
    mIgnoreBOM = false;
252
0
  }
253
0
  mIsAnyMemberPresent = true;
254
0
  return true;
255
0
}
256
257
bool
258
TextDecoderOptions::Init(const nsAString& aJSON)
259
0
{
260
0
  AutoJSAPI jsapi;
261
0
  JSObject* cleanGlobal = SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
262
0
  if (!cleanGlobal) {
263
0
    return false;
264
0
  }
265
0
  if (!jsapi.Init(cleanGlobal)) {
266
0
    return false;
267
0
  }
268
0
  JSContext* cx = jsapi.cx();
269
0
  JS::Rooted<JS::Value> json(cx);
270
0
  bool ok = ParseJSON(cx, aJSON, &json);
271
0
  NS_ENSURE_TRUE(ok, false);
272
0
  return Init(cx, json);
273
0
}
274
275
bool
276
TextDecoderOptions::ToObjectInternal(JSContext* cx, JS::MutableHandle<JS::Value> rval) const
277
0
{
278
0
  TextDecoderOptionsAtoms* atomsCache = GetAtomCache<TextDecoderOptionsAtoms>(cx);
279
0
  if (!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) {
280
0
    return false;
281
0
  }
282
0
283
0
  JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
284
0
  if (!obj) {
285
0
    return false;
286
0
  }
287
0
  rval.set(JS::ObjectValue(*obj));
288
0
289
0
  do {
290
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
291
0
    JS::Rooted<JS::Value> temp(cx);
292
0
    bool const & currentValue = mFatal;
293
0
    temp.setBoolean(currentValue);
294
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->fatal_id, temp, JSPROP_ENUMERATE)) {
295
0
      return false;
296
0
    }
297
0
    break;
298
0
  } while(false);
299
0
300
0
  do {
301
0
    // block for our 'break' successCode and scope for 'temp' and 'currentValue'
302
0
    JS::Rooted<JS::Value> temp(cx);
303
0
    bool const & currentValue = mIgnoreBOM;
304
0
    temp.setBoolean(currentValue);
305
0
    if (!JS_DefinePropertyById(cx, obj, atomsCache->ignoreBOM_id, temp, JSPROP_ENUMERATE)) {
306
0
      return false;
307
0
    }
308
0
    break;
309
0
  } while(false);
310
0
311
0
  return true;
312
0
}
313
314
bool
315
TextDecoderOptions::ToJSON(nsAString& aJSON) const
316
0
{
317
0
  AutoJSAPI jsapi;
318
0
  jsapi.Init();
319
0
  JSContext *cx = jsapi.cx();
320
0
  // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
321
0
  // because we'll only be creating objects, in ways that have no
322
0
  // side-effects, followed by a call to JS::ToJSONMaybeSafely,
323
0
  // which likewise guarantees no side-effects for the sorts of
324
0
  // things we will pass it.
325
0
  JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
326
0
  JS::Rooted<JS::Value> val(cx);
327
0
  if (!ToObjectInternal(cx, &val)) {
328
0
    return false;
329
0
  }
330
0
  JS::Rooted<JSObject*> obj(cx, &val.toObject());
331
0
  return StringifyToJSON(cx, obj, aJSON);
332
0
}
333
334
void
335
TextDecoderOptions::TraceDictionary(JSTracer* trc)
336
0
{
337
0
}
338
339
TextDecoderOptions&
340
TextDecoderOptions::operator=(const TextDecoderOptions& aOther)
341
0
{
342
0
  DictionaryBase::operator=(aOther);
343
0
  mFatal = aOther.mFatal;
344
0
  mIgnoreBOM = aOther.mIgnoreBOM;
345
0
  return *this;
346
0
}
347
348
namespace binding_detail {
349
} // namespace binding_detail
350
351
352
namespace TextDecoder_Binding {
353
354
MOZ_CAN_RUN_SCRIPT static bool
355
get_encoding(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TextDecoder* self, JSJitGetterCallArgs args)
356
0
{
357
0
  AUTO_PROFILER_LABEL_FAST("get TextDecoder.encoding", DOM, cx);
358
0
359
0
  DOMString result;
360
0
  self->GetEncoding(result);
361
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
362
0
  if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) {
363
0
    return false;
364
0
  }
365
0
  return true;
366
0
}
367
368
static const JSJitInfo encoding_getterinfo = {
369
  { (JSJitGetterOp)get_encoding },
370
  { prototypes::id::TextDecoder },
371
  { PrototypeTraits<prototypes::id::TextDecoder>::Depth },
372
  JSJitInfo::Getter,
373
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
374
  JSVAL_TYPE_STRING,  /* returnType.  Not relevant for setters. */
375
  false,  /* isInfallible. False in setters. */
376
  true,  /* isMovable.  Not relevant for setters. */
377
  true, /* isEliminatable.  Not relevant for setters. */
378
  false, /* isAlwaysInSlot.  Only relevant for getters. */
379
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
380
  false,  /* isTypedMethod.  Only relevant for methods. */
381
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
382
};
383
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
384
static_assert(0 < 1, "There is no slot for us");
385
386
MOZ_CAN_RUN_SCRIPT static bool
387
get_fatal(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TextDecoder* self, JSJitGetterCallArgs args)
388
0
{
389
0
  AUTO_PROFILER_LABEL_FAST("get TextDecoder.fatal", DOM, cx);
390
0
391
0
  bool result(self->Fatal());
392
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
393
0
  args.rval().setBoolean(result);
394
0
  return true;
395
0
}
396
397
static const JSJitInfo fatal_getterinfo = {
398
  { (JSJitGetterOp)get_fatal },
399
  { prototypes::id::TextDecoder },
400
  { PrototypeTraits<prototypes::id::TextDecoder>::Depth },
401
  JSJitInfo::Getter,
402
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
403
  JSVAL_TYPE_BOOLEAN,  /* returnType.  Not relevant for setters. */
404
  true,  /* isInfallible. False in setters. */
405
  true,  /* isMovable.  Not relevant for setters. */
406
  true, /* isEliminatable.  Not relevant for setters. */
407
  false, /* isAlwaysInSlot.  Only relevant for getters. */
408
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
409
  false,  /* isTypedMethod.  Only relevant for methods. */
410
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
411
};
412
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
413
static_assert(0 < 1, "There is no slot for us");
414
415
MOZ_CAN_RUN_SCRIPT static bool
416
get_ignoreBOM(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TextDecoder* self, JSJitGetterCallArgs args)
417
0
{
418
0
  AUTO_PROFILER_LABEL_FAST("get TextDecoder.ignoreBOM", DOM, cx);
419
0
420
0
  bool result(self->IgnoreBOM());
421
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
422
0
  args.rval().setBoolean(result);
423
0
  return true;
424
0
}
425
426
static const JSJitInfo ignoreBOM_getterinfo = {
427
  { (JSJitGetterOp)get_ignoreBOM },
428
  { prototypes::id::TextDecoder },
429
  { PrototypeTraits<prototypes::id::TextDecoder>::Depth },
430
  JSJitInfo::Getter,
431
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
432
  JSVAL_TYPE_BOOLEAN,  /* returnType.  Not relevant for setters. */
433
  true,  /* isInfallible. False in setters. */
434
  true,  /* isMovable.  Not relevant for setters. */
435
  true, /* isEliminatable.  Not relevant for setters. */
436
  false, /* isAlwaysInSlot.  Only relevant for getters. */
437
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
438
  false,  /* isTypedMethod.  Only relevant for methods. */
439
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
440
};
441
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
442
static_assert(0 < 1, "There is no slot for us");
443
444
MOZ_CAN_RUN_SCRIPT static bool
445
decode(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TextDecoder* self, const JSJitMethodCallArgs& args)
446
0
{
447
0
  AUTO_PROFILER_LABEL_FAST("TextDecoder.decode", DOM, cx);
448
0
449
0
  Optional<ArrayBufferViewOrArrayBuffer> arg0;
450
0
  Maybe<ArrayBufferViewOrArrayBufferArgument> arg0_holder;
451
0
  if (args.hasDefined(0)) {
452
0
    arg0.Construct();
453
0
    arg0_holder.emplace(arg0.Value());
454
0
    {
455
0
      bool done = false, failed = false, tryNext;
456
0
      if (args[0].isObject()) {
457
0
        done = (failed = !arg0_holder.ref().TrySetToArrayBufferView(cx, args[0], tryNext, false)) || !tryNext ||
458
0
               (failed = !arg0_holder.ref().TrySetToArrayBuffer(cx, args[0], tryNext, false)) || !tryNext;
459
0
460
0
      }
461
0
      if (failed) {
462
0
        return false;
463
0
      }
464
0
      if (!done) {
465
0
        ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 1 of TextDecoder.decode", "ArrayBufferView, ArrayBuffer");
466
0
        return false;
467
0
      }
468
0
    }
469
0
  }
470
0
  binding_detail::FastTextDecodeOptions arg1;
471
0
  if (!arg1.Init(cx, (args.hasDefined(1)) ? args[1] : JS::NullHandleValue,  "Argument 2 of TextDecoder.decode", false)) {
472
0
    return false;
473
0
  }
474
0
  FastErrorResult rv;
475
0
  DOMString result;
476
0
  self->Decode(Constify(arg0), Constify(arg1), result, rv);
477
0
  if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
478
0
    return false;
479
0
  }
480
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
481
0
  if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) {
482
0
    return false;
483
0
  }
484
0
  return true;
485
0
}
486
487
static const JSJitInfo decode_methodinfo = {
488
  { (JSJitGetterOp)decode },
489
  { prototypes::id::TextDecoder },
490
  { PrototypeTraits<prototypes::id::TextDecoder>::Depth },
491
  JSJitInfo::Method,
492
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
493
  JSVAL_TYPE_STRING,  /* returnType.  Not relevant for setters. */
494
  false,  /* isInfallible. False in setters. */
495
  false,  /* isMovable.  Not relevant for setters. */
496
  false, /* isEliminatable.  Not relevant for setters. */
497
  false, /* isAlwaysInSlot.  Only relevant for getters. */
498
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
499
  false,  /* isTypedMethod.  Only relevant for methods. */
500
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
501
};
502
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
503
static_assert(0 < 1, "There is no slot for us");
504
505
static void
506
_finalize(js::FreeOp* fop, JSObject* obj)
507
0
{
508
0
  mozilla::dom::TextDecoder* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TextDecoder>(obj);
509
0
  if (self) {
510
0
    AddForDeferredFinalization<mozilla::dom::TextDecoder>(self);
511
0
  }
512
0
}
513
514
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
515
#if defined(__clang__)
516
#pragma clang diagnostic push
517
#pragma clang diagnostic ignored "-Wmissing-braces"
518
#endif
519
static const JSFunctionSpec sMethods_specs[] = {
520
  JS_FNSPEC("decode", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&decode_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
521
  JS_FS_END
522
};
523
#if defined(__clang__)
524
#pragma clang diagnostic pop
525
#endif
526
527
528
static const Prefable<const JSFunctionSpec> sMethods[] = {
529
  { nullptr, &sMethods_specs[0] },
530
  { nullptr, nullptr }
531
};
532
533
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
534
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
535
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
536
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
537
538
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
539
#if defined(__clang__)
540
#pragma clang diagnostic push
541
#pragma clang diagnostic ignored "-Wmissing-braces"
542
#endif
543
static const JSPropertySpec sAttributes_specs[] = {
544
  { "encoding", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &encoding_getterinfo, nullptr, nullptr },
545
  { "fatal", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &fatal_getterinfo, nullptr, nullptr },
546
  { "ignoreBOM", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &ignoreBOM_getterinfo, nullptr, nullptr },
547
  { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
548
};
549
#if defined(__clang__)
550
#pragma clang diagnostic pop
551
#endif
552
553
554
static const Prefable<const JSPropertySpec> sAttributes[] = {
555
  { nullptr, &sAttributes_specs[0] },
556
  { nullptr, nullptr }
557
};
558
559
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
560
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
561
static_assert(3 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
562
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
563
564
565
static uint16_t sNativeProperties_sortedPropertyIndices[4];
566
static PropertyInfo sNativeProperties_propertyInfos[4];
567
568
static const NativePropertiesN<2> sNativeProperties = {
569
  false, 0,
570
  false, 0,
571
  true,  0 /* sMethods */,
572
  true,  1 /* sAttributes */,
573
  false, 0,
574
  false, 0,
575
  false, 0,
576
  -1,
577
  4,
578
  sNativeProperties_sortedPropertyIndices,
579
  {
580
    { sMethods, &sNativeProperties_propertyInfos[0] },
581
    { sAttributes, &sNativeProperties_propertyInfos[1] }
582
  }
583
};
584
static_assert(4 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
585
    "We have a property info count that is oversized");
586
587
static bool
588
_constructor(JSContext* cx, unsigned argc, JS::Value* vp)
589
0
{
590
0
  AUTO_PROFILER_LABEL_FAST("TextDecoder constructor", DOM, cx);
591
0
592
0
  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
593
0
  JS::Rooted<JSObject*> obj(cx, &args.callee());
594
0
  if (!args.isConstructing()) {
595
0
    // XXXbz wish I could get the name from the callee instead of
596
0
    // Adding more relocations
597
0
    return ThrowConstructorWithoutNew(cx, "TextDecoder");
598
0
  }
599
0
600
0
  JS::Rooted<JSObject*> desiredProto(cx);
601
0
  if (!GetDesiredProto(cx, args, &desiredProto)) {
602
0
    return false;
603
0
  }
604
0
605
0
  GlobalObject global(cx, obj);
606
0
  if (global.Failed()) {
607
0
    return false;
608
0
  }
609
0
610
0
  bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
611
0
  binding_detail::FakeString arg0;
612
0
  if (args.hasDefined(0)) {
613
0
    if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
614
0
      return false;
615
0
    }
616
0
  } else {
617
0
    static const char16_t data[] = { 'u', 't', 'f', '-', '8', 0 };
618
0
    arg0.Rebind(data, ArrayLength(data) - 1);
619
0
  }
620
0
  binding_detail::FastTextDecoderOptions arg1;
621
0
  if (!arg1.Init(cx, (args.hasDefined(1)) ? args[1] : JS::NullHandleValue,  "Argument 2 of TextDecoder.constructor", false)) {
622
0
    return false;
623
0
  }
624
0
  Maybe<JSAutoRealm> ar;
625
0
  if (objIsXray) {
626
0
    obj = js::CheckedUnwrap(obj);
627
0
    if (!obj) {
628
0
      return false;
629
0
    }
630
0
    ar.emplace(cx, obj);
631
0
    if (!JS_WrapObject(cx, &desiredProto)) {
632
0
      return false;
633
0
    }
634
0
  }
635
0
  FastErrorResult rv;
636
0
  auto result(StrongOrRawPtr<mozilla::dom::TextDecoder>(mozilla::dom::TextDecoder::Constructor(global, NonNullHelper(Constify(arg0)), Constify(arg1), rv)));
637
0
  if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
638
0
    return false;
639
0
  }
640
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
641
0
  static_assert(!IsPointer<decltype(result)>::value,
642
0
                "NewObject implies that we need to keep the object alive with a strong reference.");
643
0
  if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval(), desiredProto)) {
644
0
    MOZ_ASSERT(JS_IsExceptionPending(cx));
645
0
    return false;
646
0
  }
647
0
  return true;
648
0
}
649
650
static const js::ClassOps sInterfaceObjectClassOps = {
651
    nullptr,               /* addProperty */
652
    nullptr,               /* delProperty */
653
    nullptr,               /* enumerate */
654
    nullptr,               /* newEnumerate */
655
    nullptr,               /* resolve */
656
    nullptr,               /* mayResolve */
657
    nullptr,               /* finalize */
658
    _constructor, /* call */
659
    nullptr,               /* hasInstance */
660
    _constructor, /* construct */
661
    nullptr,               /* trace */
662
};
663
664
static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
665
  {
666
    "Function",
667
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
668
    &sInterfaceObjectClassOps,
669
    JS_NULL_CLASS_SPEC,
670
    JS_NULL_CLASS_EXT,
671
    &sInterfaceObjectClassObjectOps
672
  },
673
  eInterface,
674
  true,
675
  prototypes::id::TextDecoder,
676
  PrototypeTraits<prototypes::id::TextDecoder>::Depth,
677
  sNativePropertyHooks,
678
  "function TextDecoder() {\n    [native code]\n}",
679
  JS::GetRealmFunctionPrototype
680
};
681
682
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
683
  {
684
    "TextDecoderPrototype",
685
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
686
    JS_NULL_CLASS_OPS,
687
    JS_NULL_CLASS_SPEC,
688
    JS_NULL_CLASS_EXT,
689
    JS_NULL_OBJECT_OPS
690
  },
691
  eInterfacePrototype,
692
  false,
693
  prototypes::id::TextDecoder,
694
  PrototypeTraits<prototypes::id::TextDecoder>::Depth,
695
  sNativePropertyHooks,
696
  "[object TextDecoderPrototype]",
697
  JS::GetRealmObjectPrototype
698
};
699
700
static const js::ClassOps sClassOps = {
701
  nullptr, /* addProperty */
702
  nullptr,               /* delProperty */
703
  nullptr,               /* enumerate */
704
  nullptr, /* newEnumerate */
705
  nullptr, /* resolve */
706
  nullptr, /* mayResolve */
707
  _finalize, /* finalize */
708
  nullptr, /* call */
709
  nullptr,               /* hasInstance */
710
  nullptr,               /* construct */
711
  nullptr, /* trace */
712
};
713
714
static const js::ClassExtension sClassExtension = {
715
  nullptr, /* weakmapKeyDelegateOp */
716
  nullptr /* objectMovedOp */
717
};
718
719
static const DOMJSClass sClass = {
720
  { "TextDecoder",
721
    JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
722
    &sClassOps,
723
    JS_NULL_CLASS_SPEC,
724
    &sClassExtension,
725
    JS_NULL_OBJECT_OPS
726
  },
727
  { prototypes::id::TextDecoder, 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 },
728
  IsBaseOf<nsISupports, mozilla::dom::TextDecoder >::value,
729
  sNativePropertyHooks,
730
  FindAssociatedGlobalForNative<mozilla::dom::TextDecoder>::Get,
731
  GetProtoObjectHandle,
732
  GetCCParticipant<mozilla::dom::TextDecoder>::Get()
733
};
734
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
735
              "Must have the right minimal number of reserved slots.");
736
static_assert(1 >= 1,
737
              "Must have enough reserved slots.");
738
739
const JSClass*
740
GetJSClass()
741
0
{
742
0
  return sClass.ToJSClass();
743
0
}
744
745
bool
746
Wrap(JSContext* aCx, mozilla::dom::TextDecoder* aObject, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
747
0
{
748
0
  MOZ_ASSERT(static_cast<mozilla::dom::TextDecoder*>(aObject) ==
749
0
             reinterpret_cast<mozilla::dom::TextDecoder*>(aObject),
750
0
             "Multiple inheritance for mozilla::dom::TextDecoder is broken.");
751
0
  MOZ_ASSERT(ToSupportsIsCorrect(aObject));
752
0
  MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
753
0
754
0
  JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
755
0
  JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
756
0
  if (!canonicalProto) {
757
0
    return false;
758
0
  }
759
0
  JS::Rooted<JSObject*> proto(aCx);
760
0
  if (aGivenProto) {
761
0
    proto = aGivenProto;
762
0
    // Unfortunately, while aGivenProto was in the compartment of aCx
763
0
    // coming in, we changed compartments to that of "parent" so may need
764
0
    // to wrap the proto here.
765
0
    if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
766
0
      if (!JS_WrapObject(aCx, &proto)) {
767
0
        return false;
768
0
      }
769
0
    }
770
0
  } else {
771
0
    proto = canonicalProto;
772
0
  }
773
0
774
0
  BindingJSObjectCreator<mozilla::dom::TextDecoder> creator(aCx);
775
0
  creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
776
0
  if (!aReflector) {
777
0
    return false;
778
0
  }
779
0
780
0
781
0
782
0
  creator.InitializationSucceeded();
783
0
  return true;
784
0
}
785
786
const NativePropertyHooks sNativePropertyHooks[] = { {
787
  nullptr,
788
  nullptr,
789
  nullptr,
790
  { sNativeProperties.Upcast(), nullptr },
791
  prototypes::id::TextDecoder,
792
  constructors::id::TextDecoder,
793
  nullptr,
794
  &DefaultXrayExpandoObjectClass
795
} };
796
797
void
798
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
799
0
{
800
0
  JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
801
0
  if (!parentProto) {
802
0
    return;
803
0
  }
804
0
805
0
  JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
806
0
  if (!constructorProto) {
807
0
    return;
808
0
  }
809
0
810
0
  static bool sIdsInited = false;
811
0
  if (!sIdsInited && NS_IsMainThread()) {
812
0
    if (!InitIds(aCx, sNativeProperties.Upcast())) {
813
0
      return;
814
0
    }
815
0
    sIdsInited = true;
816
0
  }
817
0
818
0
  JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TextDecoder);
819
0
  JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TextDecoder);
820
0
  dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
821
0
                              &sPrototypeClass.mBase, protoCache,
822
0
                              nullptr,
823
0
                              constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
824
0
                              interfaceCache,
825
0
                              sNativeProperties.Upcast(),
826
0
                              nullptr,
827
0
                              "TextDecoder", aDefineOnGlobal,
828
0
                              nullptr,
829
0
                              false);
830
0
}
831
832
JSObject*
833
GetConstructorObject(JSContext* aCx)
834
0
{
835
0
  return GetConstructorObjectHandle(aCx);
836
0
}
837
838
} // namespace TextDecoder_Binding
839
840
841
842
} // namespace dom
843
} // namespace mozilla