Changeset 34863 in webkit for trunk/JavaScriptCore/kjs


Ignore:
Timestamp:
Jun 28, 2008, 5:09:26 PM (17 years ago)
Author:
[email protected]
Message:

2008-06-28 Sam Weinig <[email protected]>

Rubber-stamped by Darin Adler.

Splits RegExpConstructor and RegExpPrototype out of RegExpObject.h/cpp

  • DerivedSources.make:
  • GNUmakefile.am:
  • JavaScriptCore.pri:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • JavaScriptCoreSources.bkl:
  • VM/Machine.cpp:
  • kjs/AllInOneFile.cpp:
  • kjs/JSGlobalObject.cpp:
  • kjs/RegExpConstructor.cpp: Copied from kjs/RegExpObject.cpp.
  • kjs/RegExpConstructor.h: Copied from kjs/RegExpObject.h.
  • kjs/RegExpObject.cpp:
  • kjs/RegExpObject.h:
  • kjs/RegExpPrototype.cpp: Copied from kjs/RegExpObject.cpp.
  • kjs/RegExpPrototype.h: Copied from kjs/RegExpObject.h.
  • kjs/StringPrototype.cpp:
  • kjs/internal.cpp:
Location:
trunk/JavaScriptCore/kjs
Files:
6 edited
4 copied

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/AllInOneFile.cpp

    r34861 r34863  
    7272#include "PropertyNameArray.cpp"
    7373#include "regexp.cpp"
     74#include "RegExpConstructor.cpp"
    7475#include "RegExpObject.cpp"
     76#include "RegExpPrototype.cpp"
    7577#include "ScopeChain.cpp"
    7678#include "StringConstructor.cpp"
  • trunk/JavaScriptCore/kjs/JSGlobalObject.cpp

    r34861 r34863  
    4444#include "ObjectConstructor.h"
    4545#include "ObjectPrototype.h"
    46 #include "RegExpObject.h"
     46#include "RegExpConstructor.h"
     47#include "RegExpPrototype.h"
    4748#include "ScopeChainMark.h"
    4849#include "StringConstructor.h"
  • trunk/JavaScriptCore/kjs/RegExpConstructor.cpp

    r34860 r34863  
    2020
    2121#include "config.h"
    22 #include "RegExpObject.h"
    23 #include "RegExpObject.lut.h"
     22#include "RegExpConstructor.h"
     23#include "RegExpConstructor.lut.h"
    2424
    2525#include "ArrayPrototype.h"
    2626#include "JSArray.h"
    27 #include "JSObject.h"
    2827#include "JSString.h"
    29 #include "JSValue.h"
    3028#include "ObjectPrototype.h"
    31 #include "UnusedParam.h"
     29#include "RegExpPrototype.h"
    3230#include "error_object.h"
    33 #include "operations.h"
    3431#include "regexp.h"
    3532
    36 #include <stdio.h>
    37 
    3833namespace KJS {
    3934
    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.5
    48 
    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.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 
    24435const ClassInfo RegExpConstructor::info = { "Function", &InternalFunction::info, 0, ExecState::regExpConstructorTable };
    24536
    246 /* Source for RegExpObject.lut.h
     37/* Source for RegExpConstructor.lut.h
    24738@begin regExpConstructorTable
    24839  input           RegExpConstructor::Input          None
     
    522313}
    523314
    524 }
     315} // namespace KJS
  • trunk/JavaScriptCore/kjs/RegExpConstructor.h

    r34860 r34863  
    1919 */
    2020
    21 #ifndef RegExpObject_h
    22 #define RegExpObject_h
     21#ifndef RegExpConstructor_h
     22#define RegExpConstructor_h
    2323
    2424#include "JSFunction.h"
    25 #include "JSObject.h"
    26 #include "regexp.h"
    2725
    2826namespace KJS {
    2927
    3028    class FunctionPrototype;
    31     class ObjectPrototype;
     29    class RegExpPrototype;
     30    class RegExp;
    3231    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     };
    7332
    7433    class RegExpConstructor : public InternalFunction {
  • trunk/JavaScriptCore/kjs/RegExpObject.cpp

    r34857 r34863  
    2323#include "RegExpObject.lut.h"
    2424
    25 #include "ArrayPrototype.h"
    2625#include "JSArray.h"
    27 #include "JSObject.h"
     26#include "JSGlobalObject.h"
    2827#include "JSString.h"
    29 #include "JSValue.h"
    30 #include "ObjectPrototype.h"
    31 #include "UnusedParam.h"
     28#include "RegExpConstructor.h"
     29#include "RegExpPrototype.h"
    3230#include "error_object.h"
    33 #include "operations.h"
    34 #include "regexp.h"
    35 
    36 #include <stdio.h>
    3731
    3832namespace 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.5
    48 
    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 ------------------------------------
    12233
    12334const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable };
     
    240151}
    241152
    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  
    2222#define RegExpObject_h
    2323
    24 #include "JSFunction.h"
    2524#include "JSObject.h"
    2625#include "regexp.h"
    2726
    2827namespace 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     };
    4128
    4229    class RegExpObject : public JSObject {
     
    7259    };
    7360
    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
    7862
    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  
    2020
    2121#include "config.h"
    22 #include "RegExpObject.h"
    23 #include "RegExpObject.lut.h"
     22#include "RegExpPrototype.h"
    2423
    2524#include "ArrayPrototype.h"
     25#include "FunctionPrototype.h"
    2626#include "JSArray.h"
    2727#include "JSObject.h"
     
    2929#include "JSValue.h"
    3030#include "ObjectPrototype.h"
     31#include "RegExpObject.h"
    3132#include "UnusedParam.h"
    3233#include "error_object.h"
     
    3435#include "regexp.h"
    3536
    36 #include <stdio.h>
    37 
    3837namespace KJS {
    39 
    40 // ------------------------------ RegExpPrototype ---------------------------
    4138
    4239static JSValue* regExpProtoFuncTest(ExecState*, JSObject*, JSValue*, const ArgList&);
     
    119116}
    120117
    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  
    1919 */
    2020
    21 #ifndef RegExpObject_h
    22 #define RegExpObject_h
     21#ifndef RegExpPrototype_h
     22#define RegExpPrototype_h
    2323
    24 #include "JSFunction.h"
    2524#include "JSObject.h"
    26 #include "regexp.h"
    2725
    2826namespace KJS {
     
    3028    class FunctionPrototype;
    3129    class ObjectPrototype;
    32     struct RegExpConstructorPrivate;
    3330
    3431    class RegExpPrototype : public JSObject {
     
    4037    };
    4138
    42     class RegExpObject : public JSObject {
    43     public:
    44         enum { Global, IgnoreCase, Multiline, Source, LastIndex };
     39} // namespace KJS
    4540
    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  
    2525#include "ObjectPrototype.h"
    2626#include "PropertyNameArray.h"
     27#include "RegExpConstructor.h"
    2728#include "RegExpObject.h"
    2829#include "error_object.h"
  • trunk/JavaScriptCore/kjs/internal.cpp

    r34861 r34863  
    2929#include "MathObject.h"
    3030#include "NumberObject.h"
    31 #include "RegExpObject.h"
    3231#include "StringPrototype.h"
    3332#include "collector.h"
Note: See TracChangeset for help on using the changeset viewer.