Coverage Report

Created: 2018-09-25 14:53

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