Exemplo n.º 1
0
RegExpObject *
RegExpObjectBuilder::clone(Handle<RegExpObject *> other, Handle<RegExpObject *> proto)
{
    if (!getOrCreateClone(proto))
        return NULL;

    /*
     * Check that the RegExpShared for the original is okay to use in
     * the clone -- if the |RegExpStatics| provides more flags we'll
     * need a different |RegExpShared|.
     */
    RegExpStatics *res = cx->regExpStatics();
    RegExpFlag origFlags = other->getFlags();
    RegExpFlag staticsFlags = res->getFlags();
    if ((origFlags & staticsFlags) != staticsFlags) {
        RegExpFlag newFlags = RegExpFlag(origFlags | staticsFlags);
        return build(Rooted<JSAtom *>(cx, other->getSource()), newFlags);
    }

    RegExpGuard g;
    if (!other->getShared(cx, &g))
        return NULL;

    return build(RootedAtom(cx, other->getSource()), *g);
}
Exemplo n.º 2
0
RegExpObject*
RegExpObjectBuilder::clone(Handle<RegExpObject*> other)
{
    RootedObjectGroup group(cx, other->group());
    if (!getOrCreateClone(group))
        return nullptr;

    /*
     * Check that the RegExpShared for the original is okay to use in
     * the clone -- if the |RegExpStatics| provides more flags we'll
     * need a different |RegExpShared|.
     */
    RegExpStatics* res = other->getProto()->global().getRegExpStatics(cx);
    if (!res)
        return nullptr;

    RegExpFlag origFlags = other->getFlags();
    RegExpFlag staticsFlags = res->getFlags();
    if ((origFlags & staticsFlags) != staticsFlags) {
        RegExpFlag newFlags = RegExpFlag(origFlags | staticsFlags);
        Rooted<JSAtom*> source(cx, other->getSource());
        return build(source, newFlags);
    }

    RegExpGuard g(cx);
    if (!other->getShared(cx->asJSContext(), &g))
        return nullptr;

    Rooted<JSAtom*> source(cx, other->getSource());
    return build(source, *g);
}
Exemplo n.º 3
0
RegExpObject *
RegExpObjectBuilder::clone(RegExpObject *other, RegExpObject *proto)
{
    if (!getOrCreateClone(proto))
        return NULL;

    /*
     * Check that the RegExpPrivate for the original is okay to use in
     * the clone -- if the |RegExpStatics| provides more flags we'll
     * need a different |RegExpPrivate|.
     */
    RegExpStatics *res = cx->regExpStatics();
    RegExpFlag origFlags = other->getFlags();
    RegExpFlag staticsFlags = res->getFlags();
    if ((origFlags & staticsFlags) != staticsFlags) {
        RegExpFlag newFlags = RegExpFlag(origFlags | staticsFlags);
        return build(other->getSource(), newFlags);
    }

    RegExpPrivate *toShare = other->getOrCreatePrivate(cx);
    if (!toShare)
        return NULL;

    toShare->incref(cx);
    return build(AlreadyIncRefed<RegExpPrivate>(toShare));
}
Exemplo n.º 4
0
RegExpObject *
RegExpObjectBuilder::clone(Handle<RegExpObject *> other, Handle<RegExpObject *> proto)
{
    RootedTypeObject type(cx, other->type());
    JS_ASSERT(type->proto == proto);

    if (!getOrCreateClone(type))
        return nullptr;

    /*
     * Check that the RegExpShared for the original is okay to use in
     * the clone -- if the |RegExpStatics| provides more flags we'll
     * need a different |RegExpShared|.
     */
    RegExpStatics *res = proto->getParent()->as<GlobalObject>().getRegExpStatics();
    RegExpFlag origFlags = other->getFlags();
    RegExpFlag staticsFlags = res->getFlags();
    if ((origFlags & staticsFlags) != staticsFlags) {
        RegExpFlag newFlags = RegExpFlag(origFlags | staticsFlags);
        Rooted<JSAtom *> source(cx, other->getSource());
        return build(source, newFlags);
    }

    RegExpGuard g(cx);
    if (!other->getShared(cx, &g))
        return nullptr;

    Rooted<JSAtom *> source(cx, other->getSource());
    return build(source, *g);
}
Exemplo n.º 5
0
RegExpObject *
RegExpObjectBuilder::clone(Handle<RegExpObject *> other)
{
    RootedTypeObject type(cx, other->type());
    if (!getOrCreateClone(type))
        return nullptr;

    /*
     * Check that the RegExpShared for the original is okay to use in
     * the clone -- if the |RegExpStatics| provides more flags we'll
     * need a different |RegExpShared|.
     */
    RegExpStatics *res = other->getProto()->getParent()->as<GlobalObject>().getRegExpStatics(cx);
    if (!res)
        return nullptr;

    RegExpFlag origFlags = other->getFlags();
    RegExpFlag staticsFlags = res->getFlags();
    if ((origFlags & staticsFlags) != staticsFlags) {
        RegExpFlag newFlags = RegExpFlag(origFlags | staticsFlags);
        Rooted<JSAtom *> source(cx, other->getSource());
        return build(source, newFlags);
    }

    RegExpGuard g(cx);
    if (!other->getShared(cx->asJSContext(), &g))
        return nullptr;

    // Copying a RegExpShared from one object to another requires a read
    // barrier, as the shared pointer in an object may be weak.
    MaybeTraceRegExpShared(cx->asJSContext(), g.re());

    Rooted<JSAtom *> source(cx, other->getSource());
    return build(source, *g);
}
Exemplo n.º 6
0
static void
resc_trace(JSTracer* trc, JSObject* obj)
{
    void* pdata = obj->as<RegExpStaticsObject>().getPrivate();
    MOZ_ASSERT(pdata);
    RegExpStatics* res = static_cast<RegExpStatics*>(pdata);
    res->mark(trc);
}
Exemplo n.º 7
0
static void
resc_trace(JSTracer *trc, RawObject obj)
{
    void *pdata = obj->getPrivate();
    JS_ASSERT(pdata);
    RegExpStatics *res = static_cast<RegExpStatics *>(pdata);
    res->mark(trc);
}
Exemplo n.º 8
0
static bool
static_multiline_getter(JSContext* cx, unsigned argc, Value* vp)
{
    CallArgs args = CallArgsFromVp(argc, vp);
    RegExpStatics* res = cx->global()->getRegExpStatics(cx);
    if (!res)
        return false;

    if (!WarnOnceAboutRegExpMultiline(cx))
        return false;

    args.rval().setBoolean(res->multiline());
    return true;
}
Exemplo n.º 9
0
/*
 * ES6 21.2.3.2.2.  Because this function only ever returns |obj| in the spec,
 * provided by the user, we omit it and just return the usual success/failure.
 */
