]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/RegExpConstructor.cpp
JavaScriptCore-1097.3.tar.gz
[apple/javascriptcore.git] / runtime / RegExpConstructor.cpp
1 /*
2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
4 * Copyright (C) 2009 Torch Mobile, Inc.
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
25 #include "Error.h"
26 #include "RegExpMatchesArray.h"
27 #include "RegExpPrototype.h"
28
29 #include <wtf/PassOwnPtr.h>
30
31 namespace JSC {
32
33 static JSValue regExpConstructorInput(ExecState*, JSValue, const Identifier&);
34 static JSValue regExpConstructorMultiline(ExecState*, JSValue, const Identifier&);
35 static JSValue regExpConstructorLastMatch(ExecState*, JSValue, const Identifier&);
36 static JSValue regExpConstructorLastParen(ExecState*, JSValue, const Identifier&);
37 static JSValue regExpConstructorLeftContext(ExecState*, JSValue, const Identifier&);
38 static JSValue regExpConstructorRightContext(ExecState*, JSValue, const Identifier&);
39 static JSValue regExpConstructorDollar1(ExecState*, JSValue, const Identifier&);
40 static JSValue regExpConstructorDollar2(ExecState*, JSValue, const Identifier&);
41 static JSValue regExpConstructorDollar3(ExecState*, JSValue, const Identifier&);
42 static JSValue regExpConstructorDollar4(ExecState*, JSValue, const Identifier&);
43 static JSValue regExpConstructorDollar5(ExecState*, JSValue, const Identifier&);
44 static JSValue regExpConstructorDollar6(ExecState*, JSValue, const Identifier&);
45 static JSValue regExpConstructorDollar7(ExecState*, JSValue, const Identifier&);
46 static JSValue regExpConstructorDollar8(ExecState*, JSValue, const Identifier&);
47 static JSValue regExpConstructorDollar9(ExecState*, JSValue, const Identifier&);
48
49 static void setRegExpConstructorInput(ExecState*, JSObject*, JSValue);
50 static void setRegExpConstructorMultiline(ExecState*, JSObject*, JSValue);
51
52 } // namespace JSC
53
54 #include "RegExpConstructor.lut.h"
55
56 namespace JSC {
57
58 ASSERT_CLASS_FITS_IN_CELL(RegExpConstructor);
59
60 const ClassInfo RegExpConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::regExpConstructorTable, CREATE_METHOD_TABLE(RegExpConstructor) };
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
88 RegExpConstructor::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
95 void RegExpConstructor::finishCreation(ExecState* exec, RegExpPrototype* regExpPrototype)
96 {
97 Base::finishCreation(exec->globalData(), Identifier(exec, "RegExp"));
98 ASSERT(inherits(&s_info));
99
100 // ECMA 15.10.5.1 RegExp.prototype
101 putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, regExpPrototype, DontEnum | DontDelete | ReadOnly);
102
103 // no. of arguments for constructor
104 putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(2), ReadOnly | DontDelete | DontEnum);
105 }
106
107 void RegExpConstructor::destroy(JSCell* cell)
108 {
109 jsCast<RegExpConstructor*>(cell)->RegExpConstructor::~RegExpConstructor();
110 }
111
112 void RegExpConstructor::visitChildren(JSCell* cell, SlotVisitor& visitor)
113 {
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());
118
119 Base::visitChildren(thisObject, visitor);
120 thisObject->m_cachedResult.visitChildren(visitor);
121 }
122
123 JSValue RegExpConstructor::getBackref(ExecState* exec, unsigned i)
124 {
125 RegExpMatchesArray* array = m_cachedResult.lastResult(exec, this);
126
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;
132 }
133 return jsEmptyString(exec);
134 }
135
136 JSValue RegExpConstructor::getLastParen(ExecState* exec)
137 {
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;
145 }
146 return jsEmptyString(exec);
147 }
148
149 JSValue RegExpConstructor::getLeftContext(ExecState* exec)
150 {
151 return m_cachedResult.lastResult(exec, this)->leftContext(exec);
152 }
153
154 JSValue RegExpConstructor::getRightContext(ExecState* exec)
155 {
156 return m_cachedResult.lastResult(exec, this)->rightContext(exec);
157 }
158
159 bool RegExpConstructor::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
160 {
161 return getStaticValueSlot<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), jsCast<RegExpConstructor*>(cell), propertyName, slot);
162 }
163
164 bool RegExpConstructor::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
165 {
166 return getStaticValueDescriptor<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), jsCast<RegExpConstructor*>(object), propertyName, descriptor);
167 }
168
169 JSValue regExpConstructorDollar1(ExecState* exec, JSValue slotBase, const Identifier&)
170 {
171 return asRegExpConstructor(slotBase)->getBackref(exec, 1);
172 }
173
174 JSValue regExpConstructorDollar2(ExecState* exec, JSValue slotBase, const Identifier&)
175 {
176 return asRegExpConstructor(slotBase)->getBackref(exec, 2);
177 }
178
179 JSValue regExpConstructorDollar3(ExecState* exec, JSValue slotBase, const Identifier&)
180 {
181 return asRegExpConstructor(slotBase)->getBackref(exec, 3);
182 }
183
184 JSValue regExpConstructorDollar4(ExecState* exec, JSValue slotBase, const Identifier&)
185 {
186 return asRegExpConstructor(slotBase)->getBackref(exec, 4);
187 }
188
189 JSValue regExpConstructorDollar5(ExecState* exec, JSValue slotBase, const Identifier&)
190 {
191 return asRegExpConstructor(slotBase)->getBackref(exec, 5);
192 }
193
194 JSValue regExpConstructorDollar6(ExecState* exec, JSValue slotBase, const Identifier&)
195 {
196 return asRegExpConstructor(slotBase)->getBackref(exec, 6);
197 }
198
199 JSValue regExpConstructorDollar7(ExecState* exec, JSValue slotBase, const Identifier&)
200 {
201 return asRegExpConstructor(slotBase)->getBackref(exec, 7);
202 }
203
204 JSValue regExpConstructorDollar8(ExecState* exec, JSValue slotBase, const Identifier&)
205 {
206 return asRegExpConstructor(slotBase)->getBackref(exec, 8);
207 }
208
209 JSValue regExpConstructorDollar9(ExecState* exec, JSValue slotBase, const Identifier&)
210 {
211 return asRegExpConstructor(slotBase)->getBackref(exec, 9);
212 }
213
214 JSValue regExpConstructorInput(ExecState*, JSValue slotBase, const Identifier&)
215 {
216 return asRegExpConstructor(slotBase)->input();
217 }
218
219 JSValue regExpConstructorMultiline(ExecState*, JSValue slotBase, const Identifier&)
220 {
221 return jsBoolean(asRegExpConstructor(slotBase)->multiline());
222 }
223
224 JSValue regExpConstructorLastMatch(ExecState* exec, JSValue slotBase, const Identifier&)
225 {
226 return asRegExpConstructor(slotBase)->getBackref(exec, 0);
227 }
228
229 JSValue regExpConstructorLastParen(ExecState* exec, JSValue slotBase, const Identifier&)
230 {
231 return asRegExpConstructor(slotBase)->getLastParen(exec);
232 }
233
234 JSValue regExpConstructorLeftContext(ExecState* exec, JSValue slotBase, const Identifier&)
235 {
236 return asRegExpConstructor(slotBase)->getLeftContext(exec);
237 }
238
239 JSValue regExpConstructorRightContext(ExecState* exec, JSValue slotBase, const Identifier&)
240 {
241 return asRegExpConstructor(slotBase)->getRightContext(exec);
242 }
243
244 void RegExpConstructor::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
245 {
246 lookupPut<RegExpConstructor, InternalFunction>(exec, propertyName, value, ExecState::regExpConstructorTable(exec), jsCast<RegExpConstructor*>(cell), slot);
247 }
248
249 void setRegExpConstructorInput(ExecState* exec, JSObject* baseObject, JSValue value)
250 {
251 asRegExpConstructor(baseObject)->setInput(exec, value.toString(exec));
252 }
253
254 void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValue value)
255 {
256 asRegExpConstructor(baseObject)->setMultiline(value.toBoolean(exec));
257 }
258
259 // ECMA 15.10.4
260 JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, bool callAsConstructor)
261 {
262 JSValue arg0 = args.at(0);
263 JSValue arg1 = args.at(1);
264
265 if (arg0.inherits(&RegExpObject::s_info)) {
266 if (!arg1.isUndefined())
267 return throwError(exec, createTypeError(exec, "Cannot supply flags when constructing one RegExp from another."));
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 }
273 return asObject(arg0);
274 }
275
276 UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec)->value(exec);
277 if (exec->hadException())
278 return 0;
279
280 RegExpFlags flags = NoFlags;
281 if (!arg1.isUndefined()) {
282 flags = regExpFlags(arg1.toString(exec)->value(exec));
283 if (exec->hadException())
284 return 0;
285 if (flags == InvalidFlags)
286 return throwError(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor."));
287 }
288
289 RegExp* regExp = RegExp::create(exec->globalData(), pattern, flags);
290 if (!regExp->isValid())
291 return throwError(exec, createSyntaxError(exec, regExp->errorMessage()));
292 return RegExpObject::create(exec, exec->lexicalGlobalObject(), globalObject->regExpStructure(), regExp);
293 }
294
295 static EncodedJSValue JSC_HOST_CALL constructWithRegExpConstructor(ExecState* exec)
296 {
297 ArgList args(exec);
298 return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args, true));
299 }
300
301 ConstructType RegExpConstructor::getConstructData(JSCell*, ConstructData& constructData)
302 {
303 constructData.native.function = constructWithRegExpConstructor;
304 return ConstructTypeHost;
305 }
306
307 // ECMA 15.10.3
308 static EncodedJSValue JSC_HOST_CALL callRegExpConstructor(ExecState* exec)
309 {
310 ArgList args(exec);
311 return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args));
312 }
313
314 CallType RegExpConstructor::getCallData(JSCell*, CallData& callData)
315 {
316 callData.native.function = callRegExpConstructor;
317 return CallTypeHost;
318 }
319
320 } // namespace JSC