Ejemplo n.º 1
0
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. Directly allocate the copy in the
     * destination compartment, rather than first flattening it (and possibly
     * allocating in source compartment), because we don't know whether the
     * flattening will pay off later.
     */
    JSString *copy;
    if (str->hasPureChars()) {
        copy = js_NewStringCopyN<CanGC>(cx, str->pureChars(), str->length());
    } else {
        ScopedJSFreePtr<jschar> copiedChars;
        if (!str->copyNonPureCharsZ(cx, copiedChars))
            return false;
        copy = js_NewString<CanGC>(cx, copiedChars.forget(), str->length());
    }

    if (!copy)
        return false;
    if (!putWrapper(cx, key, StringValue(copy)))
        return false;

    *strp = copy;
    return true;
}
Ejemplo n.º 2
0
bool
ScopedThreadSafeStringInspector::ensureChars(ThreadSafeContext *cx, const AutoCheckCannotGC &nogc)
{
    if (state_ != Uninitialized)
        return true;

    if (cx->isExclusiveContext()) {
        JSLinearString *linear = str_->ensureLinear(cx->asExclusiveContext());
        if (!linear)
            return false;
        if (linear->hasTwoByteChars()) {
            state_ = TwoByte;
            twoByteChars_ = linear->twoByteChars(nogc);
        } else {
            state_ = Latin1;
            latin1Chars_ = linear->latin1Chars(nogc);
        }
    } else {
        if (str_->isLinear()) {
            if (str_->hasLatin1Chars()) {
                state_ = Latin1;
                latin1Chars_ = str_->asLinear().latin1Chars(nogc);
            } else {
                state_ = TwoByte;
                twoByteChars_ = str_->asLinear().twoByteChars(nogc);
            }
        } else {
            if (str_->hasLatin1Chars()) {
                ScopedJSFreePtr<Latin1Char> chars;
                if (!str_->asRope().copyLatin1Chars(cx, chars))
                    return false;
                state_ = Latin1;
                latin1Chars_ = chars;
                scopedChars_ = chars.forget();
            } else {
                ScopedJSFreePtr<jschar> chars;
                if (!str_->asRope().copyTwoByteChars(cx, chars))
                    return false;
                state_ = TwoByte;
                twoByteChars_ = chars;
                scopedChars_ = chars.forget();
            }
        }
    }

    MOZ_ASSERT(state_ != Uninitialized);
    return true;
}
Ejemplo n.º 3
0
static JSString*
CopyStringPure(JSContext* cx, JSString* str)
{
    /*
     * Directly allocate the copy in the destination compartment, rather than
     * first flattening it (and possibly allocating in source compartment),
     * because we don't know whether the flattening will pay off later.
     */

    size_t len = str->length();
    JSString* copy;
    if (str->isLinear()) {
        /* Only use AutoStableStringChars if the NoGC allocation fails. */
        if (str->hasLatin1Chars()) {
            JS::AutoCheckCannotGC nogc;
            copy = NewStringCopyN<NoGC>(cx, str->asLinear().latin1Chars(nogc), len);
        } else {
            JS::AutoCheckCannotGC nogc;
            copy = NewStringCopyNDontDeflate<NoGC>(cx, str->asLinear().twoByteChars(nogc), len);
        }
        if (copy)
            return copy;

        AutoStableStringChars chars(cx);
        if (!chars.init(cx, str))
            return nullptr;

        return chars.isLatin1()
               ? NewStringCopyN<CanGC>(cx, chars.latin1Range().begin().get(), len)
               : NewStringCopyNDontDeflate<CanGC>(cx, chars.twoByteRange().begin().get(), len);
    }

    if (str->hasLatin1Chars()) {
        ScopedJSFreePtr<Latin1Char> copiedChars;
        if (!str->asRope().copyLatin1CharsZ(cx, copiedChars))
            return nullptr;

        return NewString<CanGC>(cx, copiedChars.forget(), len);
    }

    ScopedJSFreePtr<char16_t> copiedChars;
    if (!str->asRope().copyTwoByteCharsZ(cx, copiedChars))
        return nullptr;

    return NewStringDontDeflate<CanGC>(cx, copiedChars.forget(), len);
}
Ejemplo n.º 4
0
bool
JSRope::copyNonPureCharsInternal(ThreadSafeContext *cx, ScopedJSFreePtr<jschar> &out,
                                 bool nullTerminate) const
{
    /*
     * Perform non-destructive post-order traversal of the rope, splatting
     * each node's characters into a contiguous buffer.
     */

    size_t n = length();
    if (cx)
        out.reset(cx->pod_malloc<jschar>(n + 1));
    else
        out.reset(js_pod_malloc<jschar>(n + 1));

    if (!out)
        return false;

    Vector<const JSString *, 8, SystemAllocPolicy> nodeStack;
    const JSString *str = this;
    jschar *pos = out;
    while (true) {
        if (str->isRope()) {
            if (!nodeStack.append(str->asRope().rightChild()))
                return false;
            str = str->asRope().leftChild();
        } else {
            size_t len = str->length();
            PodCopy(pos, str->asLinear().chars(), len);
            pos += len;
            if (nodeStack.empty())
                break;
            str = nodeStack.popCopy();
        }
    }

    JS_ASSERT(pos == out + n);

    if (nullTerminate)
        out[n] = 0;

    return true;
}
Ejemplo n.º 5
0
bool
JSDependentString::copyNonPureCharsZ(ThreadSafeContext *cx, ScopedJSFreePtr<jschar> &out) const
{
    JS_ASSERT(JSString::isDependent());

    size_t n = length();
    jschar *s = cx->pod_malloc<jschar>(n + 1);
    if (!s)
        return false;

    PodCopy(s, nonInlineChars(), n);
    s[n] = 0;

    out.reset(s);
    return true;
}