Coverage Report

Created: 2018-09-25 14:53

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