1 /* 2 * Copyright (C) 1999-2000 Harri Porten (porten (at) kde.org) 3 * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved. 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 * 19 */ 20 21 #include "config.h" 22 #include "RegExpPrototype.h" 23 24 #include "ArrayPrototype.h" 25 #include "Error.h" 26 #include "JSArray.h" 27 #include "JSFunction.h" 28 #include "JSObject.h" 29 #include "JSString.h" 30 #include "JSStringBuilder.h" 31 #include "JSValue.h" 32 #include "ObjectPrototype.h" 33 #include "PrototypeFunction.h" 34 #include "RegExpObject.h" 35 #include "RegExp.h" 36 37 namespace JSC { 38 39 ASSERT_CLASS_FITS_IN_CELL(RegExpPrototype); 40 41 static JSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState*, JSObject*, JSValue, const ArgList&); 42 static JSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState*, JSObject*, JSValue, const ArgList&); 43 static JSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState*, JSObject*, JSValue, const ArgList&); 44 static JSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&); 45 46 // ECMA 15.10.5 47 48 const ClassInfo RegExpPrototype::info = { "RegExpPrototype", 0, 0, 0 }; 49 50 RegExpPrototype::RegExpPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure) 51 : JSObject(structure) 52 { 53 putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum); 54 putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().exec, regExpProtoFuncExec), DontEnum); 55 putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().test, regExpProtoFuncTest), DontEnum); 56 putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, regExpProtoFuncToString), DontEnum); 57 } 58 59 // ------------------------------ Functions --------------------------- 60 61 JSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) 62 { 63 if (!thisValue.inherits(&RegExpObject::info)) 64 return throwError(exec, TypeError); 65 return asRegExpObject(thisValue)->test(exec, args); 66 } 67 68 JSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) 69 { 70 if (!thisValue.inherits(&RegExpObject::info)) 71 return throwError(exec, TypeError); 72 return asRegExpObject(thisValue)->exec(exec, args); 73 } 74 75 JSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) 76 { 77 if (!thisValue.inherits(&RegExpObject::info)) 78 return throwError(exec, TypeError); 79 80 RefPtr<RegExp> regExp; 81 JSValue arg0 = args.at(0); 82 JSValue arg1 = args.at(1); 83 84 if (arg0.inherits(&RegExpObject::info)) { 85 if (!arg1.isUndefined()) 86 return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another."); 87 regExp = asRegExpObject(arg0)->regExp(); 88 } else { 89 UString pattern = args.isEmpty() ? UString("") : arg0.toString(exec); 90 UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec); 91 regExp = RegExp::create(&exec->globalData(), pattern, flags); 92 } 93 94 if (!regExp->isValid()) 95 return throwError(exec, SyntaxError, makeString("Invalid regular expression: ", regExp->errorMessage())); 96 97 asRegExpObject(thisValue)->setRegExp(regExp.release()); 98 asRegExpObject(thisValue)->setLastIndex(0); 99 return jsUndefined(); 100 } 101 102 JSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) 103 { 104 if (!thisValue.inherits(&RegExpObject::info)) { 105 if (thisValue.inherits(&RegExpPrototype::info)) 106 return jsNontrivialString(exec, "//"); 107 return throwError(exec, TypeError); 108 } 109 110 char postfix[5] = { '/', 0, 0, 0, 0 }; 111 int index = 1; 112 if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().global).toBoolean(exec)) 113 postfix[index++] = 'g'; 114 if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().ignoreCase).toBoolean(exec)) 115 postfix[index++] = 'i'; 116 if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().multiline).toBoolean(exec)) 117 postfix[index] = 'm'; 118 UString source = asRegExpObject(thisValue)->get(exec, exec->propertyNames().source).toString(exec); 119 // If source is empty, use "/(?:)/" to avoid colliding with comment syntax 120 return jsMakeNontrivialString(exec, "/", source.size() ? source : UString("(?:)"), postfix); 121 } 122 123 } // namespace JSC 124