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