18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  This library is free software; you can redistribute it and/or
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  modify it under the terms of the GNU Lesser General Public
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  License as published by the Free Software Foundation; either
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  version 2 of the License, or (at your option) any later version.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  This library is distributed in the hope that it will be useful,
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  but WITHOUT ANY WARRANTY; without even the implied warranty of
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  Lesser General Public License for more details.
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  You should have received a copy of the GNU Lesser General Public
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  License along with this library; if not, write to the Free Software
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RegExpObject.h"
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "Error.h"
25545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch#include "ExceptionHelpers.h"
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSArray.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSGlobalObject.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSString.h"
29dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "Lookup.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RegExpConstructor.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RegExpPrototype.h"
32a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "UStringConcatenate.h"
33e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#include <wtf/PassOwnPtr.h>
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace JSC {
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
37dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic JSValue regExpObjectGlobal(ExecState*, JSValue, const Identifier&);
38dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic JSValue regExpObjectIgnoreCase(ExecState*, JSValue, const Identifier&);
39dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic JSValue regExpObjectMultiline(ExecState*, JSValue, const Identifier&);
40dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic JSValue regExpObjectSource(ExecState*, JSValue, const Identifier&);
41dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic JSValue regExpObjectLastIndex(ExecState*, JSValue, const Identifier&);
425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic void setRegExpObjectLastIndex(ExecState*, JSObject*, JSValue);
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace JSC
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RegExpObject.lut.h"
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace JSC {
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectASSERT_CLASS_FITS_IN_CELL(RegExpObject);
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochconst ClassInfo RegExpObject::s_info = { "RegExp", &JSObjectWithGlobalObject::s_info, 0, ExecState::regExpTable };
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* Source for RegExpObject.lut.h
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@begin regExpTable
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    global        regExpObjectGlobal       DontDelete|ReadOnly|DontEnum
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ignoreCase    regExpObjectIgnoreCase   DontDelete|ReadOnly|DontEnum
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    multiline     regExpObjectMultiline    DontDelete|ReadOnly|DontEnum
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    source        regExpObjectSource       DontDelete|ReadOnly|DontEnum
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    lastIndex     regExpObjectLastIndex    DontDelete|DontEnum
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@end
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project*/
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochRegExpObject::RegExpObject(JSGlobalObject* globalObject, Structure* structure, NonNullPassRefPtr<RegExp> regExp)
65e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block    : JSObjectWithGlobalObject(globalObject, structure)
662bde8e466a4451c7319e3a072d118917957d6554Steve Block    , d(adoptPtr(new RegExpObjectData(regExp)))
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(inherits(&s_info));
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectRegExpObject::~RegExpObject()
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
752bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid RegExpObject::markChildren(MarkStack& markStack)
762bde8e466a4451c7319e3a072d118917957d6554Steve Block{
772bde8e466a4451c7319e3a072d118917957d6554Steve Block    Base::markChildren(markStack);
782bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (UNLIKELY(!d->lastIndex.get().isInt32()))
792bde8e466a4451c7319e3a072d118917957d6554Steve Block        markStack.append(&d->lastIndex);
802bde8e466a4451c7319e3a072d118917957d6554Steve Block}
812bde8e466a4451c7319e3a072d118917957d6554Steve Block
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool RegExpObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot);
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
87231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool RegExpObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
88231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
89231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return getStaticValueDescriptor<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, descriptor);
90231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
91231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
92dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockJSValue regExpObjectGlobal(ExecState*, JSValue slotBase, const Identifier&)
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
94dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return jsBoolean(asRegExpObject(slotBase)->regExp()->global());
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
97dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockJSValue regExpObjectIgnoreCase(ExecState*, JSValue slotBase, const Identifier&)
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
99dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return jsBoolean(asRegExpObject(slotBase)->regExp()->ignoreCase());
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
102dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockJSValue regExpObjectMultiline(ExecState*, JSValue slotBase, const Identifier&)
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
104dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return jsBoolean(asRegExpObject(slotBase)->regExp()->multiline());
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
107dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockJSValue regExpObjectSource(ExecState* exec, JSValue slotBase, const Identifier&)
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
109dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return jsString(exec, asRegExpObject(slotBase)->regExp()->pattern());
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
112e14391e94c850b8bd03680c23b38978db68687a8John ReckJSValue regExpObjectLastIndex(ExecState*, JSValue slotBase, const Identifier&)
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1142bde8e466a4451c7319e3a072d118917957d6554Steve Block    return asRegExpObject(slotBase)->getLastIndex();
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), this, slot);
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValue value)
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1242bde8e466a4451c7319e3a072d118917957d6554Steve Block    asRegExpObject(baseObject)->setLastIndex(exec->globalData(), value);
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1275af96e2c7b73ebc627c6894727826a7576d31758Leon ClarkeJSValue RegExpObject::test(ExecState* exec)
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1295af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    return jsBoolean(match(exec));
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1325af96e2c7b73ebc627c6894727826a7576d31758Leon ClarkeJSValue RegExpObject::exec(ExecState* exec)
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1345af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    if (match(exec))
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return exec->lexicalGlobalObject()->regExpConstructor()->arrayOfMatches(exec);
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return jsNull();
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
139635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// Shared implementation used by test and exec.
1405af96e2c7b73ebc627c6894727826a7576d31758Leon Clarkebool RegExpObject::match(ExecState* exec)
141635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
142635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
1432bde8e466a4451c7319e3a072d118917957d6554Steve Block    UString input = exec->argument(0).toString(exec);
144635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
145635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!regExp()->global()) {
146635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        int position;
147635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        int length;
148635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        regExpConstructor->performMatch(d->regExp.get(), input, 0, position, length);
149635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return position >= 0;
150635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
151635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1522bde8e466a4451c7319e3a072d118917957d6554Steve Block    JSValue jsLastIndex = getLastIndex();
1532bde8e466a4451c7319e3a072d118917957d6554Steve Block    unsigned lastIndex;
1542bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (LIKELY(jsLastIndex.isUInt32())) {
1552bde8e466a4451c7319e3a072d118917957d6554Steve Block        lastIndex = jsLastIndex.asUInt32();
1562bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (lastIndex > input.length()) {
1572bde8e466a4451c7319e3a072d118917957d6554Steve Block            setLastIndex(0);
1582bde8e466a4451c7319e3a072d118917957d6554Steve Block            return false;
1592bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
1602bde8e466a4451c7319e3a072d118917957d6554Steve Block    } else {
1612bde8e466a4451c7319e3a072d118917957d6554Steve Block        double doubleLastIndex = jsLastIndex.toInteger(exec);
1622bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (doubleLastIndex < 0 || doubleLastIndex > input.length()) {
1632bde8e466a4451c7319e3a072d118917957d6554Steve Block            setLastIndex(0);
1642bde8e466a4451c7319e3a072d118917957d6554Steve Block            return false;
1652bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
1662bde8e466a4451c7319e3a072d118917957d6554Steve Block        lastIndex = static_cast<unsigned>(doubleLastIndex);
167635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
168635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
169635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    int position;
170cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    int length = 0;
1712bde8e466a4451c7319e3a072d118917957d6554Steve Block    regExpConstructor->performMatch(d->regExp.get(), input, lastIndex, position, length);
172635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (position < 0) {
1732bde8e466a4451c7319e3a072d118917957d6554Steve Block        setLastIndex(0);
174635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return false;
175635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
176635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1772bde8e466a4451c7319e3a072d118917957d6554Steve Block    setLastIndex(position + length);
178635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return true;
179635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
180635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace JSC
182