Changeset 34863 in webkit for trunk/JavaScriptCore/kjs
- Timestamp:
- Jun 28, 2008, 5:09:26 PM (17 years ago)
- Location:
- trunk/JavaScriptCore/kjs
- Files:
-
- 6 edited
- 4 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/AllInOneFile.cpp
r34861 r34863 72 72 #include "PropertyNameArray.cpp" 73 73 #include "regexp.cpp" 74 #include "RegExpConstructor.cpp" 74 75 #include "RegExpObject.cpp" 76 #include "RegExpPrototype.cpp" 75 77 #include "ScopeChain.cpp" 76 78 #include "StringConstructor.cpp" -
trunk/JavaScriptCore/kjs/JSGlobalObject.cpp
r34861 r34863 44 44 #include "ObjectConstructor.h" 45 45 #include "ObjectPrototype.h" 46 #include "RegExpObject.h" 46 #include "RegExpConstructor.h" 47 #include "RegExpPrototype.h" 47 48 #include "ScopeChainMark.h" 48 49 #include "StringConstructor.h" -
trunk/JavaScriptCore/kjs/RegExpConstructor.cpp
r34860 r34863 20 20 21 21 #include "config.h" 22 #include "RegExp Object.h"23 #include "RegExp Object.lut.h"22 #include "RegExpConstructor.h" 23 #include "RegExpConstructor.lut.h" 24 24 25 25 #include "ArrayPrototype.h" 26 26 #include "JSArray.h" 27 #include "JSObject.h"28 27 #include "JSString.h" 29 #include "JSValue.h"30 28 #include "ObjectPrototype.h" 31 #include " UnusedParam.h"29 #include "RegExpPrototype.h" 32 30 #include "error_object.h" 33 #include "operations.h"34 31 #include "regexp.h" 35 32 36 #include <stdio.h>37 38 33 namespace KJS { 39 34 40 // ------------------------------ RegExpPrototype ---------------------------41 42 static JSValue* regExpProtoFuncTest(ExecState*, JSObject*, JSValue*, const ArgList&);43 static JSValue* regExpProtoFuncExec(ExecState*, JSObject*, JSValue*, const ArgList&);44 static JSValue* regExpProtoFuncCompile(ExecState*, JSObject*, JSValue*, const ArgList&);45 static JSValue* regExpProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&);46 47 // ECMA 15.10.548 49 const ClassInfo RegExpPrototype::info = { "RegExpPrototype", 0, 0, 0 };50 51 RegExpPrototype::RegExpPrototype(ExecState* exec, ObjectPrototype* objectPrototype, FunctionPrototype* functionPrototype)52 : JSObject(objectPrototype)53 {54 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum);55 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().exec, regExpProtoFuncExec), DontEnum);56 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().test, regExpProtoFuncTest), DontEnum);57 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().toString, regExpProtoFuncToString), DontEnum);58 }59 60 // ------------------------------ Functions ---------------------------61 62 JSValue* regExpProtoFuncTest(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)63 {64 if (!thisValue->isObject(&RegExpObject::info))65 return throwError(exec, TypeError);66 return static_cast<RegExpObject*>(thisValue)->test(exec, args);67 }68 69 JSValue* regExpProtoFuncExec(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)70 {71 if (!thisValue->isObject(&RegExpObject::info))72 return throwError(exec, TypeError);73 return static_cast<RegExpObject*>(thisValue)->exec(exec, args);74 }75 76 JSValue* regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)77 {78 if (!thisValue->isObject(&RegExpObject::info))79 return throwError(exec, TypeError);80 81 RefPtr<RegExp> regExp;82 JSValue* arg0 = args[0];83 JSValue* arg1 = args[1];84 85 if (arg0->isObject(&RegExpObject::info)) {86 if (!arg1->isUndefined())87 return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");88 regExp = static_cast<RegExpObject*>(arg0)->regExp();89 } else {90 UString pattern = args.isEmpty() ? UString("") : arg0->toString(exec);91 UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec);92 regExp = RegExp::create(pattern, flags);93 }94 95 if (!regExp->isValid())96 return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));97 98 static_cast<RegExpObject*>(thisValue)->setRegExp(regExp.release());99 static_cast<RegExpObject*>(thisValue)->setLastIndex(0);100 return jsUndefined();101 }102 103 JSValue* regExpProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)104 {105 if (!thisValue->isObject(&RegExpObject::info)) {106 if (thisValue->isObject(&RegExpPrototype::info))107 return jsString(exec, "//");108 return throwError(exec, TypeError);109 }110 111 UString result = "/" + static_cast<RegExpObject*>(thisValue)->get(exec, exec->propertyNames().source)->toString(exec) + "/";112 if (static_cast<RegExpObject*>(thisValue)->get(exec, exec->propertyNames().global)->toBoolean(exec))113 result += "g";114 if (static_cast<RegExpObject*>(thisValue)->get(exec, exec->propertyNames().ignoreCase)->toBoolean(exec))115 result += "i";116 if (static_cast<RegExpObject*>(thisValue)->get(exec, exec->propertyNames().multiline)->toBoolean(exec))117 result += "m";118 return jsString(exec, result);119 }120 121 // ------------------------------ RegExpObject ------------------------------------122 123 const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable };124 125 /* Source for RegExpObject.lut.h126 @begin regExpTable127 global RegExpObject::Global DontDelete|ReadOnly|DontEnum128 ignoreCase RegExpObject::IgnoreCase DontDelete|ReadOnly|DontEnum129 multiline RegExpObject::Multiline DontDelete|ReadOnly|DontEnum130 source RegExpObject::Source DontDelete|ReadOnly|DontEnum131 lastIndex RegExpObject::LastIndex DontDelete|DontEnum132 @end133 */134 135 RegExpObject::RegExpObject(RegExpPrototype* regexpProto, PassRefPtr<RegExp> regExp)136 : JSObject(regexpProto)137 , m_regExp(regExp)138 , m_lastIndex(0)139 {140 }141 142 RegExpObject::~RegExpObject()143 {144 }145 146 bool RegExpObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)147 {148 return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot);149 }150 151 JSValue* RegExpObject::getValueProperty(ExecState* exec, int token) const152 {153 switch (token) {154 case Global:155 return jsBoolean(m_regExp->global());156 case IgnoreCase:157 return jsBoolean(m_regExp->ignoreCase());158 case Multiline:159 return jsBoolean(m_regExp->multiline());160 case Source:161 return jsString(exec, m_regExp->pattern());162 case LastIndex:163 return jsNumber(exec, m_lastIndex);164 }165 166 ASSERT_NOT_REACHED();167 return 0;168 }169 170 void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value)171 {172 lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), this);173 }174 175 void RegExpObject::putValueProperty(ExecState* exec, int token, JSValue* value)176 {177 UNUSED_PARAM(token);178 ASSERT(token == LastIndex);179 m_lastIndex = value->toInteger(exec);180 }181 182 bool RegExpObject::match(ExecState* exec, const ArgList& args)183 {184 RegExpConstructor* regExpObj = exec->lexicalGlobalObject()->regExpConstructor();185 186 UString input;187 if (!args.isEmpty())188 input = args[0]->toString(exec);189 else {190 input = regExpObj->input();191 if (input.isNull()) {192 throwError(exec, GeneralError, "No input.");193 return false;194 }195 }196 197 bool global = get(exec, exec->propertyNames().global)->toBoolean(exec);198 int lastIndex = 0;199 if (global) {200 if (m_lastIndex < 0 || m_lastIndex > input.size()) {201 m_lastIndex = 0;202 return false;203 }204 lastIndex = static_cast<int>(m_lastIndex);205 }206 207 int foundIndex;208 int foundLength;209 regExpObj->performMatch(m_regExp.get(), input, lastIndex, foundIndex, foundLength);210 211 if (global) {212 lastIndex = foundIndex < 0 ? 0 : foundIndex + foundLength;213 m_lastIndex = lastIndex;214 }215 216 return foundIndex >= 0;217 }218 219 JSValue* RegExpObject::test(ExecState* exec, const ArgList& args)220 {221 return jsBoolean(match(exec, args));222 }223 224 JSValue* RegExpObject::exec(ExecState* exec, const ArgList& args)225 {226 return match(exec, args)227 ? exec->lexicalGlobalObject()->regExpConstructor()->arrayOfMatches(exec)228 : jsNull();229 }230 231 static JSValue* callRegExpObject(ExecState* exec, JSObject* function, JSValue*, const ArgList& args)232 {233 return static_cast<RegExpObject*>(function)->exec(exec, args);234 }235 236 CallType RegExpObject::getCallData(CallData& callData)237 {238 callData.native.function = callRegExpObject;239 return CallTypeNative;240 }241 242 // ------------------------------ RegExpConstructor ------------------------------243 244 35 const ClassInfo RegExpConstructor::info = { "Function", &InternalFunction::info, 0, ExecState::regExpConstructorTable }; 245 36 246 /* Source for RegExp Object.lut.h37 /* Source for RegExpConstructor.lut.h 247 38 @begin regExpConstructorTable 248 39 input RegExpConstructor::Input None … … 522 313 } 523 314 524 } 315 } // namespace KJS -
trunk/JavaScriptCore/kjs/RegExpConstructor.h
r34860 r34863 19 19 */ 20 20 21 #ifndef RegExp Object_h22 #define RegExp Object_h21 #ifndef RegExpConstructor_h 22 #define RegExpConstructor_h 23 23 24 24 #include "JSFunction.h" 25 #include "JSObject.h"26 #include "regexp.h"27 25 28 26 namespace KJS { 29 27 30 28 class FunctionPrototype; 31 class ObjectPrototype; 29 class RegExpPrototype; 30 class RegExp; 32 31 struct RegExpConstructorPrivate; 33 34 class RegExpPrototype : public JSObject {35 public:36 RegExpPrototype(ExecState*, ObjectPrototype*, FunctionPrototype*);37 38 virtual const ClassInfo* classInfo() const { return &info; }39 static const ClassInfo info;40 };41 42 class RegExpObject : public JSObject {43 public:44 enum { Global, IgnoreCase, Multiline, Source, LastIndex };45 46 RegExpObject(RegExpPrototype*, PassRefPtr<RegExp>);47 virtual ~RegExpObject();48 49 void setRegExp(PassRefPtr<RegExp> r) { m_regExp = r; }50 RegExp* regExp() const { return m_regExp.get(); }51 52 JSValue* test(ExecState*, const ArgList&);53 JSValue* exec(ExecState*, const ArgList&);54 55 bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);56 JSValue* getValueProperty(ExecState*, int token) const;57 void put(ExecState*, const Identifier&, JSValue*);58 void putValueProperty(ExecState*, int token, JSValue*);59 60 virtual const ClassInfo* classInfo() const { return &info; }61 static const ClassInfo info;62 63 void setLastIndex(double lastIndex) { m_lastIndex = lastIndex; }64 65 private:66 bool match(ExecState*, const ArgList&);67 68 virtual CallType getCallData(CallData&);69 70 RefPtr<RegExp> m_regExp;71 double m_lastIndex;72 };73 32 74 33 class RegExpConstructor : public InternalFunction { -
trunk/JavaScriptCore/kjs/RegExpObject.cpp
r34857 r34863 23 23 #include "RegExpObject.lut.h" 24 24 25 #include "ArrayPrototype.h"26 25 #include "JSArray.h" 27 #include "JS Object.h"26 #include "JSGlobalObject.h" 28 27 #include "JSString.h" 29 #include "JSValue.h" 30 #include "ObjectPrototype.h" 31 #include "UnusedParam.h" 28 #include "RegExpConstructor.h" 29 #include "RegExpPrototype.h" 32 30 #include "error_object.h" 33 #include "operations.h"34 #include "regexp.h"35 36 #include <stdio.h>37 31 38 32 namespace KJS { 39 40 // ------------------------------ RegExpPrototype ---------------------------41 42 static JSValue* regExpProtoFuncTest(ExecState*, JSObject*, JSValue*, const ArgList&);43 static JSValue* regExpProtoFuncExec(ExecState*, JSObject*, JSValue*, const ArgList&);44 static JSValue* regExpProtoFuncCompile(ExecState*, JSObject*, JSValue*, const ArgList&);45 static JSValue* regExpProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&);46 47 // ECMA 15.10.548 49 const ClassInfo RegExpPrototype::info = { "RegExpPrototype", 0, 0, 0 };50 51 RegExpPrototype::RegExpPrototype(ExecState* exec, ObjectPrototype* objectPrototype, FunctionPrototype* functionPrototype)52 : JSObject(objectPrototype)53 {54 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum);55 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().exec, regExpProtoFuncExec), DontEnum);56 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().test, regExpProtoFuncTest), DontEnum);57 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().toString, regExpProtoFuncToString), DontEnum);58 }59 60 // ------------------------------ Functions ---------------------------61 62 JSValue* regExpProtoFuncTest(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)63 {64 if (!thisValue->isObject(&RegExpObject::info))65 return throwError(exec, TypeError);66 return static_cast<RegExpObject*>(thisValue)->test(exec, args);67 }68 69 JSValue* regExpProtoFuncExec(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)70 {71 if (!thisValue->isObject(&RegExpObject::info))72 return throwError(exec, TypeError);73 return static_cast<RegExpObject*>(thisValue)->exec(exec, args);74 }75 76 JSValue* regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)77 {78 if (!thisValue->isObject(&RegExpObject::info))79 return throwError(exec, TypeError);80 81 RefPtr<RegExp> regExp;82 JSValue* arg0 = args[0];83 JSValue* arg1 = args[1];84 85 if (arg0->isObject(&RegExpObject::info)) {86 if (!arg1->isUndefined())87 return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");88 regExp = static_cast<RegExpObject*>(arg0)->regExp();89 } else {90 UString pattern = args.isEmpty() ? UString("") : arg0->toString(exec);91 UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec);92 regExp = RegExp::create(pattern, flags);93 }94 95 if (!regExp->isValid())96 return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));97 98 static_cast<RegExpObject*>(thisValue)->setRegExp(regExp.release());99 static_cast<RegExpObject*>(thisValue)->setLastIndex(0);100 return jsUndefined();101 }102 103 JSValue* regExpProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)104 {105 if (!thisValue->isObject(&RegExpObject::info)) {106 if (thisValue->isObject(&RegExpPrototype::info))107 return jsString(exec, "//");108 return throwError(exec, TypeError);109 }110 111 UString result = "/" + static_cast<RegExpObject*>(thisValue)->get(exec, exec->propertyNames().source)->toString(exec) + "/";112 if (static_cast<RegExpObject*>(thisValue)->get(exec, exec->propertyNames().global)->toBoolean(exec))113 result += "g";114 if (static_cast<RegExpObject*>(thisValue)->get(exec, exec->propertyNames().ignoreCase)->toBoolean(exec))115 result += "i";116 if (static_cast<RegExpObject*>(thisValue)->get(exec, exec->propertyNames().multiline)->toBoolean(exec))117 result += "m";118 return jsString(exec, result);119 }120 121 // ------------------------------ RegExpObject ------------------------------------122 33 123 34 const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable }; … … 240 151 } 241 152 242 // ------------------------------ RegExpConstructor ------------------------------ 243 244 const ClassInfo RegExpConstructor::info = { "Function", &InternalFunction::info, 0, ExecState::regExpConstructorTable }; 245 246 /* Source for RegExpObject.lut.h 247 @begin regExpConstructorTable 248 input RegExpConstructor::Input None 249 $_ RegExpConstructor::Input DontEnum 250 multiline RegExpConstructor::Multiline None 251 $* RegExpConstructor::Multiline DontEnum 252 lastMatch RegExpConstructor::LastMatch DontDelete|ReadOnly 253 $& RegExpConstructor::LastMatch DontDelete|ReadOnly|DontEnum 254 lastParen RegExpConstructor::LastParen DontDelete|ReadOnly 255 $+ RegExpConstructor::LastParen DontDelete|ReadOnly|DontEnum 256 leftContext RegExpConstructor::LeftContext DontDelete|ReadOnly 257 $` RegExpConstructor::LeftContext DontDelete|ReadOnly|DontEnum 258 rightContext RegExpConstructor::RightContext DontDelete|ReadOnly 259 $' RegExpConstructor::RightContext DontDelete|ReadOnly|DontEnum 260 $1 RegExpConstructor::Dollar1 DontDelete|ReadOnly 261 $2 RegExpConstructor::Dollar2 DontDelete|ReadOnly 262 $3 RegExpConstructor::Dollar3 DontDelete|ReadOnly 263 $4 RegExpConstructor::Dollar4 DontDelete|ReadOnly 264 $5 RegExpConstructor::Dollar5 DontDelete|ReadOnly 265 $6 RegExpConstructor::Dollar6 DontDelete|ReadOnly 266 $7 RegExpConstructor::Dollar7 DontDelete|ReadOnly 267 $8 RegExpConstructor::Dollar8 DontDelete|ReadOnly 268 $9 RegExpConstructor::Dollar9 DontDelete|ReadOnly 269 @end 270 */ 271 272 struct RegExpConstructorPrivate { 273 // Global search cache / settings 274 RegExpConstructorPrivate() : lastNumSubPatterns(0), multiline(false) { } 275 UString lastInput; 276 OwnArrayPtr<int> lastOvector; 277 unsigned lastNumSubPatterns : 31; 278 bool multiline : 1; 279 }; 280 281 RegExpConstructor::RegExpConstructor(ExecState* exec, FunctionPrototype* funcProto, RegExpPrototype* regProto) 282 : InternalFunction(funcProto, Identifier(exec, "RegExp")) 283 , d(new RegExpConstructorPrivate) 284 { 285 // ECMA 15.10.5.1 RegExp.prototype 286 putDirect(exec->propertyNames().prototype, regProto, DontEnum | DontDelete | ReadOnly); 287 288 // no. of arguments for constructor 289 putDirect(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly | DontDelete | DontEnum); 290 } 291 292 /* 293 To facilitate result caching, exec(), test(), match(), search(), and replace() dipatch regular 294 expression matching through the performMatch function. We use cached results to calculate, 295 e.g., RegExp.lastMatch and RegExp.leftParen. 296 */ 297 void RegExpConstructor::performMatch(RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector) 298 { 299 OwnArrayPtr<int> tmpOvector; 300 position = r->match(s, startOffset, &tmpOvector); 301 302 if (ovector) 303 *ovector = tmpOvector.get(); 304 305 if (position != -1) { 306 ASSERT(tmpOvector); 307 308 length = tmpOvector[1] - tmpOvector[0]; 309 310 d->lastInput = s; 311 d->lastOvector.set(tmpOvector.release()); 312 d->lastNumSubPatterns = r->numSubpatterns(); 313 } 314 } 315 316 class RegExpMatchesArray : public JSArray { 317 public: 318 RegExpMatchesArray(ExecState*, RegExpConstructorPrivate*); 319 virtual ~RegExpMatchesArray(); 320 321 private: 322 virtual bool getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { if (lazyCreationData()) fillArrayInstance(exec); return JSArray::getOwnPropertySlot(exec, propertyName, slot); } 323 virtual bool getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) { if (lazyCreationData()) fillArrayInstance(exec); return JSArray::getOwnPropertySlot(exec, propertyName, slot); } 324 virtual void put(ExecState* exec, const Identifier& propertyName, JSValue* v) { if (lazyCreationData()) fillArrayInstance(exec); JSArray::put(exec, propertyName, v); } 325 virtual void put(ExecState* exec, unsigned propertyName, JSValue* v) { if (lazyCreationData()) fillArrayInstance(exec); JSArray::put(exec, propertyName, v); } 326 virtual bool deleteProperty(ExecState* exec, const Identifier& propertyName) { if (lazyCreationData()) fillArrayInstance(exec); return JSArray::deleteProperty(exec, propertyName); } 327 virtual bool deleteProperty(ExecState* exec, unsigned propertyName) { if (lazyCreationData()) fillArrayInstance(exec); return JSArray::deleteProperty(exec, propertyName); } 328 virtual void getPropertyNames(ExecState* exec, PropertyNameArray& arr) { if (lazyCreationData()) fillArrayInstance(exec); JSArray::getPropertyNames(exec, arr); } 329 330 void fillArrayInstance(ExecState*); 331 }; 332 333 RegExpMatchesArray::RegExpMatchesArray(ExecState* exec, RegExpConstructorPrivate* data) 334 : JSArray(exec->lexicalGlobalObject()->arrayPrototype(), data->lastNumSubPatterns + 1) 335 { 336 RegExpConstructorPrivate* d = new RegExpConstructorPrivate; 337 d->lastInput = data->lastInput; 338 d->lastNumSubPatterns = data->lastNumSubPatterns; 339 unsigned offsetVectorSize = (data->lastNumSubPatterns + 1) * 2; // only copying the result part of the vector 340 d->lastOvector.set(new int[offsetVectorSize]); 341 memcpy(d->lastOvector.get(), data->lastOvector.get(), offsetVectorSize * sizeof(int)); 342 // d->multiline is not needed, and remains uninitialized 343 344 setLazyCreationData(d); 345 } 346 347 RegExpMatchesArray::~RegExpMatchesArray() 348 { 349 delete static_cast<RegExpConstructorPrivate*>(lazyCreationData()); 350 } 351 352 void RegExpMatchesArray::fillArrayInstance(ExecState* exec) 353 { 354 RegExpConstructorPrivate* d = static_cast<RegExpConstructorPrivate*>(lazyCreationData()); 355 ASSERT(d); 356 357 unsigned lastNumSubpatterns = d->lastNumSubPatterns; 358 359 for (unsigned i = 0; i <= lastNumSubpatterns; ++i) { 360 int start = d->lastOvector[2 * i]; 361 if (start >= 0) 362 JSArray::put(exec, i, jsString(exec, d->lastInput.substr(start, d->lastOvector[2 * i + 1] - start))); 363 } 364 JSArray::put(exec, exec->propertyNames().index, jsNumber(exec, d->lastOvector[0])); 365 JSArray::put(exec, exec->propertyNames().input, jsString(exec, d->lastInput)); 366 367 delete d; 368 setLazyCreationData(0); 369 } 370 371 JSObject* RegExpConstructor::arrayOfMatches(ExecState* exec) const 372 { 373 return new (exec) RegExpMatchesArray(exec, d.get()); 374 } 375 376 JSValue* RegExpConstructor::getBackref(ExecState* exec, unsigned i) const 377 { 378 if (d->lastOvector && i <= d->lastNumSubPatterns) 379 return jsString(exec, d->lastInput.substr(d->lastOvector[2 * i], d->lastOvector[2 * i + 1] - d->lastOvector[2 * i])); 380 return jsString(exec, ""); 381 } 382 383 JSValue* RegExpConstructor::getLastParen(ExecState* exec) const 384 { 385 unsigned i = d->lastNumSubPatterns; 386 if (i > 0) { 387 ASSERT(d->lastOvector); 388 return jsString(exec, d->lastInput.substr(d->lastOvector[2 * i], d->lastOvector[2 * i + 1] - d->lastOvector[2 * i])); 389 } 390 return jsString(exec, ""); 391 } 392 393 JSValue* RegExpConstructor::getLeftContext(ExecState* exec) const 394 { 395 if (d->lastOvector) 396 return jsString(exec, d->lastInput.substr(0, d->lastOvector[0])); 397 return jsString(exec, ""); 398 } 399 400 JSValue* RegExpConstructor::getRightContext(ExecState* exec) const 401 { 402 if (d->lastOvector) { 403 UString s = d->lastInput; 404 return jsString(exec, s.substr(d->lastOvector[1], s.size() - d->lastOvector[1])); 405 } 406 return jsString(exec, ""); 407 } 408 409 bool RegExpConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) 410 { 411 return getStaticValueSlot<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), this, propertyName, slot); 412 } 413 414 JSValue *RegExpConstructor::getValueProperty(ExecState* exec, int token) const 415 { 416 switch (token) { 417 case Dollar1: 418 return getBackref(exec, 1); 419 case Dollar2: 420 return getBackref(exec, 2); 421 case Dollar3: 422 return getBackref(exec, 3); 423 case Dollar4: 424 return getBackref(exec, 4); 425 case Dollar5: 426 return getBackref(exec, 5); 427 case Dollar6: 428 return getBackref(exec, 6); 429 case Dollar7: 430 return getBackref(exec, 7); 431 case Dollar8: 432 return getBackref(exec, 8); 433 case Dollar9: 434 return getBackref(exec, 9); 435 case Input: 436 return jsString(exec, d->lastInput); 437 case Multiline: 438 return jsBoolean(d->multiline); 439 case LastMatch: 440 return getBackref(exec, 0); 441 case LastParen: 442 return getLastParen(exec); 443 case LeftContext: 444 return getLeftContext(exec); 445 case RightContext: 446 return getRightContext(exec); 447 default: 448 ASSERT_NOT_REACHED(); 449 } 450 451 return jsString(exec, ""); 452 } 453 454 void RegExpConstructor::put(ExecState *exec, const Identifier &propertyName, JSValue *value) 455 { 456 lookupPut<RegExpConstructor, InternalFunction>(exec, propertyName, value, ExecState::regExpConstructorTable(exec), this); 457 } 458 459 void RegExpConstructor::putValueProperty(ExecState *exec, int token, JSValue *value) 460 { 461 switch (token) { 462 case Input: 463 d->lastInput = value->toString(exec); 464 break; 465 case Multiline: 466 d->multiline = value->toBoolean(exec); 467 break; 468 default: 469 ASSERT(0); 470 } 471 } 472 473 // ECMA 15.10.4 474 static JSObject* constructRegExp(ExecState* exec, const ArgList& args) 475 { 476 JSValue* arg0 = args[0]; 477 JSValue* arg1 = args[1]; 478 479 if (arg0->isObject(&RegExpObject::info)) { 480 if (!arg1->isUndefined()) 481 return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another."); 482 return static_cast<JSObject*>(arg0); 483 } 484 485 UString pattern = arg0->isUndefined() ? UString("") : arg0->toString(exec); 486 UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec); 487 488 RefPtr<RegExp> regExp = RegExp::create(pattern, flags); 489 return regExp->isValid() 490 ? new (exec) RegExpObject(exec->lexicalGlobalObject()->regExpPrototype(), regExp.release()) 491 : throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage())); 492 } 493 494 static JSObject* constructWithRegExpConstructor(ExecState* exec, JSObject*, const ArgList& args) 495 { 496 return constructRegExp(exec, args); 497 } 498 499 ConstructType RegExpConstructor::getConstructData(ConstructData& constructData) 500 { 501 constructData.native.function = constructWithRegExpConstructor; 502 return ConstructTypeNative; 503 } 504 505 // ECMA 15.10.3 506 static JSValue* callRegExpConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args) 507 { 508 return constructRegExp(exec, args); 509 } 510 511 CallType RegExpConstructor::getCallData(CallData& callData) 512 { 513 callData.native.function = callRegExpConstructor; 514 return CallTypeNative; 515 } 516 517 const UString& RegExpConstructor::input() const 518 { 519 // Can detect a distinct initial state that is invisible to JavaScript, by checking for null 520 // state (since jsString turns null strings to empty strings). 521 return d->lastInput; 522 } 523 524 } 153 } // namespace KJS -
trunk/JavaScriptCore/kjs/RegExpObject.h
r34855 r34863 22 22 #define RegExpObject_h 23 23 24 #include "JSFunction.h"25 24 #include "JSObject.h" 26 25 #include "regexp.h" 27 26 28 27 namespace KJS { 29 30 class FunctionPrototype;31 class ObjectPrototype;32 struct RegExpConstructorPrivate;33 34 class RegExpPrototype : public JSObject {35 public:36 RegExpPrototype(ExecState*, ObjectPrototype*, FunctionPrototype*);37 38 virtual const ClassInfo* classInfo() const { return &info; }39 static const ClassInfo info;40 };41 28 42 29 class RegExpObject : public JSObject { … … 72 59 }; 73 60 74 class RegExpConstructor : public InternalFunction { 75 public: 76 enum { Dollar1, Dollar2, Dollar3, Dollar4, Dollar5, Dollar6, Dollar7, Dollar8, Dollar9, 77 Input, Multiline, LastMatch, LastParen, LeftContext, RightContext }; 61 } // namespace KJS 78 62 79 RegExpConstructor(ExecState*, FunctionPrototype*, RegExpPrototype*); 80 81 virtual void put(ExecState*, const Identifier&, JSValue*); 82 void putValueProperty(ExecState*, int token, JSValue*); 83 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); 84 JSValue* getValueProperty(ExecState*, int token) const; 85 86 static const ClassInfo info; 87 88 void performMatch(RegExp*, const UString&, int startOffset, int& position, int& length, int** ovector = 0); 89 JSObject* arrayOfMatches(ExecState*) const; 90 const UString& input() const; 91 92 private: 93 virtual ConstructType getConstructData(ConstructData&); 94 virtual CallType getCallData(CallData&); 95 virtual const ClassInfo* classInfo() const { return &info; } 96 97 JSValue* getBackref(ExecState*, unsigned) const; 98 JSValue* getLastParen(ExecState*) const; 99 JSValue* getLeftContext(ExecState*) const; 100 JSValue* getRightContext(ExecState*) const; 101 102 OwnPtr<RegExpConstructorPrivate> d; 103 }; 104 105 } // namespace 106 107 #endif 63 #endif // RegExpObject_h -
trunk/JavaScriptCore/kjs/RegExpPrototype.cpp
r34860 r34863 20 20 21 21 #include "config.h" 22 #include "RegExpObject.h" 23 #include "RegExpObject.lut.h" 22 #include "RegExpPrototype.h" 24 23 25 24 #include "ArrayPrototype.h" 25 #include "FunctionPrototype.h" 26 26 #include "JSArray.h" 27 27 #include "JSObject.h" … … 29 29 #include "JSValue.h" 30 30 #include "ObjectPrototype.h" 31 #include "RegExpObject.h" 31 32 #include "UnusedParam.h" 32 33 #include "error_object.h" … … 34 35 #include "regexp.h" 35 36 36 #include <stdio.h>37 38 37 namespace KJS { 39 40 // ------------------------------ RegExpPrototype ---------------------------41 38 42 39 static JSValue* regExpProtoFuncTest(ExecState*, JSObject*, JSValue*, const ArgList&); … … 119 116 } 120 117 121 // ------------------------------ RegExpObject ------------------------------------ 122 123 const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable }; 124 125 /* Source for RegExpObject.lut.h 126 @begin regExpTable 127 global RegExpObject::Global DontDelete|ReadOnly|DontEnum 128 ignoreCase RegExpObject::IgnoreCase DontDelete|ReadOnly|DontEnum 129 multiline RegExpObject::Multiline DontDelete|ReadOnly|DontEnum 130 source RegExpObject::Source DontDelete|ReadOnly|DontEnum 131 lastIndex RegExpObject::LastIndex DontDelete|DontEnum 132 @end 133 */ 134 135 RegExpObject::RegExpObject(RegExpPrototype* regexpProto, PassRefPtr<RegExp> regExp) 136 : JSObject(regexpProto) 137 , m_regExp(regExp) 138 , m_lastIndex(0) 139 { 140 } 141 142 RegExpObject::~RegExpObject() 143 { 144 } 145 146 bool RegExpObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) 147 { 148 return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot); 149 } 150 151 JSValue* RegExpObject::getValueProperty(ExecState* exec, int token) const 152 { 153 switch (token) { 154 case Global: 155 return jsBoolean(m_regExp->global()); 156 case IgnoreCase: 157 return jsBoolean(m_regExp->ignoreCase()); 158 case Multiline: 159 return jsBoolean(m_regExp->multiline()); 160 case Source: 161 return jsString(exec, m_regExp->pattern()); 162 case LastIndex: 163 return jsNumber(exec, m_lastIndex); 164 } 165 166 ASSERT_NOT_REACHED(); 167 return 0; 168 } 169 170 void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value) 171 { 172 lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), this); 173 } 174 175 void RegExpObject::putValueProperty(ExecState* exec, int token, JSValue* value) 176 { 177 UNUSED_PARAM(token); 178 ASSERT(token == LastIndex); 179 m_lastIndex = value->toInteger(exec); 180 } 181 182 bool RegExpObject::match(ExecState* exec, const ArgList& args) 183 { 184 RegExpConstructor* regExpObj = exec->lexicalGlobalObject()->regExpConstructor(); 185 186 UString input; 187 if (!args.isEmpty()) 188 input = args[0]->toString(exec); 189 else { 190 input = regExpObj->input(); 191 if (input.isNull()) { 192 throwError(exec, GeneralError, "No input."); 193 return false; 194 } 195 } 196 197 bool global = get(exec, exec->propertyNames().global)->toBoolean(exec); 198 int lastIndex = 0; 199 if (global) { 200 if (m_lastIndex < 0 || m_lastIndex > input.size()) { 201 m_lastIndex = 0; 202 return false; 203 } 204 lastIndex = static_cast<int>(m_lastIndex); 205 } 206 207 int foundIndex; 208 int foundLength; 209 regExpObj->performMatch(m_regExp.get(), input, lastIndex, foundIndex, foundLength); 210 211 if (global) { 212 lastIndex = foundIndex < 0 ? 0 : foundIndex + foundLength; 213 m_lastIndex = lastIndex; 214 } 215 216 return foundIndex >= 0; 217 } 218 219 JSValue* RegExpObject::test(ExecState* exec, const ArgList& args) 220 { 221 return jsBoolean(match(exec, args)); 222 } 223 224 JSValue* RegExpObject::exec(ExecState* exec, const ArgList& args) 225 { 226 return match(exec, args) 227 ? exec->lexicalGlobalObject()->regExpConstructor()->arrayOfMatches(exec) 228 : jsNull(); 229 } 230 231 static JSValue* callRegExpObject(ExecState* exec, JSObject* function, JSValue*, const ArgList& args) 232 { 233 return static_cast<RegExpObject*>(function)->exec(exec, args); 234 } 235 236 CallType RegExpObject::getCallData(CallData& callData) 237 { 238 callData.native.function = callRegExpObject; 239 return CallTypeNative; 240 } 241 242 // ------------------------------ RegExpConstructor ------------------------------ 243 244 const ClassInfo RegExpConstructor::info = { "Function", &InternalFunction::info, 0, ExecState::regExpConstructorTable }; 245 246 /* Source for RegExpObject.lut.h 247 @begin regExpConstructorTable 248 input RegExpConstructor::Input None 249 $_ RegExpConstructor::Input DontEnum 250 multiline RegExpConstructor::Multiline None 251 $* RegExpConstructor::Multiline DontEnum 252 lastMatch RegExpConstructor::LastMatch DontDelete|ReadOnly 253 $& RegExpConstructor::LastMatch DontDelete|ReadOnly|DontEnum 254 lastParen RegExpConstructor::LastParen DontDelete|ReadOnly 255 $+ RegExpConstructor::LastParen DontDelete|ReadOnly|DontEnum 256 leftContext RegExpConstructor::LeftContext DontDelete|ReadOnly 257 $` RegExpConstructor::LeftContext DontDelete|ReadOnly|DontEnum 258 rightContext RegExpConstructor::RightContext DontDelete|ReadOnly 259 $' RegExpConstructor::RightContext DontDelete|ReadOnly|DontEnum 260 $1 RegExpConstructor::Dollar1 DontDelete|ReadOnly 261 $2 RegExpConstructor::Dollar2 DontDelete|ReadOnly 262 $3 RegExpConstructor::Dollar3 DontDelete|ReadOnly 263 $4 RegExpConstructor::Dollar4 DontDelete|ReadOnly 264 $5 RegExpConstructor::Dollar5 DontDelete|ReadOnly 265 $6 RegExpConstructor::Dollar6 DontDelete|ReadOnly 266 $7 RegExpConstructor::Dollar7 DontDelete|ReadOnly 267 $8 RegExpConstructor::Dollar8 DontDelete|ReadOnly 268 $9 RegExpConstructor::Dollar9 DontDelete|ReadOnly 269 @end 270 */ 271 272 struct RegExpConstructorPrivate { 273 // Global search cache / settings 274 RegExpConstructorPrivate() : lastNumSubPatterns(0), multiline(false) { } 275 UString lastInput; 276 OwnArrayPtr<int> lastOvector; 277 unsigned lastNumSubPatterns : 31; 278 bool multiline : 1; 279 }; 280 281 RegExpConstructor::RegExpConstructor(ExecState* exec, FunctionPrototype* funcProto, RegExpPrototype* regProto) 282 : InternalFunction(funcProto, Identifier(exec, "RegExp")) 283 , d(new RegExpConstructorPrivate) 284 { 285 // ECMA 15.10.5.1 RegExp.prototype 286 putDirect(exec->propertyNames().prototype, regProto, DontEnum | DontDelete | ReadOnly); 287 288 // no. of arguments for constructor 289 putDirect(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly | DontDelete | DontEnum); 290 } 291 292 /* 293 To facilitate result caching, exec(), test(), match(), search(), and replace() dipatch regular 294 expression matching through the performMatch function. We use cached results to calculate, 295 e.g., RegExp.lastMatch and RegExp.leftParen. 296 */ 297 void RegExpConstructor::performMatch(RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector) 298 { 299 OwnArrayPtr<int> tmpOvector; 300 position = r->match(s, startOffset, &tmpOvector); 301 302 if (ovector) 303 *ovector = tmpOvector.get(); 304 305 if (position != -1) { 306 ASSERT(tmpOvector); 307 308 length = tmpOvector[1] - tmpOvector[0]; 309 310 d->lastInput = s; 311 d->lastOvector.set(tmpOvector.release()); 312 d->lastNumSubPatterns = r->numSubpatterns(); 313 } 314 } 315 316 class RegExpMatchesArray : public JSArray { 317 public: 318 RegExpMatchesArray(ExecState*, RegExpConstructorPrivate*); 319 virtual ~RegExpMatchesArray(); 320 321 private: 322 virtual bool getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { if (lazyCreationData()) fillArrayInstance(exec); return JSArray::getOwnPropertySlot(exec, propertyName, slot); } 323 virtual bool getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) { if (lazyCreationData()) fillArrayInstance(exec); return JSArray::getOwnPropertySlot(exec, propertyName, slot); } 324 virtual void put(ExecState* exec, const Identifier& propertyName, JSValue* v) { if (lazyCreationData()) fillArrayInstance(exec); JSArray::put(exec, propertyName, v); } 325 virtual void put(ExecState* exec, unsigned propertyName, JSValue* v) { if (lazyCreationData()) fillArrayInstance(exec); JSArray::put(exec, propertyName, v); } 326 virtual bool deleteProperty(ExecState* exec, const Identifier& propertyName) { if (lazyCreationData()) fillArrayInstance(exec); return JSArray::deleteProperty(exec, propertyName); } 327 virtual bool deleteProperty(ExecState* exec, unsigned propertyName) { if (lazyCreationData()) fillArrayInstance(exec); return JSArray::deleteProperty(exec, propertyName); } 328 virtual void getPropertyNames(ExecState* exec, PropertyNameArray& arr) { if (lazyCreationData()) fillArrayInstance(exec); JSArray::getPropertyNames(exec, arr); } 329 330 void fillArrayInstance(ExecState*); 331 }; 332 333 RegExpMatchesArray::RegExpMatchesArray(ExecState* exec, RegExpConstructorPrivate* data) 334 : JSArray(exec->lexicalGlobalObject()->arrayPrototype(), data->lastNumSubPatterns + 1) 335 { 336 RegExpConstructorPrivate* d = new RegExpConstructorPrivate; 337 d->lastInput = data->lastInput; 338 d->lastNumSubPatterns = data->lastNumSubPatterns; 339 unsigned offsetVectorSize = (data->lastNumSubPatterns + 1) * 2; // only copying the result part of the vector 340 d->lastOvector.set(new int[offsetVectorSize]); 341 memcpy(d->lastOvector.get(), data->lastOvector.get(), offsetVectorSize * sizeof(int)); 342 // d->multiline is not needed, and remains uninitialized 343 344 setLazyCreationData(d); 345 } 346 347 RegExpMatchesArray::~RegExpMatchesArray() 348 { 349 delete static_cast<RegExpConstructorPrivate*>(lazyCreationData()); 350 } 351 352 void RegExpMatchesArray::fillArrayInstance(ExecState* exec) 353 { 354 RegExpConstructorPrivate* d = static_cast<RegExpConstructorPrivate*>(lazyCreationData()); 355 ASSERT(d); 356 357 unsigned lastNumSubpatterns = d->lastNumSubPatterns; 358 359 for (unsigned i = 0; i <= lastNumSubpatterns; ++i) { 360 int start = d->lastOvector[2 * i]; 361 if (start >= 0) 362 JSArray::put(exec, i, jsString(exec, d->lastInput.substr(start, d->lastOvector[2 * i + 1] - start))); 363 } 364 JSArray::put(exec, exec->propertyNames().index, jsNumber(exec, d->lastOvector[0])); 365 JSArray::put(exec, exec->propertyNames().input, jsString(exec, d->lastInput)); 366 367 delete d; 368 setLazyCreationData(0); 369 } 370 371 JSObject* RegExpConstructor::arrayOfMatches(ExecState* exec) const 372 { 373 return new (exec) RegExpMatchesArray(exec, d.get()); 374 } 375 376 JSValue* RegExpConstructor::getBackref(ExecState* exec, unsigned i) const 377 { 378 if (d->lastOvector && i <= d->lastNumSubPatterns) 379 return jsString(exec, d->lastInput.substr(d->lastOvector[2 * i], d->lastOvector[2 * i + 1] - d->lastOvector[2 * i])); 380 return jsString(exec, ""); 381 } 382 383 JSValue* RegExpConstructor::getLastParen(ExecState* exec) const 384 { 385 unsigned i = d->lastNumSubPatterns; 386 if (i > 0) { 387 ASSERT(d->lastOvector); 388 return jsString(exec, d->lastInput.substr(d->lastOvector[2 * i], d->lastOvector[2 * i + 1] - d->lastOvector[2 * i])); 389 } 390 return jsString(exec, ""); 391 } 392 393 JSValue* RegExpConstructor::getLeftContext(ExecState* exec) const 394 { 395 if (d->lastOvector) 396 return jsString(exec, d->lastInput.substr(0, d->lastOvector[0])); 397 return jsString(exec, ""); 398 } 399 400 JSValue* RegExpConstructor::getRightContext(ExecState* exec) const 401 { 402 if (d->lastOvector) { 403 UString s = d->lastInput; 404 return jsString(exec, s.substr(d->lastOvector[1], s.size() - d->lastOvector[1])); 405 } 406 return jsString(exec, ""); 407 } 408 409 bool RegExpConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) 410 { 411 return getStaticValueSlot<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), this, propertyName, slot); 412 } 413 414 JSValue *RegExpConstructor::getValueProperty(ExecState* exec, int token) const 415 { 416 switch (token) { 417 case Dollar1: 418 return getBackref(exec, 1); 419 case Dollar2: 420 return getBackref(exec, 2); 421 case Dollar3: 422 return getBackref(exec, 3); 423 case Dollar4: 424 return getBackref(exec, 4); 425 case Dollar5: 426 return getBackref(exec, 5); 427 case Dollar6: 428 return getBackref(exec, 6); 429 case Dollar7: 430 return getBackref(exec, 7); 431 case Dollar8: 432 return getBackref(exec, 8); 433 case Dollar9: 434 return getBackref(exec, 9); 435 case Input: 436 return jsString(exec, d->lastInput); 437 case Multiline: 438 return jsBoolean(d->multiline); 439 case LastMatch: 440 return getBackref(exec, 0); 441 case LastParen: 442 return getLastParen(exec); 443 case LeftContext: 444 return getLeftContext(exec); 445 case RightContext: 446 return getRightContext(exec); 447 default: 448 ASSERT_NOT_REACHED(); 449 } 450 451 return jsString(exec, ""); 452 } 453 454 void RegExpConstructor::put(ExecState *exec, const Identifier &propertyName, JSValue *value) 455 { 456 lookupPut<RegExpConstructor, InternalFunction>(exec, propertyName, value, ExecState::regExpConstructorTable(exec), this); 457 } 458 459 void RegExpConstructor::putValueProperty(ExecState *exec, int token, JSValue *value) 460 { 461 switch (token) { 462 case Input: 463 d->lastInput = value->toString(exec); 464 break; 465 case Multiline: 466 d->multiline = value->toBoolean(exec); 467 break; 468 default: 469 ASSERT(0); 470 } 471 } 472 473 // ECMA 15.10.4 474 static JSObject* constructRegExp(ExecState* exec, const ArgList& args) 475 { 476 JSValue* arg0 = args[0]; 477 JSValue* arg1 = args[1]; 478 479 if (arg0->isObject(&RegExpObject::info)) { 480 if (!arg1->isUndefined()) 481 return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another."); 482 return static_cast<JSObject*>(arg0); 483 } 484 485 UString pattern = arg0->isUndefined() ? UString("") : arg0->toString(exec); 486 UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec); 487 488 RefPtr<RegExp> regExp = RegExp::create(pattern, flags); 489 return regExp->isValid() 490 ? new (exec) RegExpObject(exec->lexicalGlobalObject()->regExpPrototype(), regExp.release()) 491 : throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage())); 492 } 493 494 static JSObject* constructWithRegExpConstructor(ExecState* exec, JSObject*, const ArgList& args) 495 { 496 return constructRegExp(exec, args); 497 } 498 499 ConstructType RegExpConstructor::getConstructData(ConstructData& constructData) 500 { 501 constructData.native.function = constructWithRegExpConstructor; 502 return ConstructTypeNative; 503 } 504 505 // ECMA 15.10.3 506 static JSValue* callRegExpConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args) 507 { 508 return constructRegExp(exec, args); 509 } 510 511 CallType RegExpConstructor::getCallData(CallData& callData) 512 { 513 callData.native.function = callRegExpConstructor; 514 return CallTypeNative; 515 } 516 517 const UString& RegExpConstructor::input() const 518 { 519 // Can detect a distinct initial state that is invisible to JavaScript, by checking for null 520 // state (since jsString turns null strings to empty strings). 521 return d->lastInput; 522 } 523 524 } 118 } // namespace KJS -
trunk/JavaScriptCore/kjs/RegExpPrototype.h
r34860 r34863 19 19 */ 20 20 21 #ifndef RegExp Object_h22 #define RegExp Object_h21 #ifndef RegExpPrototype_h 22 #define RegExpPrototype_h 23 23 24 #include "JSFunction.h"25 24 #include "JSObject.h" 26 #include "regexp.h"27 25 28 26 namespace KJS { … … 30 28 class FunctionPrototype; 31 29 class ObjectPrototype; 32 struct RegExpConstructorPrivate;33 30 34 31 class RegExpPrototype : public JSObject { … … 40 37 }; 41 38 42 class RegExpObject : public JSObject { 43 public: 44 enum { Global, IgnoreCase, Multiline, Source, LastIndex }; 39 } // namespace KJS 45 40 46 RegExpObject(RegExpPrototype*, PassRefPtr<RegExp>); 47 virtual ~RegExpObject(); 48 49 void setRegExp(PassRefPtr<RegExp> r) { m_regExp = r; } 50 RegExp* regExp() const { return m_regExp.get(); } 51 52 JSValue* test(ExecState*, const ArgList&); 53 JSValue* exec(ExecState*, const ArgList&); 54 55 bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); 56 JSValue* getValueProperty(ExecState*, int token) const; 57 void put(ExecState*, const Identifier&, JSValue*); 58 void putValueProperty(ExecState*, int token, JSValue*); 59 60 virtual const ClassInfo* classInfo() const { return &info; } 61 static const ClassInfo info; 62 63 void setLastIndex(double lastIndex) { m_lastIndex = lastIndex; } 64 65 private: 66 bool match(ExecState*, const ArgList&); 67 68 virtual CallType getCallData(CallData&); 69 70 RefPtr<RegExp> m_regExp; 71 double m_lastIndex; 72 }; 73 74 class RegExpConstructor : public InternalFunction { 75 public: 76 enum { Dollar1, Dollar2, Dollar3, Dollar4, Dollar5, Dollar6, Dollar7, Dollar8, Dollar9, 77 Input, Multiline, LastMatch, LastParen, LeftContext, RightContext }; 78 79 RegExpConstructor(ExecState*, FunctionPrototype*, RegExpPrototype*); 80 81 virtual void put(ExecState*, const Identifier&, JSValue*); 82 void putValueProperty(ExecState*, int token, JSValue*); 83 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); 84 JSValue* getValueProperty(ExecState*, int token) const; 85 86 static const ClassInfo info; 87 88 void performMatch(RegExp*, const UString&, int startOffset, int& position, int& length, int** ovector = 0); 89 JSObject* arrayOfMatches(ExecState*) const; 90 const UString& input() const; 91 92 private: 93 virtual ConstructType getConstructData(ConstructData&); 94 virtual CallType getCallData(CallData&); 95 virtual const ClassInfo* classInfo() const { return &info; } 96 97 JSValue* getBackref(ExecState*, unsigned) const; 98 JSValue* getLastParen(ExecState*) const; 99 JSValue* getLeftContext(ExecState*) const; 100 JSValue* getRightContext(ExecState*) const; 101 102 OwnPtr<RegExpConstructorPrivate> d; 103 }; 104 105 } // namespace 106 107 #endif 41 #endif // RegExpPrototype_h -
trunk/JavaScriptCore/kjs/StringPrototype.cpp
r34861 r34863 25 25 #include "ObjectPrototype.h" 26 26 #include "PropertyNameArray.h" 27 #include "RegExpConstructor.h" 27 28 #include "RegExpObject.h" 28 29 #include "error_object.h" -
trunk/JavaScriptCore/kjs/internal.cpp
r34861 r34863 29 29 #include "MathObject.h" 30 30 #include "NumberObject.h" 31 #include "RegExpObject.h"32 31 #include "StringPrototype.h" 33 32 #include "collector.h"
Note:
See TracChangeset
for help on using the changeset viewer.