// ECMA 15.10.4
JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, JSValue newTarget)
{
    JSValue arg0 = args.at(0);
    JSValue arg1 = args.at(1);

    if (arg0.inherits(RegExpObject::info())) {
        if (!arg1.isUndefined())
            return exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Cannot supply flags when constructing one RegExp from another.")));
        // If called as a function, this just returns the first argument (see 15.10.3.1).
        if (newTarget != jsUndefined()) {
            RegExp* regExp = static_cast<RegExpObject*>(asObject(arg0))->regExp();

            return RegExpObject::create(exec->vm(), getRegExpStructure(exec, globalObject, newTarget), regExp);
        }
        return asObject(arg0);
    }

    String pattern = arg0.isUndefined() ? emptyString() : arg0.toString(exec)->value(exec);
    if (exec->hadException())
        return 0;

    RegExpFlags flags = NoFlags;
    if (!arg1.isUndefined()) {
        flags = regExpFlags(arg1.toString(exec)->value(exec));
        if (exec->hadException())
            return 0;
        if (flags == InvalidFlags)
            return exec->vm().throwException(exec, createSyntaxError(exec, ASCIILiteral("Invalid flags supplied to RegExp constructor.")));
    }

    VM& vm = exec->vm();
    RegExp* regExp = RegExp::create(vm, pattern, flags);
    if (!regExp->isValid())
        return vm.throwException(exec, createSyntaxError(exec, regExp->errorMessage()));

    return RegExpObject::create(vm, getRegExpStructure(exec, globalObject, newTarget), regExp);
}
JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args,  JSObject* callee, JSValue newTarget)
{
    VM& vm = exec->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);
    JSValue patternArg = args.at(0);
    JSValue flagsArg = args.at(1);

    bool isPatternRegExp = patternArg.inherits(vm, RegExpObject::info());
    bool constructAsRegexp = isRegExp(vm, exec, patternArg);
    RETURN_IF_EXCEPTION(scope, nullptr);

    if (newTarget.isUndefined() && constructAsRegexp && flagsArg.isUndefined()) {
        JSValue constructor = patternArg.get(exec, vm.propertyNames->constructor);
        RETURN_IF_EXCEPTION(scope, nullptr);
        if (callee == constructor) {
            // We know that patternArg is a object otherwise constructAsRegexp would be false.
            return patternArg.getObject();
        }
    }

    if (isPatternRegExp) {
        RegExp* regExp = jsCast<RegExpObject*>(patternArg)->regExp();
        Structure* structure = getRegExpStructure(exec, globalObject, newTarget);
        RETURN_IF_EXCEPTION(scope, nullptr);

        if (!flagsArg.isUndefined()) {
            RegExpFlags flags = toFlags(exec, flagsArg);
            ASSERT(!!scope.exception() == (flags == InvalidFlags));
            if (flags == InvalidFlags)
                return nullptr;
            regExp = RegExp::create(vm, regExp->pattern(), flags);
        }

        return RegExpObject::create(vm, structure, regExp);
    }

    if (constructAsRegexp) {
        JSValue pattern = patternArg.get(exec, vm.propertyNames->source);
        RETURN_IF_EXCEPTION(scope, nullptr);
        if (flagsArg.isUndefined()) {
            flagsArg = patternArg.get(exec, vm.propertyNames->flags);
            RETURN_IF_EXCEPTION(scope, nullptr);
        }
        patternArg = pattern;
    }

    scope.release();
    return regExpCreate(exec, globalObject, newTarget, patternArg, flagsArg);
}
static JSObject* regExpCreate(ExecState* exec, JSGlobalObject* globalObject, JSValue newTarget, JSValue patternArg, JSValue flagsArg)
{
    VM& vm = exec->vm();
    String pattern = patternArg.isUndefined() ? emptyString() : patternArg.toString(exec)->value(exec);
    if (exec->hadException())
        return nullptr;

    RegExpFlags flags = toFlags(exec, flagsArg);
    if (flags == InvalidFlags)
        return nullptr;

    RegExp* regExp = RegExp::create(vm, pattern, flags);
    if (!regExp->isValid())
        return vm.throwException(exec, createSyntaxError(exec, regExp->errorMessage()));

    Structure* structure = getRegExpStructure(exec, globalObject, newTarget);
    if (vm.exception())
        return nullptr;
    return RegExpObject::create(vm, structure, regExp);
}
static JSObject* regExpCreate(ExecState* exec, JSGlobalObject* globalObject, JSValue newTarget, JSValue patternArg, JSValue flagsArg)
{
    VM& vm = exec->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    String pattern = patternArg.isUndefined() ? emptyString() : patternArg.toWTFString(exec);
    RETURN_IF_EXCEPTION(scope, nullptr);

    RegExpFlags flags = toFlags(exec, flagsArg);
    ASSERT(!!scope.exception() == (flags == InvalidFlags));
    if (UNLIKELY(flags == InvalidFlags))
        return nullptr;

    RegExp* regExp = RegExp::create(vm, pattern, flags);
    if (!regExp->isValid())
        return throwException(exec, scope, createSyntaxError(exec, regExp->errorMessage()));

    Structure* structure = getRegExpStructure(exec, globalObject, newTarget);
    RETURN_IF_EXCEPTION(scope, nullptr);
    return RegExpObject::create(vm, structure, regExp);
}