/* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */ void js::ReportUsageError(JSContext *cx, HandleObject callee, const char *msg) { const char *usageStr = "usage"; PropertyName *usageAtom = Atomize(cx, usageStr, strlen(usageStr))->asPropertyName(); RootedId id(cx, NameToId(usageAtom)); DebugOnly<Shape *> shape = static_cast<Shape *>(callee->nativeLookup(cx, id)); JS_ASSERT(!shape->configurable()); JS_ASSERT(!shape->writable()); JS_ASSERT(shape->hasDefaultGetter()); RootedValue usage(cx); if (!JS_LookupProperty(cx, callee, "usage", &usage)) return; if (usage.isUndefined()) { JS_ReportError(cx, "%s", msg); } else { JSString *str = usage.toString(); JS::Anchor<JSString *> a_str(str); const jschar *chars = JS_GetStringCharsZ(cx, str); if (!chars) return; JS_ReportError(cx, "%s. Usage: %hs", msg, chars); } }
void nsFileInputStream::Serialize(InputStreamParams& aParams, FileDescriptorArray& aFileDescriptors) { FileInputStreamParams params; if (mFD) { FileHandleType fd = FileHandleType(PR_FileDesc2NativeHandle(mFD)); NS_ASSERTION(fd, "This should never be null!"); DebugOnly<FileDescriptor*> dbgFD = aFileDescriptors.AppendElement(fd); NS_ASSERTION(dbgFD->IsValid(), "Sending an invalid file descriptor!"); params.fileDescriptorIndex() = aFileDescriptors.Length() - 1; Close(); } else { NS_WARNING("This file has not been opened (or could not be opened). " "Sending an invalid file descriptor to the other process!"); params.fileDescriptorIndex() = UINT32_MAX; } int32_t behaviorFlags = mBehaviorFlags; // The receiving process (or thread) is going to have an open file // descriptor automatically so transferring this flag is meaningless. behaviorFlags &= ~nsIFileInputStream::DEFER_OPEN; params.behaviorFlags() = behaviorFlags; params.ioFlags() = mIOFlags; aParams = params; }
/* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */ void ReportUsageError(JSContext *cx, JSObject *callee, const char *msg) { const char *usageStr = "usage"; PropertyName *usageAtom = js_Atomize(cx, usageStr, strlen(usageStr))->asPropertyName(); DebugOnly<Shape *> shape = callee->nativeLookup(cx, NameToId(usageAtom)); JS_ASSERT(!shape->configurable()); JS_ASSERT(!shape->writable()); JS_ASSERT(shape->hasDefaultGetter()); jsval usage; if (!JS_LookupProperty(cx, callee, "usage", &usage)) return; if (JSVAL_IS_VOID(usage)) { JS_ReportError(cx, "%s", msg); } else { JSString *str = JSVAL_TO_STRING(usage); JS::Anchor<JSString *> a_str(str); const jschar *chars = JS_GetStringCharsZ(cx, str); if (!chars) return; JS_ReportError(cx, "%s. Usage: %hs", msg, chars); } }
void GCMarker::checkZone(void* p) { MOZ_ASSERT(started); DebugOnly<Cell*> cell = static_cast<Cell*>(p); MOZ_ASSERT_IF(cell->isTenured(), cell->asTenured().zone()->isCollecting()); }
/* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */ void js::ReportUsageError(JSContext *cx, HandleObject callee, const char *msg) { const char *usageStr = "usage"; PropertyName *usageAtom = Atomize(cx, usageStr, strlen(usageStr))->asPropertyName(); RootedId id(cx, NameToId(usageAtom)); DebugOnly<Shape *> shape = static_cast<Shape *>(callee->as<NativeObject>().lookup(cx, id)); MOZ_ASSERT(!shape->configurable()); MOZ_ASSERT(!shape->writable()); MOZ_ASSERT(shape->hasDefaultGetter()); RootedValue usage(cx); if (!JS_LookupProperty(cx, callee, "usage", &usage)) return; if (usage.isUndefined()) { JS_ReportError(cx, "%s", msg); } else { JSString *str = usage.toString(); if (!str->ensureFlat(cx)) return; AutoStableStringChars chars(cx); if (!chars.initTwoByte(cx, str)) return; JS_ReportError(cx, "%s. Usage: %hs", msg, chars.twoByteRange().start().get()); } }
/* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */ void js::ReportUsageErrorASCII(JSContext* cx, HandleObject callee, const char* msg) { const char* usageStr = "usage"; PropertyName* usageAtom = Atomize(cx, usageStr, strlen(usageStr))->asPropertyName(); RootedId id(cx, NameToId(usageAtom)); DebugOnly<Shape*> shape = static_cast<Shape*>(callee->as<JSFunction>().lookup(cx, id)); MOZ_ASSERT(!shape->configurable()); MOZ_ASSERT(!shape->writable()); MOZ_ASSERT(shape->hasDefaultGetter()); RootedValue usage(cx); if (!JS_GetProperty(cx, callee, "usage", &usage)) return; if (!usage.isString()) { JS_ReportErrorASCII(cx, "%s", msg); } else { RootedString usageStr(cx, usage.toString()); JSAutoByteString str; if (!str.encodeUtf8(cx, usageStr)) return; JS_ReportErrorUTF8(cx, "%s. Usage: %s", msg, str.ptr()); } }
JSObject * RegExpCompartment::createMatchResultTemplateObject(JSContext *cx) { JS_ASSERT(!matchResultTemplateObject_); /* Create template array object */ RootedObject templateObject(cx, NewDenseUnallocatedArray(cx, 0, nullptr, TenuredObject)); if (!templateObject) return matchResultTemplateObject_; // = nullptr /* Set dummy index property */ RootedValue index(cx, Int32Value(0)); if (!baseops::DefineProperty(cx, templateObject, cx->names().index, index, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE)) return matchResultTemplateObject_; // = nullptr /* Set dummy input property */ RootedValue inputVal(cx, StringValue(cx->runtime()->emptyString)); if (!baseops::DefineProperty(cx, templateObject, cx->names().input, inputVal, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE)) return matchResultTemplateObject_; // = nullptr // Make sure that the properties are in the right slots. DebugOnly<Shape *> shape = templateObject->lastProperty(); JS_ASSERT(shape->previous()->slot() == 0 && shape->previous()->propidRef() == NameToId(cx->names().index)); JS_ASSERT(shape->slot() == 1 && shape->propidRef() == NameToId(cx->names().input)); matchResultTemplateObject_ = templateObject; return matchResultTemplateObject_; }
static inline void CheckMarkedThing(JSTracer *trc, T *thing) { JS_ASSERT(trc); JS_ASSERT(thing); JS_ASSERT(thing->compartment()); JS_ASSERT(thing->compartment()->rt == trc->runtime); JS_ASSERT_IF(IS_GC_MARKING_TRACER(trc), !thing->compartment()->scheduledForDestruction); JS_ASSERT(trc->debugPrinter || trc->debugPrintArg); DebugOnly<JSRuntime *> rt = trc->runtime; #ifdef DEBUG rt->assertValidThread(); #endif JS_ASSERT_IF(thing->compartment()->requireGCTracer(), IS_GC_MARKING_TRACER(trc)); JS_ASSERT(thing->isAligned()); JS_ASSERT_IF(rt->gcStrictCompartmentChecking, thing->compartment()->isCollecting() || thing->compartment() == rt->atomsCompartment); JS_ASSERT_IF(IS_GC_MARKING_TRACER(trc) && ((GCMarker *)trc)->getMarkColor() == GRAY, thing->compartment()->isGCMarkingGray() || thing->compartment() == rt->atomsCompartment); }
void nsTemporaryFileInputStream::Serialize(InputStreamParams& aParams, FileDescriptorArray& aFileDescriptors) { TemporaryFileInputStreamParams params; MutexAutoLock lock(mFileDescOwner->FileMutex()); MOZ_ASSERT(mFileDescOwner->mFD); if (!mClosed) { FileHandleType fd = FileHandleType(PR_FileDesc2NativeHandle(mFileDescOwner->mFD)); NS_ASSERTION(fd, "This should never be null!"); DebugOnly<FileDescriptor*> dbgFD = aFileDescriptors.AppendElement(fd); NS_ASSERTION(dbgFD->IsValid(), "Sending an invalid file descriptor!"); params.fileDescriptorIndex() = aFileDescriptors.Length() - 1; Close(); } else { NS_WARNING("The stream is already closed. " "Sending an invalid file descriptor to the other process!"); params.fileDescriptorIndex() = UINT32_MAX; } params.startPos() = mCurPos; params.endPos() = mEndPos; aParams = params; }
NativeObject* JSCompartment::getOrCreateIterResultTemplateObject(JSContext* cx) { if (iterResultTemplate_) return iterResultTemplate_; // Create template plain object RootedNativeObject templateObject(cx, NewBuiltinClassInstance<PlainObject>(cx, TenuredObject)); if (!templateObject) return iterResultTemplate_; // = nullptr // Create a new group for the template. Rooted<TaggedProto> proto(cx, templateObject->taggedProto()); RootedObjectGroup group(cx, ObjectGroupCompartment::makeGroup(cx, templateObject->getClass(), proto)); if (!group) return iterResultTemplate_; // = nullptr templateObject->setGroup(group); // Set dummy `value` property if (!NativeDefineDataProperty(cx, templateObject, cx->names().value, UndefinedHandleValue, JSPROP_ENUMERATE)) { return iterResultTemplate_; // = nullptr } // Set dummy `done` property if (!NativeDefineDataProperty(cx, templateObject, cx->names().done, TrueHandleValue, JSPROP_ENUMERATE)) { return iterResultTemplate_; // = nullptr } if (!group->unknownProperties()) { // Update `value` property typeset, since it can be any value. HeapTypeSet* types = group->maybeGetProperty(NameToId(cx->names().value)); MOZ_ASSERT(types); { AutoEnterAnalysis enter(cx); types->makeUnknown(cx); } } // Make sure that the properties are in the right slots. DebugOnly<Shape*> shape = templateObject->lastProperty(); MOZ_ASSERT(shape->previous()->slot() == JSCompartment::IterResultObjectValueSlot && shape->previous()->propidRef() == NameToId(cx->names().value)); MOZ_ASSERT(shape->slot() == JSCompartment::IterResultObjectDoneSlot && shape->propidRef() == NameToId(cx->names().done)); iterResultTemplate_.set(templateObject); return iterResultTemplate_; }
void CodeGeneratorX86::visitBox(LBox* box) { const LDefinition* type = box->getDef(TYPE_INDEX); DebugOnly<const LAllocation*> a = box->getOperand(0); MOZ_ASSERT(!a->isConstant()); // On x86, the input operand and the output payload have the same // virtual register. All that needs to be written is the type tag for // the type definition. masm.mov(ImmWord(MIRTypeToTag(box->type())), ToRegister(type)); }
ArrayObject* RegExpCompartment::createMatchResultTemplateObject(JSContext* cx) { MOZ_ASSERT(!matchResultTemplateObject_); /* Create template array object */ RootedArrayObject templateObject(cx, NewDenseUnallocatedArray(cx, RegExpObject::MaxPairCount, nullptr, TenuredObject)); if (!templateObject) return matchResultTemplateObject_; // = nullptr // Create a new group for the template. Rooted<TaggedProto> proto(cx, templateObject->getTaggedProto()); ObjectGroup* group = ObjectGroupCompartment::makeGroup(cx, templateObject->getClass(), proto); if (!group) return matchResultTemplateObject_; // = nullptr templateObject->setGroup(group); /* Set dummy index property */ RootedValue index(cx, Int32Value(0)); if (!NativeDefineProperty(cx, templateObject, cx->names().index, index, nullptr, nullptr, JSPROP_ENUMERATE)) { return matchResultTemplateObject_; // = nullptr } /* Set dummy input property */ RootedValue inputVal(cx, StringValue(cx->runtime()->emptyString)); if (!NativeDefineProperty(cx, templateObject, cx->names().input, inputVal, nullptr, nullptr, JSPROP_ENUMERATE)) { return matchResultTemplateObject_; // = nullptr } // Make sure that the properties are in the right slots. DebugOnly<Shape*> shape = templateObject->lastProperty(); MOZ_ASSERT(shape->previous()->slot() == 0 && shape->previous()->propidRef() == NameToId(cx->names().index)); MOZ_ASSERT(shape->slot() == 1 && shape->propidRef() == NameToId(cx->names().input)); // Make sure type information reflects the indexed properties which might // be added. AddTypePropertyId(cx, templateObject, JSID_VOID, TypeSet::StringType()); AddTypePropertyId(cx, templateObject, JSID_VOID, TypeSet::UndefinedType()); matchResultTemplateObject_.set(templateObject); return matchResultTemplateObject_; }
bool js::CurrentThreadCanAccessZone(Zone *zone) { if (CurrentThreadCanAccessRuntime(zone->runtime_)) return true; if (InParallelSection()) { DebugOnly<PerThreadData *> pt = js::TlsPerThreadData.get(); JS_ASSERT(pt && pt->associatedWith(zone->runtime_)); return true; } // Only zones in use by an exclusive thread can be used off the main thread // or outside of PJS. We don't keep track of which thread owns such zones // though, so this check is imperfect. return zone->usedByExclusiveThread; }
ArrayObject * RegExpCompartment::createMatchResultTemplateObject(JSContext *cx) { MOZ_ASSERT(!matchResultTemplateObject_); /* Create template array object */ RootedArrayObject templateObject(cx, NewDenseUnallocatedArray(cx, 0, nullptr, TenuredObject)); if (!templateObject) return matchResultTemplateObject_; // = nullptr // Create a new type for the template. Rooted<TaggedProto> proto(cx, templateObject->getTaggedProto()); types::TypeObject *type = cx->compartment()->types.newTypeObject(cx, templateObject->getClass(), proto); templateObject->setType(type); /* Set dummy index property */ RootedValue index(cx, Int32Value(0)); if (!baseops::DefineProperty(cx, templateObject, cx->names().index, index, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE)) return matchResultTemplateObject_; // = nullptr /* Set dummy input property */ RootedValue inputVal(cx, StringValue(cx->runtime()->emptyString)); if (!baseops::DefineProperty(cx, templateObject, cx->names().input, inputVal, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE)) return matchResultTemplateObject_; // = nullptr // Make sure that the properties are in the right slots. DebugOnly<Shape *> shape = templateObject->lastProperty(); MOZ_ASSERT(shape->previous()->slot() == 0 && shape->previous()->propidRef() == NameToId(cx->names().index)); MOZ_ASSERT(shape->slot() == 1 && shape->propidRef() == NameToId(cx->names().input)); // Make sure type information reflects the indexed properties which might // be added. types::AddTypePropertyId(cx, templateObject, JSID_VOID, types::Type::StringType()); types::AddTypePropertyId(cx, templateObject, JSID_VOID, types::Type::UndefinedType()); matchResultTemplateObject_.set(templateObject); return matchResultTemplateObject_; }
bool JSCompartment::wrap(JSContext *cx, MutableHandleValue vp, HandleObject existingArg) { JS_ASSERT(cx->compartment() == this); JS_ASSERT(this != rt->atomsCompartment); JS_ASSERT_IF(existingArg, existingArg->compartment() == cx->compartment()); JS_ASSERT_IF(existingArg, vp.isObject()); JS_ASSERT_IF(existingArg, IsDeadProxyObject(existingArg)); unsigned flags = 0; JS_CHECK_CHROME_RECURSION(cx, return false); AutoDisableProxyCheck adpc(rt); /* Only GC things have to be wrapped or copied. */ if (!vp.isMarkable()) return true; if (vp.isString()) { JSString *str = vp.toString(); /* If the string is already in this compartment, we are done. */ if (str->zone() == zone()) return true; /* If the string is an atom, we don't have to copy. */ if (str->isAtom()) { JS_ASSERT(str->zone() == cx->runtime()->atomsCompartment->zone()); return true; } } /* * Wrappers should really be parented to the wrapped parent of the wrapped * object, but in that case a wrapped global object would have a NULL * parent without being a proper global object (JSCLASS_IS_GLOBAL). Instead, * we parent all wrappers to the global object in their home compartment. * This loses us some transparency, and is generally very cheesy. */ HandleObject global = cx->global(); /* Unwrap incoming objects. */ if (vp.isObject()) { RootedObject obj(cx, &vp.toObject()); if (obj->compartment() == this) return WrapForSameCompartment(cx, obj, vp); /* Translate StopIteration singleton. */ if (obj->is<StopIterationObject>()) return js_FindClassObject(cx, JSProto_StopIteration, vp); /* Unwrap the object, but don't unwrap outer windows. */ obj = UncheckedUnwrap(obj, /* stopAtOuter = */ true, &flags); if (obj->compartment() == this) return WrapForSameCompartment(cx, obj, vp); if (cx->runtime()->preWrapObjectCallback) { obj = cx->runtime()->preWrapObjectCallback(cx, global, obj, flags); if (!obj) return false; } if (obj->compartment() == this) return WrapForSameCompartment(cx, obj, vp); vp.setObject(*obj); #ifdef DEBUG { JSObject *outer = GetOuterObject(cx, obj); JS_ASSERT(outer && outer == obj); } #endif } RootedValue key(cx, vp); /* If we already have a wrapper for this value, use it. */ if (WrapperMap::Ptr p = crossCompartmentWrappers.lookup(key)) { vp.set(p->value); if (vp.isObject()) { DebugOnly<JSObject *> obj = &vp.toObject(); JS_ASSERT(obj->isCrossCompartmentWrapper()); JS_ASSERT(obj->getParent() == global); } return true; } if (vp.isString()) { Rooted<JSLinearString *> str(cx, vp.toString()->ensureLinear(cx)); if (!str) return false; JSString *wrapped = js_NewStringCopyN<CanGC>(cx, str->chars(), str->length()); if (!wrapped) return false; vp.setString(wrapped); if (!putWrapper(key, vp)) return false; if (str->zone()->isGCMarking()) { /* * All string wrappers are dropped when collection starts, but we * just created a new one. Mark the wrapped string to stop it being * finalized, because if it was then the pointer in this * compartment's wrapper map would be left dangling. */ JSString *tmp = str; MarkStringUnbarriered(&rt->gcMarker, &tmp, "wrapped string"); JS_ASSERT(tmp == str); } return true; } RootedObject proto(cx, Proxy::LazyProto); RootedObject obj(cx, &vp.toObject()); RootedObject existing(cx, existingArg); if (existing) { /* Is it possible to reuse |existing|? */ if (!existing->getTaggedProto().isLazy() || existing->getClass() != &ObjectProxyClass || existing->getParent() != global || obj->isCallable()) { existing = NULL; } } /* * We hand in the original wrapped object into the wrap hook to allow * the wrap hook to reason over what wrappers are currently applied * to the object. */ RootedObject wrapper(cx); wrapper = cx->runtime()->wrapObjectCallback(cx, existing, obj, proto, global, flags); if (!wrapper) return false; // We maintain the invariant that the key in the cross-compartment wrapper // map is always directly wrapped by the value. JS_ASSERT(Wrapper::wrappedObject(wrapper) == &key.get().toObject()); vp.setObject(*wrapper); return putWrapper(key, vp); }
void EventQueue::CoalesceEvents() { NS_ASSERTION(mEvents.Length(), "There should be at least one pending event!"); uint32_t tail = mEvents.Length() - 1; AccEvent* tailEvent = mEvents[tail]; switch(tailEvent->mEventRule) { case AccEvent::eCoalesceReorder: { DebugOnly<Accessible*> target = tailEvent->mAccessible.get(); MOZ_ASSERT(target->IsApplication() || target->IsOuterDoc() || target->IsXULTree(), "Only app or outerdoc accessible reorder events are in the queue"); MOZ_ASSERT(tailEvent->GetEventType() == nsIAccessibleEvent::EVENT_REORDER, "only reorder events should be queued"); break; // case eCoalesceReorder } case AccEvent::eCoalesceOfSameType: { // Coalesce old events by newer event. for (uint32_t index = tail - 1; index < tail; index--) { AccEvent* accEvent = mEvents[index]; if (accEvent->mEventType == tailEvent->mEventType && accEvent->mEventRule == tailEvent->mEventRule) { accEvent->mEventRule = AccEvent::eDoNotEmit; return; } } break; // case eCoalesceOfSameType } case AccEvent::eCoalesceSelectionChange: { AccSelChangeEvent* tailSelChangeEvent = downcast_accEvent(tailEvent); for (uint32_t index = tail - 1; index < tail; index--) { AccEvent* thisEvent = mEvents[index]; if (thisEvent->mEventRule == tailEvent->mEventRule) { AccSelChangeEvent* thisSelChangeEvent = downcast_accEvent(thisEvent); // Coalesce selection change events within same control. if (tailSelChangeEvent->mWidget == thisSelChangeEvent->mWidget) { CoalesceSelChangeEvents(tailSelChangeEvent, thisSelChangeEvent, index); return; } } } break; // eCoalesceSelectionChange } case AccEvent::eCoalesceStateChange: { // If state change event is duped then ignore previous event. If state // change event is opposite to previous event then no event is emitted // (accessible state wasn't changed). for (uint32_t index = tail - 1; index < tail; index--) { AccEvent* thisEvent = mEvents[index]; if (thisEvent->mEventRule != AccEvent::eDoNotEmit && thisEvent->mEventType == tailEvent->mEventType && thisEvent->mAccessible == tailEvent->mAccessible) { AccStateChangeEvent* thisSCEvent = downcast_accEvent(thisEvent); AccStateChangeEvent* tailSCEvent = downcast_accEvent(tailEvent); if (thisSCEvent->mState == tailSCEvent->mState) { thisEvent->mEventRule = AccEvent::eDoNotEmit; if (thisSCEvent->mIsEnabled != tailSCEvent->mIsEnabled) tailEvent->mEventRule = AccEvent::eDoNotEmit; } } } break; // eCoalesceStateChange } case AccEvent::eCoalesceTextSelChange: { // Coalesce older event by newer event for the same selection or target. // Events for same selection may have different targets and vice versa one // target may be pointed by different selections (for latter see // bug 927159). for (uint32_t index = tail - 1; index < tail; index--) { AccEvent* thisEvent = mEvents[index]; if (thisEvent->mEventRule != AccEvent::eDoNotEmit && thisEvent->mEventType == tailEvent->mEventType) { AccTextSelChangeEvent* thisTSCEvent = downcast_accEvent(thisEvent); AccTextSelChangeEvent* tailTSCEvent = downcast_accEvent(tailEvent); if (thisTSCEvent->mSel == tailTSCEvent->mSel || thisEvent->mAccessible == tailEvent->mAccessible) thisEvent->mEventRule = AccEvent::eDoNotEmit; } } break; // eCoalesceTextSelChange } case AccEvent::eRemoveDupes: { // Check for repeat events, coalesce newly appended event by more older // event. for (uint32_t index = tail - 1; index < tail; index--) { AccEvent* accEvent = mEvents[index]; if (accEvent->mEventType == tailEvent->mEventType && accEvent->mEventRule == tailEvent->mEventRule && accEvent->mAccessible == tailEvent->mAccessible) { tailEvent->mEventRule = AccEvent::eDoNotEmit; return; } } break; // case eRemoveDupes } default: break; // case eAllowDupes, eDoNotEmit } // switch }