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 "JSCInlines.h"
27 #include "RegExpMatchesArray.h"
28 #include "RegExpPrototype.h"
32 static EncodedJSValue
regExpConstructorInput(ExecState
*, JSObject
*, EncodedJSValue
, PropertyName
);
33 static EncodedJSValue
regExpConstructorMultiline(ExecState
*, JSObject
*, EncodedJSValue
, PropertyName
);
34 static EncodedJSValue
regExpConstructorLastMatch(ExecState
*, JSObject
*, EncodedJSValue
, PropertyName
);
35 static EncodedJSValue
regExpConstructorLastParen(ExecState
*, JSObject
*, EncodedJSValue
, PropertyName
);
36 static EncodedJSValue
regExpConstructorLeftContext(ExecState
*, JSObject
*, EncodedJSValue
, PropertyName
);
37 static EncodedJSValue
regExpConstructorRightContext(ExecState
*, JSObject
*, EncodedJSValue
, PropertyName
);
38 static EncodedJSValue
regExpConstructorDollar1(ExecState
*, JSObject
*, EncodedJSValue
, PropertyName
);
39 static EncodedJSValue
regExpConstructorDollar2(ExecState
*, JSObject
*, EncodedJSValue
, PropertyName
);
40 static EncodedJSValue
regExpConstructorDollar3(ExecState
*, JSObject
*, EncodedJSValue
, PropertyName
);
41 static EncodedJSValue
regExpConstructorDollar4(ExecState
*, JSObject
*, EncodedJSValue
, PropertyName
);
42 static EncodedJSValue
regExpConstructorDollar5(ExecState
*, JSObject
*, EncodedJSValue
, PropertyName
);
43 static EncodedJSValue
regExpConstructorDollar6(ExecState
*, JSObject
*, EncodedJSValue
, PropertyName
);
44 static EncodedJSValue
regExpConstructorDollar7(ExecState
*, JSObject
*, EncodedJSValue
, PropertyName
);
45 static EncodedJSValue
regExpConstructorDollar8(ExecState
*, JSObject
*, EncodedJSValue
, PropertyName
);
46 static EncodedJSValue
regExpConstructorDollar9(ExecState
*, JSObject
*, EncodedJSValue
, PropertyName
);
48 static void setRegExpConstructorInput(ExecState
*, JSObject
*, EncodedJSValue
, EncodedJSValue
);
49 static void setRegExpConstructorMultiline(ExecState
*, JSObject
*, EncodedJSValue
, EncodedJSValue
);
53 #include "RegExpConstructor.lut.h"
57 const ClassInfo
RegExpConstructor::s_info
= { "Function", &InternalFunction::s_info
, ®ExpConstructorTable
, CREATE_METHOD_TABLE(RegExpConstructor
) };
59 /* Source for RegExpConstructor.lut.h
60 @begin regExpConstructorTable
61 input regExpConstructorInput None
62 $_ regExpConstructorInput DontEnum
63 multiline regExpConstructorMultiline None
64 $* regExpConstructorMultiline DontEnum
65 lastMatch regExpConstructorLastMatch DontDelete|ReadOnly
66 $& regExpConstructorLastMatch DontDelete|ReadOnly|DontEnum
67 lastParen regExpConstructorLastParen DontDelete|ReadOnly
68 $+ regExpConstructorLastParen DontDelete|ReadOnly|DontEnum
69 leftContext regExpConstructorLeftContext DontDelete|ReadOnly
70 $` regExpConstructorLeftContext DontDelete|ReadOnly|DontEnum
71 rightContext regExpConstructorRightContext DontDelete|ReadOnly
72 $' regExpConstructorRightContext DontDelete|ReadOnly|DontEnum
73 $1 regExpConstructorDollar1 DontDelete|ReadOnly
74 $2 regExpConstructorDollar2 DontDelete|ReadOnly
75 $3 regExpConstructorDollar3 DontDelete|ReadOnly
76 $4 regExpConstructorDollar4 DontDelete|ReadOnly
77 $5 regExpConstructorDollar5 DontDelete|ReadOnly
78 $6 regExpConstructorDollar6 DontDelete|ReadOnly
79 $7 regExpConstructorDollar7 DontDelete|ReadOnly
80 $8 regExpConstructorDollar8 DontDelete|ReadOnly
81 $9 regExpConstructorDollar9 DontDelete|ReadOnly
85 RegExpConstructor::RegExpConstructor(VM
& vm
, Structure
* structure
, RegExpPrototype
* regExpPrototype
)
86 : InternalFunction(vm
, structure
)
87 , m_cachedResult(vm
, this, regExpPrototype
->regExp())
92 void RegExpConstructor::finishCreation(VM
& vm
, RegExpPrototype
* regExpPrototype
)
94 Base::finishCreation(vm
, regExpPrototype
->classInfo()->className
);
95 ASSERT(inherits(info()));
97 // ECMA 15.10.5.1 RegExp.prototype
98 putDirectWithoutTransition(vm
, vm
.propertyNames
->prototype
, regExpPrototype
, DontEnum
| DontDelete
| ReadOnly
);
100 // no. of arguments for constructor
101 putDirectWithoutTransition(vm
, vm
.propertyNames
->length
, jsNumber(2), ReadOnly
| DontDelete
| DontEnum
);
104 void RegExpConstructor::destroy(JSCell
* cell
)
106 static_cast<RegExpConstructor
*>(cell
)->RegExpConstructor::~RegExpConstructor();
109 void RegExpConstructor::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
111 RegExpConstructor
* thisObject
= jsCast
<RegExpConstructor
*>(cell
);
112 ASSERT_GC_OBJECT_INHERITS(thisObject
, info());
113 Base::visitChildren(thisObject
, visitor
);
114 thisObject
->m_cachedResult
.visitChildren(visitor
);
117 JSValue
RegExpConstructor::getBackref(ExecState
* exec
, unsigned i
)
119 JSArray
* array
= m_cachedResult
.lastResult(exec
, this);
121 if (i
< array
->length()) {
122 JSValue result
= JSValue(array
).get(exec
, i
);
123 ASSERT(result
.isString() || result
.isUndefined());
124 if (!result
.isUndefined())
127 return jsEmptyString(exec
);
130 JSValue
RegExpConstructor::getLastParen(ExecState
* exec
)
132 JSArray
* array
= m_cachedResult
.lastResult(exec
, this);
133 unsigned length
= array
->length();
135 JSValue result
= JSValue(array
).get(exec
, length
- 1);
136 ASSERT(result
.isString() || result
.isUndefined());
137 if (!result
.isUndefined())
140 return jsEmptyString(exec
);
143 JSValue
RegExpConstructor::getLeftContext(ExecState
* exec
)
145 return m_cachedResult
.leftContext(exec
, this);
148 JSValue
RegExpConstructor::getRightContext(ExecState
* exec
)
150 return m_cachedResult
.rightContext(exec
, this);
153 bool RegExpConstructor::getOwnPropertySlot(JSObject
* object
, ExecState
* exec
, PropertyName propertyName
, PropertySlot
& slot
)
155 return getStaticValueSlot
<RegExpConstructor
, InternalFunction
>(exec
, regExpConstructorTable
, jsCast
<RegExpConstructor
*>(object
), propertyName
, slot
);
158 EncodedJSValue
regExpConstructorDollar1(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
160 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 1));
163 EncodedJSValue
regExpConstructorDollar2(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
165 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 2));
168 EncodedJSValue
regExpConstructorDollar3(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
170 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 3));
173 EncodedJSValue
regExpConstructorDollar4(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
175 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 4));
178 EncodedJSValue
regExpConstructorDollar5(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
180 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 5));
183 EncodedJSValue
regExpConstructorDollar6(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
185 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 6));
188 EncodedJSValue
regExpConstructorDollar7(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
190 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 7));
193 EncodedJSValue
regExpConstructorDollar8(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
195 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 8));
198 EncodedJSValue
regExpConstructorDollar9(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
200 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 9));
203 EncodedJSValue
regExpConstructorInput(ExecState
*, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
205 return JSValue::encode(asRegExpConstructor(slotBase
)->input());
208 EncodedJSValue
regExpConstructorMultiline(ExecState
*, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
210 return JSValue::encode(jsBoolean(asRegExpConstructor(slotBase
)->multiline()));
213 EncodedJSValue
regExpConstructorLastMatch(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
215 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 0));
218 EncodedJSValue
regExpConstructorLastParen(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
220 return JSValue::encode(asRegExpConstructor(slotBase
)->getLastParen(exec
));
223 EncodedJSValue
regExpConstructorLeftContext(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
225 return JSValue::encode(asRegExpConstructor(slotBase
)->getLeftContext(exec
));
228 EncodedJSValue
regExpConstructorRightContext(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
230 return JSValue::encode(asRegExpConstructor(slotBase
)->getRightContext(exec
));
233 void setRegExpConstructorInput(ExecState
* exec
, JSObject
* baseObject
, EncodedJSValue
, EncodedJSValue value
)
235 if (auto constructor
= jsDynamicCast
<RegExpConstructor
*>(baseObject
))
236 constructor
->setInput(exec
, JSValue::decode(value
).toString(exec
));
239 void setRegExpConstructorMultiline(ExecState
* exec
, JSObject
* baseObject
, EncodedJSValue
, EncodedJSValue value
)
241 if (auto constructor
= jsDynamicCast
<RegExpConstructor
*>(baseObject
))
242 constructor
->setMultiline(JSValue::decode(value
).toBoolean(exec
));
246 JSObject
* constructRegExp(ExecState
* exec
, JSGlobalObject
* globalObject
, const ArgList
& args
, bool callAsConstructor
)
248 JSValue arg0
= args
.at(0);
249 JSValue arg1
= args
.at(1);
251 if (arg0
.inherits(RegExpObject::info())) {
252 if (!arg1
.isUndefined())
253 return exec
->vm().throwException(exec
, createTypeError(exec
, ASCIILiteral("Cannot supply flags when constructing one RegExp from another.")));
254 // If called as a function, this just returns the first argument (see 15.10.3.1).
255 if (callAsConstructor
) {
256 RegExp
* regExp
= static_cast<RegExpObject
*>(asObject(arg0
))->regExp();
257 return RegExpObject::create(exec
->vm(), globalObject
->regExpStructure(), regExp
);
259 return asObject(arg0
);
262 String pattern
= arg0
.isUndefined() ? emptyString() : arg0
.toString(exec
)->value(exec
);
263 if (exec
->hadException())
266 RegExpFlags flags
= NoFlags
;
267 if (!arg1
.isUndefined()) {
268 flags
= regExpFlags(arg1
.toString(exec
)->value(exec
));
269 if (exec
->hadException())
271 if (flags
== InvalidFlags
)
272 return exec
->vm().throwException(exec
, createSyntaxError(exec
, ASCIILiteral("Invalid flags supplied to RegExp constructor.")));
276 RegExp
* regExp
= RegExp::create(vm
, pattern
, flags
);
277 if (!regExp
->isValid())
278 return vm
.throwException(exec
, createSyntaxError(exec
, regExp
->errorMessage()));
279 return RegExpObject::create(vm
, globalObject
->regExpStructure(), regExp
);
282 static EncodedJSValue JSC_HOST_CALL
constructWithRegExpConstructor(ExecState
* exec
)
285 return JSValue::encode(constructRegExp(exec
, asInternalFunction(exec
->callee())->globalObject(), args
, true));
288 ConstructType
RegExpConstructor::getConstructData(JSCell
*, ConstructData
& constructData
)
290 constructData
.native
.function
= constructWithRegExpConstructor
;
291 return ConstructTypeHost
;
295 static EncodedJSValue JSC_HOST_CALL
callRegExpConstructor(ExecState
* exec
)
298 return JSValue::encode(constructRegExp(exec
, asInternalFunction(exec
->callee())->globalObject(), args
));
301 CallType
RegExpConstructor::getCallData(JSCell
*, CallData
& callData
)
303 callData
.native
.function
= callRegExpConstructor
;