]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/RegExpConstructor.cpp
JavaScriptCore-1097.3.3.tar.gz
[apple/javascriptcore.git] / runtime / RegExpConstructor.cpp
CommitLineData
9dae56ea
A
1/*
2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
ba379fdc 4 * Copyright (C) 2009 Torch Mobile, Inc.
9dae56ea
A
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21
22#include "config.h"
23#include "RegExpConstructor.h"
24
f9bf01c6 25#include "Error.h"
9dae56ea 26#include "RegExpMatchesArray.h"
9dae56ea 27#include "RegExpPrototype.h"
14957cd0
A
28
29#include <wtf/PassOwnPtr.h>
9dae56ea
A
30
31namespace JSC {
32
4e4e5a6f
A
33static JSValue regExpConstructorInput(ExecState*, JSValue, const Identifier&);
34static JSValue regExpConstructorMultiline(ExecState*, JSValue, const Identifier&);
35static JSValue regExpConstructorLastMatch(ExecState*, JSValue, const Identifier&);
36static JSValue regExpConstructorLastParen(ExecState*, JSValue, const Identifier&);
37static JSValue regExpConstructorLeftContext(ExecState*, JSValue, const Identifier&);
38static JSValue regExpConstructorRightContext(ExecState*, JSValue, const Identifier&);
39static JSValue regExpConstructorDollar1(ExecState*, JSValue, const Identifier&);
40static JSValue regExpConstructorDollar2(ExecState*, JSValue, const Identifier&);
41static JSValue regExpConstructorDollar3(ExecState*, JSValue, const Identifier&);
42static JSValue regExpConstructorDollar4(ExecState*, JSValue, const Identifier&);
43static JSValue regExpConstructorDollar5(ExecState*, JSValue, const Identifier&);
44static JSValue regExpConstructorDollar6(ExecState*, JSValue, const Identifier&);
45static JSValue regExpConstructorDollar7(ExecState*, JSValue, const Identifier&);
46static JSValue regExpConstructorDollar8(ExecState*, JSValue, const Identifier&);
47static JSValue regExpConstructorDollar9(ExecState*, JSValue, const Identifier&);
ba379fdc
A
48
49static void setRegExpConstructorInput(ExecState*, JSObject*, JSValue);
50static void setRegExpConstructorMultiline(ExecState*, JSObject*, JSValue);
9dae56ea
A
51
52} // namespace JSC
53
54#include "RegExpConstructor.lut.h"
55
56namespace JSC {
57
58ASSERT_CLASS_FITS_IN_CELL(RegExpConstructor);
59
6fe7ccc8 60const ClassInfo RegExpConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::regExpConstructorTable, CREATE_METHOD_TABLE(RegExpConstructor) };
9dae56ea
A
61
62/* Source for RegExpConstructor.lut.h
63@begin regExpConstructorTable
64 input regExpConstructorInput None
65 $_ regExpConstructorInput DontEnum
66 multiline regExpConstructorMultiline None
67 $* regExpConstructorMultiline DontEnum
68 lastMatch regExpConstructorLastMatch DontDelete|ReadOnly
69 $& regExpConstructorLastMatch DontDelete|ReadOnly|DontEnum
70 lastParen regExpConstructorLastParen DontDelete|ReadOnly
71 $+ regExpConstructorLastParen DontDelete|ReadOnly|DontEnum
72 leftContext regExpConstructorLeftContext DontDelete|ReadOnly
73 $` regExpConstructorLeftContext DontDelete|ReadOnly|DontEnum
74 rightContext regExpConstructorRightContext DontDelete|ReadOnly
75 $' regExpConstructorRightContext DontDelete|ReadOnly|DontEnum
76 $1 regExpConstructorDollar1 DontDelete|ReadOnly
77 $2 regExpConstructorDollar2 DontDelete|ReadOnly
78 $3 regExpConstructorDollar3 DontDelete|ReadOnly
79 $4 regExpConstructorDollar4 DontDelete|ReadOnly
80 $5 regExpConstructorDollar5 DontDelete|ReadOnly
81 $6 regExpConstructorDollar6 DontDelete|ReadOnly
82 $7 regExpConstructorDollar7 DontDelete|ReadOnly
83 $8 regExpConstructorDollar8 DontDelete|ReadOnly
84 $9 regExpConstructorDollar9 DontDelete|ReadOnly
85@end
86*/
87
6fe7ccc8
A
88RegExpConstructor::RegExpConstructor(JSGlobalObject* globalObject, Structure* structure, RegExpPrototype* regExpPrototype)
89 : InternalFunction(globalObject, structure)
90 , m_cachedResult(globalObject->globalData(), this, regExpPrototype->regExp())
91 , m_multiline(false)
92{
93}
94
95void RegExpConstructor::finishCreation(ExecState* exec, RegExpPrototype* regExpPrototype)
9dae56ea 96{
6fe7ccc8 97 Base::finishCreation(exec->globalData(), Identifier(exec, "RegExp"));
14957cd0
A
98 ASSERT(inherits(&s_info));
99
9dae56ea 100 // ECMA 15.10.5.1 RegExp.prototype
14957cd0 101 putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, regExpPrototype, DontEnum | DontDelete | ReadOnly);
9dae56ea
A
102
103 // no. of arguments for constructor
14957cd0 104 putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(2), ReadOnly | DontDelete | DontEnum);
9dae56ea
A
105}
106
6fe7ccc8 107void RegExpConstructor::destroy(JSCell* cell)
9dae56ea 108{
6fe7ccc8 109 jsCast<RegExpConstructor*>(cell)->RegExpConstructor::~RegExpConstructor();
9dae56ea
A
110}
111
6fe7ccc8 112void RegExpConstructor::visitChildren(JSCell* cell, SlotVisitor& visitor)
9dae56ea 113{
6fe7ccc8
A
114 RegExpConstructor* thisObject = jsCast<RegExpConstructor*>(cell);
115 ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
116 COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
117 ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
9dae56ea 118
6fe7ccc8
A
119 Base::visitChildren(thisObject, visitor);
120 thisObject->m_cachedResult.visitChildren(visitor);
9dae56ea
A
121}
122
6fe7ccc8 123JSValue RegExpConstructor::getBackref(ExecState* exec, unsigned i)
9dae56ea 124{
6fe7ccc8 125 RegExpMatchesArray* array = m_cachedResult.lastResult(exec, this);
9dae56ea 126
6fe7ccc8
A
127 if (i < array->length()) {
128 JSValue result = JSValue(array).get(exec, i);
129 ASSERT(result.isString() || result.isUndefined());
130 if (!result.isUndefined())
131 return result;
9dae56ea
A
132 }
133 return jsEmptyString(exec);
134}
135
6fe7ccc8 136JSValue RegExpConstructor::getLastParen(ExecState* exec)
9dae56ea 137{
6fe7ccc8
A
138 RegExpMatchesArray* array = m_cachedResult.lastResult(exec, this);
139 unsigned length = array->length();
140 if (length > 1) {
141 JSValue result = JSValue(array).get(exec, length - 1);
142 ASSERT(result.isString() || result.isUndefined());
143 if (!result.isUndefined())
144 return result;
9dae56ea
A
145 }
146 return jsEmptyString(exec);
147}
148
6fe7ccc8 149JSValue RegExpConstructor::getLeftContext(ExecState* exec)
9dae56ea 150{
6fe7ccc8 151 return m_cachedResult.lastResult(exec, this)->leftContext(exec);
9dae56ea
A
152}
153
6fe7ccc8 154JSValue RegExpConstructor::getRightContext(ExecState* exec)
9dae56ea 155{
6fe7ccc8 156 return m_cachedResult.lastResult(exec, this)->rightContext(exec);
9dae56ea
A
157}
158
6fe7ccc8 159bool RegExpConstructor::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
9dae56ea 160{
6fe7ccc8 161 return getStaticValueSlot<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), jsCast<RegExpConstructor*>(cell), propertyName, slot);
9dae56ea
A
162}
163
6fe7ccc8 164bool RegExpConstructor::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
f9bf01c6 165{
6fe7ccc8 166 return getStaticValueDescriptor<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), jsCast<RegExpConstructor*>(object), propertyName, descriptor);
f9bf01c6
A
167}
168
4e4e5a6f 169JSValue regExpConstructorDollar1(ExecState* exec, JSValue slotBase, const Identifier&)
9dae56ea 170{
4e4e5a6f 171 return asRegExpConstructor(slotBase)->getBackref(exec, 1);
9dae56ea
A
172}
173
4e4e5a6f 174JSValue regExpConstructorDollar2(ExecState* exec, JSValue slotBase, const Identifier&)
9dae56ea 175{
4e4e5a6f 176 return asRegExpConstructor(slotBase)->getBackref(exec, 2);
9dae56ea
A
177}
178
4e4e5a6f 179JSValue regExpConstructorDollar3(ExecState* exec, JSValue slotBase, const Identifier&)
9dae56ea 180{
4e4e5a6f 181 return asRegExpConstructor(slotBase)->getBackref(exec, 3);
9dae56ea
A
182}
183
4e4e5a6f 184JSValue regExpConstructorDollar4(ExecState* exec, JSValue slotBase, const Identifier&)
9dae56ea 185{
4e4e5a6f 186 return asRegExpConstructor(slotBase)->getBackref(exec, 4);
9dae56ea
A
187}
188
4e4e5a6f 189JSValue regExpConstructorDollar5(ExecState* exec, JSValue slotBase, const Identifier&)
9dae56ea 190{
4e4e5a6f 191 return asRegExpConstructor(slotBase)->getBackref(exec, 5);
9dae56ea
A
192}
193
4e4e5a6f 194JSValue regExpConstructorDollar6(ExecState* exec, JSValue slotBase, const Identifier&)
9dae56ea 195{
4e4e5a6f 196 return asRegExpConstructor(slotBase)->getBackref(exec, 6);
9dae56ea
A
197}
198
4e4e5a6f 199JSValue regExpConstructorDollar7(ExecState* exec, JSValue slotBase, const Identifier&)
9dae56ea 200{
4e4e5a6f 201 return asRegExpConstructor(slotBase)->getBackref(exec, 7);
9dae56ea
A
202}
203
4e4e5a6f 204JSValue regExpConstructorDollar8(ExecState* exec, JSValue slotBase, const Identifier&)
9dae56ea 205{
4e4e5a6f 206 return asRegExpConstructor(slotBase)->getBackref(exec, 8);
9dae56ea
A
207}
208
4e4e5a6f 209JSValue regExpConstructorDollar9(ExecState* exec, JSValue slotBase, const Identifier&)
9dae56ea 210{
4e4e5a6f 211 return asRegExpConstructor(slotBase)->getBackref(exec, 9);
9dae56ea
A
212}
213
6fe7ccc8 214JSValue regExpConstructorInput(ExecState*, JSValue slotBase, const Identifier&)
9dae56ea 215{
6fe7ccc8 216 return asRegExpConstructor(slotBase)->input();
9dae56ea
A
217}
218
4e4e5a6f 219JSValue regExpConstructorMultiline(ExecState*, JSValue slotBase, const Identifier&)
9dae56ea 220{
4e4e5a6f 221 return jsBoolean(asRegExpConstructor(slotBase)->multiline());
9dae56ea
A
222}
223
4e4e5a6f 224JSValue regExpConstructorLastMatch(ExecState* exec, JSValue slotBase, const Identifier&)
9dae56ea 225{
4e4e5a6f 226 return asRegExpConstructor(slotBase)->getBackref(exec, 0);
9dae56ea
A
227}
228
4e4e5a6f 229JSValue regExpConstructorLastParen(ExecState* exec, JSValue slotBase, const Identifier&)
9dae56ea 230{
4e4e5a6f 231 return asRegExpConstructor(slotBase)->getLastParen(exec);
9dae56ea
A
232}
233
4e4e5a6f 234JSValue regExpConstructorLeftContext(ExecState* exec, JSValue slotBase, const Identifier&)
9dae56ea 235{
4e4e5a6f 236 return asRegExpConstructor(slotBase)->getLeftContext(exec);
9dae56ea
A
237}
238
4e4e5a6f 239JSValue regExpConstructorRightContext(ExecState* exec, JSValue slotBase, const Identifier&)
9dae56ea 240{
4e4e5a6f 241 return asRegExpConstructor(slotBase)->getRightContext(exec);
9dae56ea
A
242}
243
6fe7ccc8 244void RegExpConstructor::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
9dae56ea 245{
6fe7ccc8 246 lookupPut<RegExpConstructor, InternalFunction>(exec, propertyName, value, ExecState::regExpConstructorTable(exec), jsCast<RegExpConstructor*>(cell), slot);
9dae56ea
A
247}
248
ba379fdc 249void setRegExpConstructorInput(ExecState* exec, JSObject* baseObject, JSValue value)
9dae56ea 250{
6fe7ccc8 251 asRegExpConstructor(baseObject)->setInput(exec, value.toString(exec));
9dae56ea
A
252}
253
ba379fdc 254void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValue value)
9dae56ea
A
255{
256 asRegExpConstructor(baseObject)->setMultiline(value.toBoolean(exec));
257}
14957cd0 258
9dae56ea 259// ECMA 15.10.4
6fe7ccc8 260JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, bool callAsConstructor)
9dae56ea 261{
ba379fdc
A
262 JSValue arg0 = args.at(0);
263 JSValue arg1 = args.at(1);
9dae56ea 264
14957cd0 265 if (arg0.inherits(&RegExpObject::s_info)) {
9dae56ea 266 if (!arg1.isUndefined())
14957cd0 267 return throwError(exec, createTypeError(exec, "Cannot supply flags when constructing one RegExp from another."));
6fe7ccc8
A
268 // If called as a function, this just returns the first argument (see 15.10.3.1).
269 if (callAsConstructor) {
270 RegExp* regExp = static_cast<RegExpObject*>(asObject(arg0))->regExp();
271 return RegExpObject::create(exec, globalObject, globalObject->regExpStructure(), regExp);
272 }
9dae56ea
A
273 return asObject(arg0);
274 }
275
6fe7ccc8 276 UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec)->value(exec);
14957cd0
A
277 if (exec->hadException())
278 return 0;
279
280 RegExpFlags flags = NoFlags;
281 if (!arg1.isUndefined()) {
6fe7ccc8 282 flags = regExpFlags(arg1.toString(exec)->value(exec));
14957cd0
A
283 if (exec->hadException())
284 return 0;
285 if (flags == InvalidFlags)
286 return throwError(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor."));
287 }
9dae56ea 288
6fe7ccc8 289 RegExp* regExp = RegExp::create(exec->globalData(), pattern, flags);
9dae56ea 290 if (!regExp->isValid())
14957cd0 291 return throwError(exec, createSyntaxError(exec, regExp->errorMessage()));
6fe7ccc8 292 return RegExpObject::create(exec, exec->lexicalGlobalObject(), globalObject->regExpStructure(), regExp);
9dae56ea
A
293}
294
14957cd0 295static EncodedJSValue JSC_HOST_CALL constructWithRegExpConstructor(ExecState* exec)
9dae56ea 296{
14957cd0 297 ArgList args(exec);
6fe7ccc8 298 return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args, true));
9dae56ea
A
299}
300
6fe7ccc8 301ConstructType RegExpConstructor::getConstructData(JSCell*, ConstructData& constructData)
9dae56ea
A
302{
303 constructData.native.function = constructWithRegExpConstructor;
304 return ConstructTypeHost;
305}
306
307// ECMA 15.10.3
14957cd0 308static EncodedJSValue JSC_HOST_CALL callRegExpConstructor(ExecState* exec)
9dae56ea 309{
14957cd0
A
310 ArgList args(exec);
311 return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args));
9dae56ea
A
312}
313
6fe7ccc8 314CallType RegExpConstructor::getCallData(JSCell*, CallData& callData)
9dae56ea
A
315{
316 callData.native.function = callRegExpConstructor;
317 return CallTypeHost;
318}
319
9dae56ea 320} // namespace JSC