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