static bool
RegExpInitialize(JSContext* cx, Handle<RegExpObject*> obj, HandleValue patternValue,
                 HandleValue flagsValue, RegExpStaticsUse staticsUse)
{
    RootedAtom pattern(cx);
    if (patternValue.isUndefined()) {
        /* Step 1. */
        pattern = cx->runtime()->emptyString;
    } else {
        /* Steps 2-3. */
        pattern = ToAtom<CanGC>(cx, patternValue);
        if (!pattern)
            return false;
    }

    /* Step 4. */
    RegExpFlag flags = RegExpFlag(0);
    if (!flagsValue.isUndefined()) {
        /* Steps 5-6. */
        RootedString flagStr(cx, ToString<CanGC>(cx, flagsValue));
        if (!flagStr)
            return false;
        /* Step 7. */
        if (!ParseRegExpFlags(cx, flagStr, &flags))
            return false;
    }

    /* Steps 9-10. */
    CompileOptions options(cx);
    frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
    if (!irregexp::ParsePatternSyntax(dummyTokenStream, cx->tempLifoAlloc(), pattern,
                                      flags & UnicodeFlag))
    {
        return false;
    }

    if (staticsUse == UseRegExpStatics) {
        RegExpStatics* res = cx->global()->getRegExpStatics(cx);
        if (!res)
            return false;
        flags = RegExpFlag(flags | res->getFlags());
    }

    /* Steps 11-15. */
    if (!RegExpObject::initFromAtom(cx, obj, pattern, flags))
        return false;

    /* Step 16. */
    return true;
}
Exemplo n.º 10
0
static bool
static_input_setter(JSContext* cx, unsigned argc, Value* vp)
{
    CallArgs args = CallArgsFromVp(argc, vp);
    RegExpStatics* res = cx->global()->getRegExpStatics(cx);
    if (!res)
        return false;

    RootedString str(cx, ToString<CanGC>(cx, args.get(0)));
    if (!str)
        return false;

    res->setPendingInput(str);
    args.rval().setString(str);
    return true;
}
Exemplo n.º 11
0
JSObject*
js::CloneRegExpObject(JSContext* cx, JSObject* obj_)
{
    Rooted<RegExpObject*> regex(cx, &obj_->as<RegExpObject>());

    // Check that the RegExpShared for |regex| is okay to reuse in the clone.
    // If the |RegExpStatics| provides additional flags, we'll need a new
    // |RegExpShared|.
    RegExpStatics* currentStatics = regex->getProto()->global().getRegExpStatics(cx);
    if (!currentStatics)
        return nullptr;

    Rooted<JSAtom*> source(cx, regex->getSource());

    RegExpFlag origFlags = regex->getFlags();
    RegExpFlag staticsFlags = currentStatics->getFlags();
    if ((origFlags & staticsFlags) != staticsFlags) {
        Rooted<RegExpObject*> clone(cx, RegExpAlloc(cx));
        if (!clone)
            return nullptr;

        if (!RegExpObject::initFromAtom(cx, clone, source, RegExpFlag(origFlags | staticsFlags)))
            return nullptr;

        return clone;
    }

    // Otherwise, the clone can use |regexp|'s RegExpShared.
    RootedObjectGroup group(cx, regex->group());

    // Note: RegExp objects are always allocated in the tenured heap. This is
    // not strictly required, but it simplifies embedding them in jitcode.
    Rooted<RegExpObject*> clone(cx, NewObjectWithGroup<RegExpObject>(cx, group, TenuredObject));
    if (!clone)
        return nullptr;
    clone->initPrivate(nullptr);

    RegExpGuard g(cx);
    if (!regex->getShared(cx, &g))
        return nullptr;

    if (!RegExpObject::initFromAtom(cx, clone, source, g->getFlags()))
        return nullptr;

    clone->setShared(*g.re());
    return clone;
}
Exemplo n.º 12
0
JSObject * JS_FASTCALL
js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *proto)
{
    JS_ASSERT(obj->getClass() == &js_RegExpClass);
    JS_ASSERT(proto);
    JS_ASSERT(proto->getClass() == &js_RegExpClass);

    JSObject *clone = NewNativeClassInstance(cx, &js_RegExpClass, proto, proto->getParent());
    if (!clone)
        return NULL;

    /*
     * This clone functionality does not duplicate the JITted code blob, which is necessary for
     * cross-compartment cloning functionality.
     */
    assertSameCompartment(cx, obj, clone);

    RegExpStatics *res = cx->regExpStatics();
    RegExp *re = RegExp::extractFrom(obj);
    {
        uint32 origFlags = re->getFlags();
        uint32 staticsFlags = res->getFlags();
        if ((origFlags & staticsFlags) != staticsFlags) {
            /*
             * This regex is lacking flags from the statics, so we must recompile with the new
             * flags instead of increffing.
             */
            AlreadyIncRefed<RegExp> clone = RegExp::create(cx, re->getSource(),
                                                           origFlags | staticsFlags, NULL);
            if (!clone)
                return NULL;
            re = clone.get();
        } else {
            re->incref(cx);
        }
    }
    JS_ASSERT(re);
    if (!clone->initRegExp(cx, re))
        return NULL;
    return clone;
}
Exemplo n.º 13
0
/*
 * Compile a new |RegExpShared| for the |RegExpObject|.
 *
 * Per ECMAv5 15.10.4.1, we act on combinations of (pattern, flags) as
 * arguments:
 *
 *  RegExp, undefined => flags := pattern.flags
 *  RegExp, _ => throw TypeError
 *  _ => pattern := ToString(pattern) if defined(pattern) else ''
 *       flags := ToString(flags) if defined(flags) else ''
 */
