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 "Operations.h"
27 #include "RegExpMatchesArray.h"
28 #include "RegExpPrototype.h"
31 #include <wtf/PassOwnPtr.h>
36 static JSValue
regExpConstructorInput(ExecState
*, JSValue
, PropertyName
);
37 static JSValue
regExpConstructorMultiline(ExecState
*, JSValue
, PropertyName
);
38 static JSValue
regExpConstructorLastMatch(ExecState
*, JSValue
, PropertyName
);
39 static JSValue
regExpConstructorLastParen(ExecState
*, JSValue
, PropertyName
);
40 static JSValue
regExpConstructorLeftContext(ExecState
*, JSValue
, PropertyName
);
41 static JSValue
regExpConstructorRightContext(ExecState
*, JSValue
, PropertyName
);
42 static JSValue
regExpConstructorDollar1(ExecState
*, JSValue
, PropertyName
);
43 static JSValue
regExpConstructorDollar2(ExecState
*, JSValue
, PropertyName
);
44 static JSValue
regExpConstructorDollar3(ExecState
*, JSValue
, PropertyName
);
45 static JSValue
regExpConstructorDollar4(ExecState
*, JSValue
, PropertyName
);
46 static JSValue
regExpConstructorDollar5(ExecState
*, JSValue
, PropertyName
);
47 static JSValue
regExpConstructorDollar6(ExecState
*, JSValue
, PropertyName
);
48 static JSValue
regExpConstructorDollar7(ExecState
*, JSValue
, PropertyName
);
49 static JSValue
regExpConstructorDollar8(ExecState
*, JSValue
, PropertyName
);
50 static JSValue
regExpConstructorDollar9(ExecState
*, JSValue
, PropertyName
);
52 static void setRegExpConstructorInput(ExecState
*, JSObject
*, JSValue
);
53 static void setRegExpConstructorMultiline(ExecState
*, JSObject
*, JSValue
);
57 #include "RegExpConstructor.lut.h"
61 const ClassInfo
RegExpConstructor::s_info
= { "Function", &InternalFunction::s_info
, 0, ExecState::regExpConstructorTable
, CREATE_METHOD_TABLE(RegExpConstructor
) };
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
89 RegExpConstructor::RegExpConstructor(JSGlobalObject
* globalObject
, Structure
* structure
, RegExpPrototype
* regExpPrototype
)
90 : InternalFunction(globalObject
, structure
)
91 , m_cachedResult(globalObject
->vm(), this, regExpPrototype
->regExp())
96 void RegExpConstructor::finishCreation(ExecState
* exec
, RegExpPrototype
* regExpPrototype
)
98 Base::finishCreation(exec
->vm(), Identifier(exec
, "RegExp").string());
99 ASSERT(inherits(&s_info
));
101 // ECMA 15.10.5.1 RegExp.prototype
102 putDirectWithoutTransition(exec
->vm(), exec
->propertyNames().prototype
, regExpPrototype
, DontEnum
| DontDelete
| ReadOnly
);
104 // no. of arguments for constructor
105 putDirectWithoutTransition(exec
->vm(), exec
->propertyNames().length
, jsNumber(2), ReadOnly
| DontDelete
| DontEnum
);
108 void RegExpConstructor::destroy(JSCell
* cell
)
110 static_cast<RegExpConstructor
*>(cell
)->RegExpConstructor::~RegExpConstructor();
113 void RegExpConstructor::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
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());
120 Base::visitChildren(thisObject
, visitor
);
121 thisObject
->m_cachedResult
.visitChildren(visitor
);
124 JSValue
RegExpConstructor::getBackref(ExecState
* exec
, unsigned i
)
126 RegExpMatchesArray
* array
= m_cachedResult
.lastResult(exec
, this);
128 if (i
< array
->length()) {
129 JSValue result
= JSValue(array
).get(exec
, i
);
130 ASSERT(result
.isString() || result
.isUndefined());
131 if (!result
.isUndefined())
134 return jsEmptyString(exec
);
137 JSValue
RegExpConstructor::getLastParen(ExecState
* exec
)
139 RegExpMatchesArray
* array
= m_cachedResult
.lastResult(exec
, this);
140 unsigned length
= array
->length();
142 JSValue result
= JSValue(array
).get(exec
, length
- 1);
143 ASSERT(result
.isString() || result
.isUndefined());
144 if (!result
.isUndefined())
147 return jsEmptyString(exec
);
150 JSValue
RegExpConstructor::getLeftContext(ExecState
* exec
)
152 return m_cachedResult
.lastResult(exec
, this)->leftContext(exec
);
155 JSValue
RegExpConstructor::getRightContext(ExecState
* exec
)
157 return m_cachedResult
.lastResult(exec
, this)->rightContext(exec
);
160 bool RegExpConstructor::getOwnPropertySlot(JSCell
* cell
, ExecState
* exec
, PropertyName propertyName
, PropertySlot
& slot
)
162 return getStaticValueSlot
<RegExpConstructor
, InternalFunction
>(exec
, ExecState::regExpConstructorTable(exec
), jsCast
<RegExpConstructor
*>(cell
), propertyName
, slot
);
165 bool RegExpConstructor::getOwnPropertyDescriptor(JSObject
* object
, ExecState
* exec
, PropertyName propertyName
, PropertyDescriptor
& descriptor
)
167 return getStaticValueDescriptor
<RegExpConstructor
, InternalFunction
>(exec
, ExecState::regExpConstructorTable(exec
), jsCast
<RegExpConstructor
*>(object
), propertyName
, descriptor
);
170 JSValue
regExpConstructorDollar1(ExecState
* exec
, JSValue slotBase
, PropertyName
)
172 return asRegExpConstructor(slotBase
)->getBackref(exec
, 1);
175 JSValue
regExpConstructorDollar2(ExecState
* exec
, JSValue slotBase
, PropertyName
)
177 return asRegExpConstructor(slotBase
)->getBackref(exec
, 2);
180 JSValue
regExpConstructorDollar3(ExecState
* exec
, JSValue slotBase
, PropertyName
)
182 return asRegExpConstructor(slotBase
)->getBackref(exec
, 3);
185 JSValue
regExpConstructorDollar4(ExecState
* exec
, JSValue slotBase
, PropertyName
)
187 return asRegExpConstructor(slotBase
)->getBackref(exec
, 4);
190 JSValue
regExpConstructorDollar5(ExecState
* exec
, JSValue slotBase
, PropertyName
)
192 return asRegExpConstructor(slotBase
)->getBackref(exec
, 5);
195 JSValue
regExpConstructorDollar6(ExecState
* exec
, JSValue slotBase
, PropertyName
)
197 return asRegExpConstructor(slotBase
)->getBackref(exec
, 6);
200 JSValue
regExpConstructorDollar7(ExecState
* exec
, JSValue slotBase
, PropertyName
)
202 return asRegExpConstructor(slotBase
)->getBackref(exec
, 7);
205 JSValue
regExpConstructorDollar8(ExecState
* exec
, JSValue slotBase
, PropertyName
)
207 return asRegExpConstructor(slotBase
)->getBackref(exec
, 8);
210 JSValue
regExpConstructorDollar9(ExecState
* exec
, JSValue slotBase
, PropertyName
)
212 return asRegExpConstructor(slotBase
)->getBackref(exec
, 9);
215 JSValue
regExpConstructorInput(ExecState
*, JSValue slotBase
, PropertyName
)
217 return asRegExpConstructor(slotBase
)->input();
220 JSValue
regExpConstructorMultiline(ExecState
*, JSValue slotBase
, PropertyName
)
222 return jsBoolean(asRegExpConstructor(slotBase
)->multiline());
225 JSValue
regExpConstructorLastMatch(ExecState
* exec
, JSValue slotBase
, PropertyName
)
227 return asRegExpConstructor(slotBase
)->getBackref(exec
, 0);
230 JSValue
regExpConstructorLastParen(ExecState
* exec
, JSValue slotBase
, PropertyName
)
232 return asRegExpConstructor(slotBase
)->getLastParen(exec
);
235 JSValue
regExpConstructorLeftContext(ExecState
* exec
, JSValue slotBase
, PropertyName
)
237 return asRegExpConstructor(slotBase
)->getLeftContext(exec
);
240 JSValue
regExpConstructorRightContext(ExecState
* exec
, JSValue slotBase
, PropertyName
)
242 return asRegExpConstructor(slotBase
)->getRightContext(exec
);
245 void RegExpConstructor::put(JSCell
* cell
, ExecState
* exec
, PropertyName propertyName
, JSValue value
, PutPropertySlot
& slot
)
247 lookupPut
<RegExpConstructor
, InternalFunction
>(exec
, propertyName
, value
, ExecState::regExpConstructorTable(exec
), jsCast
<RegExpConstructor
*>(cell
), slot
);
250 void setRegExpConstructorInput(ExecState
* exec
, JSObject
* baseObject
, JSValue value
)
252 asRegExpConstructor(baseObject
)->setInput(exec
, value
.toString(exec
));
255 void setRegExpConstructorMultiline(ExecState
* exec
, JSObject
* baseObject
, JSValue value
)
257 asRegExpConstructor(baseObject
)->setMultiline(value
.toBoolean(exec
));
261 JSObject
* constructRegExp(ExecState
* exec
, JSGlobalObject
* globalObject
, const ArgList
& args
, bool callAsConstructor
)
263 JSValue arg0
= args
.at(0);
264 JSValue arg1
= args
.at(1);
266 if (arg0
.inherits(&RegExpObject::s_info
)) {
267 if (!arg1
.isUndefined())
268 return throwError(exec
, createTypeError(exec
, ASCIILiteral("Cannot supply flags when constructing one RegExp from another.")));
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
);
274 return asObject(arg0
);
277 String pattern
= arg0
.isUndefined() ? String("") : arg0
.toString(exec
)->value(exec
);
278 if (exec
->hadException())
281 RegExpFlags flags
= NoFlags
;
282 if (!arg1
.isUndefined()) {
283 flags
= regExpFlags(arg1
.toString(exec
)->value(exec
));
284 if (exec
->hadException())
286 if (flags
== InvalidFlags
)
287 return throwError(exec
, createSyntaxError(exec
, ASCIILiteral("Invalid flags supplied to RegExp constructor.")));
290 RegExp
* regExp
= RegExp::create(exec
->vm(), pattern
, flags
);
291 if (!regExp
->isValid())
292 return throwError(exec
, createSyntaxError(exec
, regExp
->errorMessage()));
293 return RegExpObject::create(exec
, exec
->lexicalGlobalObject(), globalObject
->regExpStructure(), regExp
);
296 static EncodedJSValue JSC_HOST_CALL
constructWithRegExpConstructor(ExecState
* exec
)
299 return JSValue::encode(constructRegExp(exec
, asInternalFunction(exec
->callee())->globalObject(), args
, true));
302 ConstructType
RegExpConstructor::getConstructData(JSCell
*, ConstructData
& constructData
)
304 constructData
.native
.function
= constructWithRegExpConstructor
;
305 return ConstructTypeHost
;
309 static EncodedJSValue JSC_HOST_CALL
callRegExpConstructor(ExecState
* exec
)
312 return JSValue::encode(constructRegExp(exec
, asInternalFunction(exec
->callee())->globalObject(), args
));
315 CallType
RegExpConstructor::getCallData(JSCell
*, CallData
& callData
)
317 callData
.native
.function
= callRegExpConstructor
;