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
, 0, ExecState::regExpConstructorTable
, 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
, Identifier(&vm
, "RegExp").string());
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 COMPILE_ASSERT(StructureFlags
& OverridesVisitChildren
, OverridesVisitChildrenWithoutSettingFlag
);
114 ASSERT(thisObject
->structure()->typeInfo().overridesVisitChildren());
116 Base::visitChildren(thisObject
, visitor
);
117 thisObject
->m_cachedResult
.visitChildren(visitor
);
120 JSValue
RegExpConstructor::getBackref(ExecState
* exec
, unsigned i
)
122 RegExpMatchesArray
* array
= m_cachedResult
.lastResult(exec
, this);
124 if (i
< array
->length()) {
125 JSValue result
= JSValue(array
).get(exec
, i
);
126 ASSERT(result
.isString() || result
.isUndefined());
127 if (!result
.isUndefined())
130 return jsEmptyString(exec
);
133 JSValue
RegExpConstructor::getLastParen(ExecState
* exec
)
135 RegExpMatchesArray
* array
= m_cachedResult
.lastResult(exec
, this);
136 unsigned length
= array
->length();
138 JSValue result
= JSValue(array
).get(exec
, length
- 1);
139 ASSERT(result
.isString() || result
.isUndefined());
140 if (!result
.isUndefined())
143 return jsEmptyString(exec
);
146 JSValue
RegExpConstructor::getLeftContext(ExecState
* exec
)
148 return m_cachedResult
.lastResult(exec
, this)->leftContext(exec
);
151 JSValue
RegExpConstructor::getRightContext(ExecState
* exec
)
153 return m_cachedResult
.lastResult(exec
, this)->rightContext(exec
);
156 bool RegExpConstructor::getOwnPropertySlot(JSObject
* object
, ExecState
* exec
, PropertyName propertyName
, PropertySlot
& slot
)
158 return getStaticValueSlot
<RegExpConstructor
, InternalFunction
>(exec
, ExecState::regExpConstructorTable(exec
->vm()), jsCast
<RegExpConstructor
*>(object
), propertyName
, slot
);
161 EncodedJSValue
regExpConstructorDollar1(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
163 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 1));
166 EncodedJSValue
regExpConstructorDollar2(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
168 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 2));
171 EncodedJSValue
regExpConstructorDollar3(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
173 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 3));
176 EncodedJSValue
regExpConstructorDollar4(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
178 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 4));
181 EncodedJSValue
regExpConstructorDollar5(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
183 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 5));
186 EncodedJSValue
regExpConstructorDollar6(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
188 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 6));
191 EncodedJSValue
regExpConstructorDollar7(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
193 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 7));
196 EncodedJSValue
regExpConstructorDollar8(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
198 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 8));
201 EncodedJSValue
regExpConstructorDollar9(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
203 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 9));
206 EncodedJSValue
regExpConstructorInput(ExecState
*, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
208 return JSValue::encode(asRegExpConstructor(slotBase
)->input());
211 EncodedJSValue
regExpConstructorMultiline(ExecState
*, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
213 return JSValue::encode(jsBoolean(asRegExpConstructor(slotBase
)->multiline()));
216 EncodedJSValue
regExpConstructorLastMatch(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
218 return JSValue::encode(asRegExpConstructor(slotBase
)->getBackref(exec
, 0));
221 EncodedJSValue
regExpConstructorLastParen(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
223 return JSValue::encode(asRegExpConstructor(slotBase
)->getLastParen(exec
));
226 EncodedJSValue
regExpConstructorLeftContext(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
228 return JSValue::encode(asRegExpConstructor(slotBase
)->getLeftContext(exec
));
231 EncodedJSValue
regExpConstructorRightContext(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
233 return JSValue::encode(asRegExpConstructor(slotBase
)->getRightContext(exec
));
236 void setRegExpConstructorInput(ExecState
* exec
, JSObject
* baseObject
, EncodedJSValue
, EncodedJSValue value
)
238 if (auto constructor
= jsDynamicCast
<RegExpConstructor
*>(baseObject
))
239 constructor
->setInput(exec
, JSValue::decode(value
).toString(exec
));
242 void setRegExpConstructorMultiline(ExecState
* exec
, JSObject
* baseObject
, EncodedJSValue
, EncodedJSValue value
)
244 if (auto constructor
= jsDynamicCast
<RegExpConstructor
*>(baseObject
))
245 constructor
->setMultiline(JSValue::decode(value
).toBoolean(exec
));
249 JSObject
* constructRegExp(ExecState
* exec
, JSGlobalObject
* globalObject
, const ArgList
& args
, bool callAsConstructor
)
251 JSValue arg0
= args
.at(0);
252 JSValue arg1
= args
.at(1);
254 if (arg0
.inherits(RegExpObject::info())) {
255 if (!arg1
.isUndefined())
256 return exec
->vm().throwException(exec
, createTypeError(exec
, ASCIILiteral("Cannot supply flags when constructing one RegExp from another.")));
257 // If called as a function, this just returns the first argument (see 15.10.3.1).
258 if (callAsConstructor
) {
259 RegExp
* regExp
= static_cast<RegExpObject
*>(asObject(arg0
))->regExp();
260 return RegExpObject::create(exec
->vm(), globalObject
->regExpStructure(), regExp
);
262 return asObject(arg0
);
265 String pattern
= arg0
.isUndefined() ? emptyString() : arg0
.toString(exec
)->value(exec
);
266 if (exec
->hadException())
269 RegExpFlags flags
= NoFlags
;
270 if (!arg1
.isUndefined()) {
271 flags
= regExpFlags(arg1
.toString(exec
)->value(exec
));
272 if (exec
->hadException())
274 if (flags
== InvalidFlags
)
275 return exec
->vm().throwException(exec
, createSyntaxError(exec
, ASCIILiteral("Invalid flags supplied to RegExp constructor.")));
279 RegExp
* regExp
= RegExp::create(vm
, pattern
, flags
);
280 if (!regExp
->isValid())
281 return vm
.throwException(exec
, createSyntaxError(exec
, regExp
->errorMessage()));
282 return RegExpObject::create(vm
, globalObject
->regExpStructure(), regExp
);
285 static EncodedJSValue JSC_HOST_CALL
constructWithRegExpConstructor(ExecState
* exec
)
288 return JSValue::encode(constructRegExp(exec
, asInternalFunction(exec
->callee())->globalObject(), args
, true));
291 ConstructType
RegExpConstructor::getConstructData(JSCell
*, ConstructData
& constructData
)
293 constructData
.native
.function
= constructWithRegExpConstructor
;
294 return ConstructTypeHost
;
298 static EncodedJSValue JSC_HOST_CALL
callRegExpConstructor(ExecState
* exec
)
301 return JSValue::encode(constructRegExp(exec
, asInternalFunction(exec
->callee())->globalObject(), args
));
304 CallType
RegExpConstructor::getCallData(JSCell
*, CallData
& callData
)
306 callData
.native
.function
= callRegExpConstructor
;