static bool
CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder, CallArgs args)
{
    if (args.length() == 0) {
        RegExpStatics *res = cx->regExpStatics();
        Rooted<JSAtom*> empty(cx, cx->runtime->emptyString);
        RegExpObject *reobj = builder.build(empty, res->getFlags());
        if (!reobj)
            return false;
        args.rval().setObject(*reobj);
        return true;
    }

    RootedValue sourceValue(cx, args[0]);

    /*
     * If we get passed in an object whose internal [[Class]] property is
     * "RegExp", return a new object with the same source/flags.
     */
    if (IsObjectWithClass(sourceValue, ESClass_RegExp, cx)) {
        /*
         * Beware, sourceObj may be a (transparent) proxy to a RegExp, so only
         * use generic (proxyable) operations on sourceObj that do not assume
         * sourceObj.isRegExp().
         */
        RootedObject sourceObj(cx, &sourceValue.toObject());

        if (args.hasDefined(1)) {
            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NEWREGEXP_FLAGGED);
            return false;
        }

        /*
         * Only extract the 'flags' out of sourceObj; do not reuse the
         * RegExpShared since it may be from a different compartment.
         */
        RegExpFlag flags;
        {
            RegExpGuard g(cx);
            if (!RegExpToShared(cx, sourceObj, &g))
                return false;

            flags = g->getFlags();
        }

        /*
         * 'toSource' is a permanent read-only property, so this is equivalent
         * to executing RegExpObject::getSource on the unwrapped object.
         */
        RootedValue v(cx);
        if (!JSObject::getProperty(cx, sourceObj, sourceObj, cx->names().source, &v))
            return false;

        Rooted<JSAtom*> sourceAtom(cx, &v.toString()->asAtom());
        RegExpObject *reobj = builder.build(sourceAtom, flags);
        if (!reobj)
            return false;

        args.rval().setObject(*reobj);
        return true;
    }

    RootedAtom source(cx);
    if (sourceValue.isUndefined()) {
        source = cx->runtime->emptyString;
    } else {
        /* Coerce to string and compile. */
        JSString *str = ToString<CanGC>(cx, sourceValue);
        if (!str)
            return false;

        source = AtomizeString<CanGC>(cx, str);
        if (!source)
            return false;
    }

    RegExpFlag flags = RegExpFlag(0);
    if (args.hasDefined(1)) {
        RootedString flagStr(cx, ToString<CanGC>(cx, args[1]));
        if (!flagStr)
            return false;
        args[1].setString(flagStr);
        if (!ParseRegExpFlags(cx, flagStr, &flags))
            return false;
    }

    RootedAtom escapedSourceStr(cx, EscapeNakedForwardSlashes(cx, source));
    if (!escapedSourceStr)
        return false;

    if (!js::RegExpShared::checkSyntax(cx, NULL, escapedSourceStr))
        return false;

    RegExpStatics *res = cx->regExpStatics();
    RegExpObject *reobj = builder.build(escapedSourceStr, RegExpFlag(flags | res->getFlags()));
    if (!reobj)
        return false;

    args.rval().setObject(*reobj);
    return true;
}
Exemplo n.º 14
0
/*
 * Compile a new |RegExpPrivate| for the |RegExpObject|.
 *
 * Per ECMAv5 15.10.4.1, we act on combinations of (pattern, flags) as
 * arguments:
 *
 *  RegExp, undefined => flags := pattern.flags
 *  RegExp, _ => throw TypeError
 *  _ => pattern := ToString(pattern) if defined(pattern) else ''
 *       flags := ToString(flags) if defined(flags) else ''
 */
