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.
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.
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.
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
23 #include "RegExpConstructor.h"
26 #include "RegExpMatchesArray.h"
27 #include "RegExpPrototype.h"
29 #include <wtf/PassOwnPtr.h>
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
&);
49 static void setRegExpConstructorInput(ExecState
*, JSObject
*, JSValue
);
50 static void setRegExpConstructorMultiline(ExecState
*, JSObject
*, JSValue
);
54 #include "RegExpConstructor.lut.h"
58 ASSERT_CLASS_FITS_IN_CELL(RegExpConstructor
);
60 const ClassInfo
RegExpConstructor::s_info
= { "Function", &InternalFunction::s_info
, 0, ExecState::regExpConstructorTable
, CREATE_METHOD_TABLE(RegExpConstructor
) };
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
88 RegExpConstructor::RegExpConstructor(JSGlobalObject
* globalObject
, Structure
* structure
, RegExpPrototype
* regExpPrototype
)
89 : InternalFunction(globalObject
, structure
)
90 , m_cachedResult(globalObject
->globalData(), this, regExpPrototype
->regExp())
95 void RegExpConstructor::finishCreation(ExecState
* exec
, RegExpPrototype
* regExpPrototype
)
97 Base::finishCreation(exec
->globalData(), Identifier(exec
, "RegExp"));
98 ASSERT(inherits(&s_info
));
100 // ECMA 15.10.5.1 RegExp.prototype
101 putDirectWithoutTransition(exec
->globalData(), exec
->propertyNames().prototype
, regExpPrototype
, DontEnum
| DontDelete
| ReadOnly
);
103 // no. of arguments for constructor
104 putDirectWithoutTransition(exec
->globalData(), exec
->propertyNames().length
, jsNumber(2), ReadOnly
| DontDelete
| DontEnum
);
107 void RegExpConstructor::destroy(JSCell
* cell
)
109 jsCast
<RegExpConstructor
*>(cell
)->RegExpConstructor::~RegExpConstructor();
112 void RegExpConstructor::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
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());
119 Base::visitChildren(thisObject
, visitor
);
120 thisObject
->m_cachedResult
.visitChildren(visitor
);
123 JSValue
RegExpConstructor::getBackref(ExecState
* exec
, unsigned i
)
125 RegExpMatchesArray
* array
= m_cachedResult
.lastResult(exec
, this);
127 if (i
< array
->length()) {
128 JSValue result
= JSValue(array
).get(exec
, i
);
129 ASSERT(result
.isString() || result
.isUndefined());
130 if (!result
.isUndefined())
133 return jsEmptyString(exec
);
136 JSValue
RegExpConstructor::getLastParen(ExecState
* exec
)
138 RegExpMatchesArray
* array
= m_cachedResult
.lastResult(exec
, this);
139 unsigned length
= array
->length();
141 JSValue result
= JSValue(array
).get(exec
, length
- 1);
142 ASSERT(result
.isString() || result
.isUndefined());
143 if (!result
.isUndefined())
146 return jsEmptyString(exec
);
149 JSValue
RegExpConstructor::getLeftContext(ExecState
* exec
)
151 return m_cachedResult
.lastResult(exec
, this)->leftContext(exec
);
154 JSValue
RegExpConstructor::getRightContext(ExecState
* exec
)
156 return m_cachedResult
.lastResult(exec
, this)->rightContext(exec
);
159 bool RegExpConstructor::getOwnPropertySlot(JSCell
* cell
, ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
)
161 return getStaticValueSlot
<RegExpConstructor
, InternalFunction
>(exec
, ExecState::regExpConstructorTable(exec
), jsCast
<RegExpConstructor
*>(cell
), propertyName
, slot
);
164 bool RegExpConstructor::getOwnPropertyDescriptor(JSObject
* object
, ExecState
* exec
, const Identifier
& propertyName
, PropertyDescriptor
& descriptor
)
166 return getStaticValueDescriptor
<RegExpConstructor
, InternalFunction
>(exec
, ExecState::regExpConstructorTable(exec
), jsCast
<RegExpConstructor
*>(object
), propertyName
, descriptor
);
169 JSValue
regExpConstructorDollar1(ExecState
* exec
, JSValue slotBase
, const Identifier
&)
171 return asRegExpConstructor(slotBase
)->getBackref(exec
, 1);
174 JSValue
regExpConstructorDollar2(ExecState
* exec
, JSValue slotBase
, const Identifier
&)
176 return asRegExpConstructor(slotBase
)->getBackref(exec
, 2);
179 JSValue
regExpConstructorDollar3(ExecState
* exec
, JSValue slotBase
, const Identifier
&)
181 return asRegExpConstructor(slotBase
)->getBackref(exec
, 3);
184 JSValue
regExpConstructorDollar4(ExecState
* exec
, JSValue slotBase
, const Identifier
&)
186 return asRegExpConstructor(slotBase
)->getBackref(exec
, 4);
189 JSValue
regExpConstructorDollar5(ExecState
* exec
, JSValue slotBase
, const Identifier
&)
191 return asRegExpConstructor(slotBase
)->getBackref(exec
, 5);
194 JSValue
regExpConstructorDollar6(ExecState
* exec
, JSValue slotBase
, const Identifier
&)
196 return asRegExpConstructor(slotBase
)->getBackref(exec
, 6);
199 JSValue
regExpConstructorDollar7(ExecState
* exec
, JSValue slotBase
, const Identifier
&)
201 return asRegExpConstructor(slotBase
)->getBackref(exec
, 7);
204 JSValue
regExpConstructorDollar8(ExecState
* exec
, JSValue slotBase
, const Identifier
&)
206 return asRegExpConstructor(slotBase
)->getBackref(exec
, 8);
209 JSValue
regExpConstructorDollar9(ExecState
* exec
, JSValue slotBase
, const Identifier
&)
211 return asRegExpConstructor(slotBase
)->getBackref(exec
, 9);
214 JSValue
regExpConstructorInput(ExecState
*, JSValue slotBase
, const Identifier
&)
216 return asRegExpConstructor(slotBase
)->input();
219 JSValue
regExpConstructorMultiline(ExecState
*, JSValue slotBase
, const Identifier
&)
221 return jsBoolean(asRegExpConstructor(slotBase
)->multiline());
224 JSValue
regExpConstructorLastMatch(ExecState
* exec
, JSValue slotBase
, const Identifier
&)
226 return asRegExpConstructor(slotBase
)->getBackref(exec
, 0);
229 JSValue
regExpConstructorLastParen(ExecState
* exec
, JSValue slotBase
, const Identifier
&)
231 return asRegExpConstructor(slotBase
)->getLastParen(exec
);
234 JSValue
regExpConstructorLeftContext(ExecState
* exec
, JSValue slotBase
, const Identifier
&)
236 return asRegExpConstructor(slotBase
)->getLeftContext(exec
);
239 JSValue
regExpConstructorRightContext(ExecState
* exec
, JSValue slotBase
, const Identifier
&)
241 return asRegExpConstructor(slotBase
)->getRightContext(exec
);
244 void RegExpConstructor::put(JSCell
* cell
, ExecState
* exec
, const Identifier
& propertyName
, JSValue value
, PutPropertySlot
& slot
)
246 lookupPut
<RegExpConstructor
, InternalFunction
>(exec
, propertyName
, value
, ExecState::regExpConstructorTable(exec
), jsCast
<RegExpConstructor
*>(cell
), slot
);
249 void setRegExpConstructorInput(ExecState
* exec
, JSObject
* baseObject
, JSValue value
)
251 asRegExpConstructor(baseObject
)->setInput(exec
, value
.toString(exec
));
254 void setRegExpConstructorMultiline(ExecState
* exec
, JSObject
* baseObject
, JSValue value
)
256 asRegExpConstructor(baseObject
)->setMultiline(value
.toBoolean(exec
));
260 JSObject
* constructRegExp(ExecState
* exec
, JSGlobalObject
* globalObject
, const ArgList
& args
, bool callAsConstructor
)
262 JSValue arg0
= args
.at(0);
263 JSValue arg1
= args
.at(1);
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
);
273 return asObject(arg0
);
276 UString pattern
= arg0
.isUndefined() ? UString("") : arg0
.toString(exec
)->value(exec
);
277 if (exec
->hadException())
280 RegExpFlags flags
= NoFlags
;
281 if (!arg1
.isUndefined()) {
282 flags
= regExpFlags(arg1
.toString(exec
)->value(exec
));
283 if (exec
->hadException())
285 if (flags
== InvalidFlags
)
286 return throwError(exec
, createSyntaxError(exec
, "Invalid flags supplied to RegExp constructor."));
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
);
295 static EncodedJSValue JSC_HOST_CALL
constructWithRegExpConstructor(ExecState
* exec
)
298 return JSValue::encode(constructRegExp(exec
, asInternalFunction(exec
->callee())->globalObject(), args
, true));
301 ConstructType
RegExpConstructor::getConstructData(JSCell
*, ConstructData
& constructData
)
303 constructData
.native
.function
= constructWithRegExpConstructor
;
304 return ConstructTypeHost
;
308 static EncodedJSValue JSC_HOST_CALL
callRegExpConstructor(ExecState
* exec
)
311 return JSValue::encode(constructRegExp(exec
, asInternalFunction(exec
->callee())->globalObject(), args
));
314 CallType
RegExpConstructor::getCallData(JSCell
*, CallData
& callData
)
316 callData
.native
.function
= callRegExpConstructor
;