/* |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<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_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()); } }
JSAtom * SavedFrame::getSource() { const Value &v = getReservedSlot(JSSLOT_SOURCE); JSString *s = v.toString(); return &s->asAtom(); }
bool JSCompartment::wrap(JSContext* cx, MutableHandleString strp) { MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(this)); MOZ_ASSERT(cx->compartment() == this); /* If the string is already in this compartment, we are done. */ JSString* str = strp; if (str->zoneFromAnyThread() == zone()) return true; /* If the string is an atom, we don't have to copy. */ if (str->isAtom()) { MOZ_ASSERT(str->isPermanentAtom() || str->zone()->isAtomsZone()); return true; } /* Check the cache. */ RootedValue key(cx, StringValue(str)); if (WrapperMap::Ptr p = crossCompartmentWrappers.lookup(CrossCompartmentKey(key))) { strp.set(p->value().get().toString()); return true; } /* No dice. Make a copy, and cache it. */ JSString* copy = CopyStringPure(cx, str); if (!copy) return false; if (!putWrapper(cx, CrossCompartmentKey(key), StringValue(copy))) return false; strp.set(copy); return true; }
// Overview: These functions convert a JSString from holding a string in rope form // down to a simple String representation. It does so by building up the string // backwards, since we want to avoid recursion, we expect that the tree structure // representing the rope is likely imbalanced with more nodes down the left side // (since appending to the string is likely more common) - and as such resolving // in this fashion should minimize work queue size. (If we built the queue forwards // we would likely have to place all of the constituent StringImpls into the // Vector before performing any concatenation, but by working backwards we likely // only fill the queue with the number of substrings at any given level in a // rope-of-ropes.) void JSRopeString::resolveRopeSlowCase8(LChar* buffer) const { LChar* position = buffer + m_length; // We will be working backwards over the rope. Vector<JSString*, 32, UnsafeVectorOverflow> workQueue; // Putting strings into a Vector is only OK because there are no GC points in this method. for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i) workQueue.append(m_fibers[i].get()); while (!workQueue.isEmpty()) { JSString* currentFiber = workQueue.last(); workQueue.removeLast(); if (currentFiber->isRope()) { JSRopeString* currentFiberAsRope = static_cast<JSRopeString*>(currentFiber); for (size_t i = 0; i < s_maxInternalRopeLength && currentFiberAsRope->m_fibers[i]; ++i) workQueue.append(currentFiberAsRope->m_fibers[i].get()); continue; } StringImpl* string = static_cast<StringImpl*>(currentFiber->m_value.impl()); unsigned length = string->length(); position -= length; StringImpl::copyChars(position, string->characters8(), length); } ASSERT(buffer == position); }
void JSRopeString::resolveRopeSlowCase(UChar* buffer) const { UChar* position = buffer + m_length; // We will be working backwards over the rope. Vector<JSString*, 32, UnsafeVectorOverflow> workQueue; // These strings are kept alive by the parent rope, so using a Vector is OK. for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i) workQueue.append(m_fibers[i].get()); while (!workQueue.isEmpty()) { JSString* currentFiber = workQueue.last(); workQueue.removeLast(); if (currentFiber->isRope()) { JSRopeString* currentFiberAsRope = static_cast<JSRopeString*>(currentFiber); for (size_t i = 0; i < s_maxInternalRopeLength && currentFiberAsRope->m_fibers[i]; ++i) workQueue.append(currentFiberAsRope->m_fibers[i].get()); continue; } StringImpl* string = static_cast<StringImpl*>(currentFiber->m_value.impl()); unsigned length = string->length(); position -= length; if (string->is8Bit()) StringImpl::copyChars(position, string->characters8(), length); else StringImpl::copyChars(position, string->characters16(), length); } ASSERT(buffer == position); }
static JSObject * CloneObject(JSContext *cx, HandleObject selfHostedObject) { AutoCycleDetector detect(cx, selfHostedObject); if (!detect.init()) return nullptr; if (detect.foundCycle()) { JS_ReportError(cx, "SelfHosted cloning cannot handle cyclic object graphs."); return nullptr; } RootedObject clone(cx); if (selfHostedObject->is<JSFunction>()) { RootedFunction selfHostedFunction(cx, &selfHostedObject->as<JSFunction>()); bool hasName = selfHostedFunction->atom() != nullptr; // Arrow functions use the first extended slot for their lexical |this| value. JS_ASSERT(!selfHostedFunction->isArrow()); js::gc::AllocKind kind = hasName ? JSFunction::ExtendedFinalizeKind : selfHostedFunction->getAllocKind(); clone = CloneFunctionObject(cx, selfHostedFunction, cx->global(), kind, TenuredObject); // To be able to re-lazify the cloned function, its name in the // self-hosting compartment has to be stored on the clone. if (clone && hasName) clone->as<JSFunction>().setExtendedSlot(0, StringValue(selfHostedFunction->atom())); } else if (selfHostedObject->is<RegExpObject>()) { RegExpObject &reobj = selfHostedObject->as<RegExpObject>(); RootedAtom source(cx, reobj.getSource()); JS_ASSERT(source->isPermanentAtom()); clone = RegExpObject::createNoStatics(cx, source, reobj.getFlags(), nullptr); } else if (selfHostedObject->is<DateObject>()) { clone = JS_NewDateObjectMsec(cx, selfHostedObject->as<DateObject>().UTCTime().toNumber()); } else if (selfHostedObject->is<BooleanObject>()) { clone = BooleanObject::create(cx, selfHostedObject->as<BooleanObject>().unbox()); } else if (selfHostedObject->is<NumberObject>()) { clone = NumberObject::create(cx, selfHostedObject->as<NumberObject>().unbox()); } else if (selfHostedObject->is<StringObject>()) { JSString *selfHostedString = selfHostedObject->as<StringObject>().unbox(); if (!selfHostedString->isFlat()) MOZ_CRASH(); RootedString str(cx, js_NewStringCopyN<CanGC>(cx, selfHostedString->asFlat().chars(), selfHostedString->asFlat().length())); if (!str) return nullptr; clone = StringObject::create(cx, str); } else if (selfHostedObject->is<ArrayObject>()) { clone = NewDenseEmptyArray(cx, nullptr, TenuredObject); } else { JS_ASSERT(selfHostedObject->isNative()); clone = NewObjectWithGivenProto(cx, selfHostedObject->getClass(), nullptr, cx->global(), selfHostedObject->tenuredGetAllocKind(), SingletonObject); } if (!clone) return nullptr; if (!CloneProperties(cx, selfHostedObject, clone)) return nullptr; return clone; }
void Shape::dump(JSContext *cx, FILE *fp) const { jsid propid = this->propid(); JS_ASSERT(!JSID_IS_VOID(propid)); if (JSID_IS_INT(propid)) { fprintf(fp, "[%ld]", (long) JSID_TO_INT(propid)); } else if (JSID_IS_DEFAULT_XML_NAMESPACE(propid)) { fprintf(fp, "<default XML namespace>"); } else { JSLinearString *str; if (JSID_IS_ATOM(propid)) { str = JSID_TO_ATOM(propid); } else { JS_ASSERT(JSID_IS_OBJECT(propid)); JSString *s = ToStringSlow<CanGC>(cx, IdToValue(propid)); fputs("object ", fp); str = s ? s->ensureLinear(cx) : NULL; } if (!str) fputs("<error>", fp); else FileEscapedString(fp, str, '"'); } fprintf(fp, " g/s %p/%p slot %d attrs %x ", JS_FUNC_TO_DATA_PTR(void *, base()->rawGetter), JS_FUNC_TO_DATA_PTR(void *, base()->rawSetter), hasSlot() ? slot() : -1, attrs); if (attrs) { int first = 1; fputs("(", fp); #define DUMP_ATTR(name, display) if (attrs & JSPROP_##name) fputs(&(" " #display)[first], fp), first = 0 DUMP_ATTR(ENUMERATE, enumerate); DUMP_ATTR(READONLY, readonly); DUMP_ATTR(PERMANENT, permanent); DUMP_ATTR(GETTER, getter); DUMP_ATTR(SETTER, setter); DUMP_ATTR(SHARED, shared); #undef DUMP_ATTR fputs(") ", fp); } fprintf(fp, "flags %x ", flags); if (flags) { int first = 1; fputs("(", fp); #define DUMP_FLAG(name, display) if (flags & name) fputs(&(" " #display)[first], fp), first = 0 DUMP_FLAG(HAS_SHORTID, has_shortid); DUMP_FLAG(IN_DICTIONARY, in_dictionary); #undef DUMP_FLAG fputs(") ", fp); } fprintf(fp, "shortid %d\n", maybeShortid()); }
JSAtom * js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags) { JSString str; str.initFlat((jschar *)chars, length); return js_AtomizeString(cx, &str, ATOM_TMPSTR | flags); }
void Shape::dump(JSContext *cx, FILE *fp) const { /* This is only used from gdb, so allowing GC here would just be confusing. */ gc::AutoSuppressGC suppress(cx); jsid propid = this->propid(); JS_ASSERT(!JSID_IS_VOID(propid)); if (JSID_IS_INT(propid)) { fprintf(fp, "[%ld]", (long) JSID_TO_INT(propid)); } else { JSLinearString *str; if (JSID_IS_ATOM(propid)) { str = JSID_TO_ATOM(propid); } else { JS_ASSERT(JSID_IS_OBJECT(propid)); Value v = IdToValue(propid); JSString *s = ToStringSlow<NoGC>(cx, v); fputs("object ", fp); str = s ? s->ensureLinear(cx) : nullptr; } if (!str) fputs("<error>", fp); else FileEscapedString(fp, str, '"'); } fprintf(fp, " g/s %p/%p slot %d attrs %x ", JS_FUNC_TO_DATA_PTR(void *, base()->rawGetter), JS_FUNC_TO_DATA_PTR(void *, base()->rawSetter), hasSlot() ? slot() : -1, attrs); if (attrs) { int first = 1; fputs("(", fp); #define DUMP_ATTR(name, display) if (attrs & JSPROP_##name) fputs(&(" " #display)[first], fp), first = 0 DUMP_ATTR(ENUMERATE, enumerate); DUMP_ATTR(READONLY, readonly); DUMP_ATTR(PERMANENT, permanent); DUMP_ATTR(GETTER, getter); DUMP_ATTR(SETTER, setter); DUMP_ATTR(SHARED, shared); #undef DUMP_ATTR fputs(") ", fp); } fprintf(fp, "flags %x ", flags); if (flags) { int first = 1; fputs("(", fp); #define DUMP_FLAG(name, display) if (flags & name) fputs(&(" " #display)[first], fp), first = 0 DUMP_FLAG(IN_DICTIONARY, in_dictionary); #undef DUMP_FLAG fputs(") ", fp); } }
static JSObject * CloneObject(JSContext *cx, JSObject *selfHostedObject, CloneMemory &clonedObjects) { DependentAddPtr<CloneMemory> p(cx, clonedObjects, selfHostedObject); if (p) return p->value(); RootedObject clone(cx); if (selfHostedObject->is<JSFunction>()) { JSFunction *selfHostedFunction = &selfHostedObject->as<JSFunction>(); bool hasName = selfHostedFunction->atom() != nullptr; js::gc::AllocKind kind = hasName ? JSFunction::ExtendedFinalizeKind : selfHostedFunction->getAllocKind(); clone = CloneFunctionObject(cx, HandleFunction::fromMarkedLocation(&selfHostedFunction), cx->global(), kind, TenuredObject); // To be able to re-lazify the cloned function, its name in the // self-hosting compartment has to be stored on the clone. if (clone && hasName) clone->as<JSFunction>().setExtendedSlot(0, StringValue(selfHostedFunction->atom())); } else if (selfHostedObject->is<RegExpObject>()) { RegExpObject &reobj = selfHostedObject->as<RegExpObject>(); RootedAtom source(cx, reobj.getSource()); JS_ASSERT(source->isPermanentAtom()); clone = RegExpObject::createNoStatics(cx, source, reobj.getFlags(), nullptr); } else if (selfHostedObject->is<DateObject>()) { clone = JS_NewDateObjectMsec(cx, selfHostedObject->as<DateObject>().UTCTime().toNumber()); } else if (selfHostedObject->is<BooleanObject>()) { clone = BooleanObject::create(cx, selfHostedObject->as<BooleanObject>().unbox()); } else if (selfHostedObject->is<NumberObject>()) { clone = NumberObject::create(cx, selfHostedObject->as<NumberObject>().unbox()); } else if (selfHostedObject->is<StringObject>()) { JSString *selfHostedString = selfHostedObject->as<StringObject>().unbox(); if (!selfHostedString->isFlat()) MOZ_CRASH(); RootedString str(cx, js_NewStringCopyN<CanGC>(cx, selfHostedString->asFlat().chars(), selfHostedString->asFlat().length())); if (!str) return nullptr; clone = StringObject::create(cx, str); } else if (selfHostedObject->is<ArrayObject>()) { clone = NewDenseEmptyArray(cx, nullptr, TenuredObject); } else { JS_ASSERT(selfHostedObject->isNative()); clone = NewObjectWithGivenProto(cx, selfHostedObject->getClass(), nullptr, cx->global(), selfHostedObject->tenuredGetAllocKind(), SingletonObject); } if (!clone) return nullptr; if (!p.add(cx, clonedObjects, selfHostedObject, clone)) return nullptr; if (!CloneProperties(cx, selfHostedObject, clone, clonedObjects)) { clonedObjects.remove(selfHostedObject); return nullptr; } return clone; }
JSAtom * SavedFrame::getFunctionDisplayName() { const Value &v = getReservedSlot(JSSLOT_FUNCTIONDISPLAYNAME); if (v.isNull()) return nullptr; JSString *s = v.toString(); return &s->asAtom(); }
bool JSString::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, PropertySlot& slot) { JSString* thisObject = jsCast<JSString*>(cell); // The semantics here are really getPropertySlot, not getOwnPropertySlot. // This function should only be called by JSValue::get. if (thisObject->getStringPropertySlot(exec, propertyName, slot)) return true; return JSString::getOwnPropertySlot(thisObject, exec, Identifier::from(exec, propertyName), slot); }
void JSString::visitChildren(JSCell* cell, SlotVisitor& visitor) { JSString* thisObject = asString(cell); Base::visitChildren(thisObject, visitor); if (thisObject->isRope()) static_cast<JSRopeString*>(thisObject)->visitFibers(visitor); if (StringImpl* impl = thisObject->m_value.impl()) visitor.reportExtraMemoryVisited(impl->costDuringGC()); }
JSAtom * js::ToAtom(ExclusiveContext *cx, typename MaybeRooted<Value, allowGC>::HandleType v) { if (!v.isString()) return ToAtomSlow<allowGC>(cx, v); JSString *str = v.toString(); if (str->isAtom()) return &str->asAtom(); return AtomizeString(cx, str); }
static TriState equalToStringImpl(JSValue value, StringImpl* stringImpl) { if (!value.isString()) return FalseTriState; JSString* jsString = asString(value); const StringImpl* string = jsString->tryGetValueImpl(); if (!string) return MixedTriState; return triState(WTF::equal(stringImpl, string)); }
JSBool EvalScriptVersion16(JSContext *cx, uintN argc, jsval *vp) { JS_ASSERT(argc == 1); jsval *argv = JS_ARGV(cx, vp); JS_ASSERT(JSVAL_IS_STRING(argv[0])); JSString *str = JSVAL_TO_STRING(argv[0]); const jschar *chars = str->getChars(cx); JS_ASSERT(chars); size_t len = str->length(); return callbackData->evalVersion(chars, len, JSVERSION_1_6); }
EncodedJSValue JSC_HOST_CALL symbolConstructorFor(ExecState* exec) { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSString* stringKey = exec->argument(0).toString(exec); RETURN_IF_EXCEPTION(scope, encodedJSValue()); String string = stringKey->value(exec); RETURN_IF_EXCEPTION(scope, encodedJSValue()); return JSValue::encode(Symbol::create(exec->vm(), exec->vm().symbolRegistry().symbolForKey(string))); }
void JSString::visitChildren(JSCell* cell, SlotVisitor& visitor) { JSString* thisObject = jsCast<JSString*>(cell); Base::visitChildren(thisObject, visitor); if (thisObject->isRope()) static_cast<JSRopeString*>(thisObject)->visitFibers(visitor); else { StringImpl* impl = thisObject->m_value.impl(); ASSERT(impl); visitor.reportExtraMemoryUsage(thisObject, impl->costDuringGC()); } }
JSAtom * js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags) { JSString str; CHECK_REQUEST(cx); if (!CheckStringLength(cx, length)) return NULL; str.initFlatNotTerminated((jschar *)chars, length); return js_AtomizeString(cx, &str, ATOM_TMPSTR | flags); }
bool SecurityWrapper<Base>::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id, PropertyDescriptor *desc) { if (desc->getter || desc->setter) { JSString *str = IdToString(cx, id); const jschar *prop = str ? str->getCharsZ(cx) : NULL; JS_ReportErrorNumberUC(cx, js_GetErrorMessage, NULL, JSMSG_ACCESSOR_DEF_DENIED, prop); return false; } return Base::defineProperty(cx, wrapper, id, desc); }
bool JSCompartment::wrap(JSContext *cx, JSString **strp) { JS_ASSERT(!cx->runtime()->isAtomsCompartment(this)); JS_ASSERT(cx->compartment() == this); /* If the string is already in this compartment, we are done. */ JSString *str = *strp; if (str->zone() == zone()) return true; /* If the string is an atom, we don't have to copy. */ if (str->isAtom()) { JS_ASSERT(cx->runtime()->isAtomsZone(str->zone())); return true; } /* Check the cache. */ RootedValue key(cx, StringValue(str)); if (WrapperMap::Ptr p = crossCompartmentWrappers.lookup(key)) { *strp = p->value().get().toString(); return true; } /* No dice. Make a copy, and cache it. */ Rooted<JSLinearString *> linear(cx, str->ensureLinear(cx)); if (!linear) return false; JSString *copy = js_NewStringCopyN<CanGC>(cx, linear->chars(), linear->length()); if (!copy) return false; if (!putWrapper(key, StringValue(copy))) return false; if (linear->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 = linear; MarkStringUnbarriered(&cx->runtime()->gcMarker, &tmp, "wrapped string"); JS_ASSERT(tmp == linear); } *strp = copy; return true; }
bool JSPropertyNameIterator::next(ExecState* exec, JSValue& output) { if (m_enumerationPhase == EnumerationPhase::IndexedNames) { for (; m_cursor < m_propertyNameEnumerator->indexedLength();) { uint32_t index = m_cursor++; if (m_iteratedObject->hasProperty(exec, index)) { output = jsString(exec, Identifier::from(exec, index).string()); return true; } } m_cursor = 0; m_enumerationPhase = EnumerationPhase::StructureNames; } if (m_enumerationPhase == EnumerationPhase::StructureNames) { for (; m_cursor < m_propertyNameEnumerator->endStructurePropertyIndex();) { uint32_t index = m_cursor++; JSString* propertyName = m_propertyNameEnumerator->propertyNameAtIndex(index); ASSERT(propertyName); if (m_iteratedObject->structure(exec->vm())->id() == m_propertyNameEnumerator->cachedStructureID()) { output = propertyName; return true; } if (m_iteratedObject->hasProperty(exec, propertyName->toIdentifier(exec))) { output = propertyName; return true; } } ASSERT(m_cursor >= m_propertyNameEnumerator->endStructurePropertyIndex()); // Use the same m_cursor in the GenericNames phase. m_enumerationPhase = EnumerationPhase::GenericNames; } if (m_enumerationPhase == EnumerationPhase::GenericNames) { for (; m_cursor < m_propertyNameEnumerator->endGenericPropertyIndex();) { uint32_t index = m_cursor++; JSString* propertyName = m_propertyNameEnumerator->propertyNameAtIndex(index); ASSERT(propertyName); if (m_iteratedObject->hasProperty(exec, propertyName->toIdentifier(exec))) { output = propertyName; return true; } } m_enumerationPhase = EnumerationPhase::Done; } return false; }
static TriState equalToSingleCharacter(JSValue value, UChar character) { if (!value.isString()) return FalseTriState; JSString* jsString = asString(value); if (jsString->length() != 1) return FalseTriState; const StringImpl* string = jsString->tryGetValueImpl(); if (!string) return MixedTriState; return triState(string->at(0) == character); }
EncodedJSValue JSC_HOST_CALL regExpProtoFuncSearch(ExecState* exec) { JSValue thisValue = exec->thisValue(); if (!thisValue.inherits(RegExpObject::info())) return throwVMTypeError(exec); RegExp* regExp = asRegExpObject(thisValue)->regExp(); JSString* string = exec->argument(0).toString(exec); String s = string->value(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); MatchResult result = regExpConstructor->performMatch(exec->vm(), regExp, string, s, 0); return JSValue::encode(result ? jsNumber(result.start) : jsNumber(-1)); }
void generateStringPath(Assembler &masm) { const ValueRemat &lvr = ic.lvr; const ValueRemat &rvr = ic.rvr; JS_ASSERT_IF(lvr.isConstant(), lvr.isType(JSVAL_TYPE_STRING)); JS_ASSERT_IF(rvr.isConstant(), rvr.isType(JSVAL_TYPE_STRING)); if (!lvr.isType(JSVAL_TYPE_STRING)) { Jump lhsFail = masm.testString(Assembler::NotEqual, lvr.typeReg()); linkToStub(lhsFail); } if (!rvr.isType(JSVAL_TYPE_STRING)) { Jump rhsFail = masm.testString(Assembler::NotEqual, rvr.typeReg()); linkToStub(rhsFail); } RegisterID tmp = ic.tempReg; /* JSString::isAtom === (lengthAndFlags & ATOM_MASK == 0) */ JS_STATIC_ASSERT(JSString::ATOM_FLAGS == 0); Imm32 atomMask(JSString::ATOM_MASK); masm.load32(Address(lvr.dataReg(), JSString::offsetOfLengthAndFlags()), tmp); Jump lhsNotAtomized = masm.branchTest32(Assembler::NonZero, tmp, atomMask); linkToStub(lhsNotAtomized); if (!rvr.isConstant()) { masm.load32(Address(rvr.dataReg(), JSString::offsetOfLengthAndFlags()), tmp); Jump rhsNotAtomized = masm.branchTest32(Assembler::NonZero, tmp, atomMask); linkToStub(rhsNotAtomized); } if (rvr.isConstant()) { JSString *str = rvr.value().toString(); JS_ASSERT(str->isAtom()); Jump test = masm.branchPtr(ic.cond, lvr.dataReg(), ImmPtr(str)); linkTrue(test); } else { Jump test = masm.branchPtr(ic.cond, lvr.dataReg(), rvr.dataReg()); linkTrue(test); } Jump fallthrough = masm.jump(); linkFalse(fallthrough); }
JSAtom* js::ToAtom(ExclusiveContext* cx, typename MaybeRooted<Value, allowGC>::HandleType v) { if (!v.isString()) return ToAtomSlow<allowGC>(cx, v); JSString* str = v.toString(); if (str->isAtom()) return &str->asAtom(); JSAtom* atom = AtomizeString(cx, str); if (!atom && !allowGC) { MOZ_ASSERT_IF(cx->isJSContext(), cx->asJSContext()->isThrowingOutOfMemory()); cx->recoverFromOutOfMemory(); } return atom; }
bool SecurityWrapper<Base>::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id, MutableHandle<PropertyDescriptor> desc) const { if (desc.getter() || desc.setter()) { JSString *str = IdToString(cx, id); AutoStableStringChars chars(cx); const jschar *prop = nullptr; if (str->ensureFlat(cx) && chars.initTwoByte(cx, str)) prop = chars.twoByteChars(); JS_ReportErrorNumberUC(cx, js_GetErrorMessage, nullptr, JSMSG_ACCESSOR_DEF_DENIED, prop); return false; } return Base::defineProperty(cx, wrapper, id, desc); }
bool JSString::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot) { JSString* thisObject = jsCast<JSString*>(cell); // The semantics here are really getPropertySlot, not getOwnPropertySlot. // This function should only be called by JSValue::get. if (thisObject->getStringPropertySlot(exec, propertyName, slot)) return true; slot.setBase(thisObject); JSObject* object; for (JSValue prototype = exec->lexicalGlobalObject()->stringPrototype(); !prototype.isNull(); prototype = object->prototype()) { object = asObject(prototype); if (object->methodTable()->getOwnPropertySlot(object, exec, propertyName, slot)) return true; } slot.setUndefined(); return true; }
inline RegExpFlags toFlags(ExecState* exec, JSValue flags) { if (flags.isUndefined()) return NoFlags; JSString* flagsString = flags.toString(exec); if (!flagsString) { ASSERT(exec->hadException()); return InvalidFlags; } RegExpFlags result = regExpFlags(flagsString->value(exec)); if (exec->hadException()) return InvalidFlags; if (result == InvalidFlags) throwSyntaxError(exec, ASCIILiteral("Invalid flags supplied to RegExp constructor.")); return result; }
/** * Handles an assertion failure in self-hosted code just like an assertion * failure in C++ code. Information about the failure can be provided in args[0]. */ static bool intrinsic_AssertionFailed(JSContext *cx, unsigned argc, Value *vp) { #ifdef DEBUG CallArgs args = CallArgsFromVp(argc, vp); if (args.length() > 0) { // try to dump the informative string JSString *str = ToString<CanGC>(cx, args[0]); if (str) { fprintf(stderr, "Self-hosted JavaScript assertion info: "); str->dumpCharsNoNewline(); fputc('\n', stderr); } } #endif JS_ASSERT(false); return false; }