static bool
CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder,
                    uintN argc, Value *argv, Value *rval)
{
    if (argc == 0) {
        RegExpStatics *res = cx->regExpStatics();
        RegExpObject *reobj = builder.build(cx->runtime->emptyString, res->getFlags());
        if (!reobj)
            return false;
        *rval = ObjectValue(*reobj);
        return true;
    }

    Value sourceValue = argv[0];
    if (ValueIsRegExp(sourceValue)) {
        /*
         * If we get passed in a |RegExpObject| source we return a new
         * object with the same source/flags.
         *
         * Note: the regexp static flags are not taken into consideration here.
         */
        JSObject &sourceObj = sourceValue.toObject();
        if (argc >= 2 && !argv[1].isUndefined()) {
            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NEWREGEXP_FLAGGED);
            return false;
        }

        RegExpObject *reobj = builder.build(sourceObj.asRegExp());
        if (!reobj)
            return false;
        *rval = ObjectValue(*reobj);
        return true;
    }

    JSLinearString *sourceStr;
    if (sourceValue.isUndefined()) {
        sourceStr = cx->runtime->emptyString;
    } else {
        /* Coerce to string and compile. */
        JSString *str = ToString(cx, sourceValue);
        if (!str)
            return false;
        sourceStr = str->ensureLinear(cx);
        if (!sourceStr)
            return false;
    }

    RegExpFlag flags = RegExpFlag(0);
    if (argc > 1 && !argv[1].isUndefined()) {
        JSString *flagStr = ToString(cx, argv[1]);
        if (!flagStr)
            return false;
        argv[1].setString(flagStr);
        if (!ParseRegExpFlags(cx, flagStr, &flags))
            return false;
    }

    JSLinearString *escapedSourceStr = EscapeNakedForwardSlashes(cx, sourceStr);
    if (!escapedSourceStr)
        return false;

    if (!CheckRegExpSyntax(cx, escapedSourceStr))
        return false;

    RegExpStatics *res = cx->regExpStatics();
    RegExpObject *reobj = builder.build(escapedSourceStr, RegExpFlag(flags | res->getFlags()));
    if (!reobj)
        return NULL;

    *rval = ObjectValue(*reobj);
    return true;
}