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));
}
RegExpObject *
RegExpObjectBuilder::build(RegExpObject *other)
{
    RegExpPrivate *rep = other->getOrCreatePrivate(cx);
    if (!rep)
        return NULL;

    /* Now, incref it for the RegExpObject being built. */
    rep->incref(cx);
    return build(AlreadyIncRefed<RegExpPrivate>(rep));
}
Example #3
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, RegExpObject *obj, uintN argc, Value *argv, Value *rval)
{
    if (argc == 0) {
        if (!ResetRegExpObjectWithStatics(cx, obj, cx->runtime->emptyString))
            return false;
        *rval = ObjectValue(*obj);
        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 |RegExpPrivate|.
         *
         * 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;
        }

        RegExpPrivate *rep = sourceObj.asRegExp()->getPrivate();
        if (!rep)
            return false;

        rep->incref(cx);
        if (!ResetRegExpObject(cx, obj, AlreadyIncRefed<RegExpPrivate>(rep)))
            return false;
        *rval = ObjectValue(*obj);
        return true;
    }

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

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

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

    if (!ResetRegExpObjectWithStatics(cx, obj, escapedSourceStr, flags))
        return false;
    *rval = ObjectValue(*obj);
    return true;
}