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