Home | History | Annotate | Download | only in runtime
      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 "RegExpObject.h"
     23 
     24 #include "Error.h"
     25 #include "JSArray.h"
     26 #include "JSGlobalObject.h"
     27 #include "JSString.h"
     28 #include "RegExpConstructor.h"
     29 #include "RegExpPrototype.h"
     30 
     31 namespace JSC {
     32 
     33 static JSValue regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot&);
     34 static JSValue regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot&);
     35 static JSValue regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot&);
     36 static JSValue regExpObjectSource(ExecState*, const Identifier&, const PropertySlot&);
     37 static JSValue regExpObjectLastIndex(ExecState*, const Identifier&, const PropertySlot&);
     38 static void setRegExpObjectLastIndex(ExecState*, JSObject*, JSValue);
     39 
     40 } // namespace JSC
     41 
     42 #include "RegExpObject.lut.h"
     43 
     44 namespace JSC {
     45 
     46 ASSERT_CLASS_FITS_IN_CELL(RegExpObject);
     47 
     48 const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable };
     49 
     50 /* Source for RegExpObject.lut.h
     51 @begin regExpTable
     52     global        regExpObjectGlobal       DontDelete|ReadOnly|DontEnum
     53     ignoreCase    regExpObjectIgnoreCase   DontDelete|ReadOnly|DontEnum
     54     multiline     regExpObjectMultiline    DontDelete|ReadOnly|DontEnum
     55     source        regExpObjectSource       DontDelete|ReadOnly|DontEnum
     56     lastIndex     regExpObjectLastIndex    DontDelete|DontEnum
     57 @end
     58 */
     59 
     60 RegExpObject::RegExpObject(NonNullPassRefPtr<Structure> structure, NonNullPassRefPtr<RegExp> regExp)
     61     : JSObject(structure)
     62     , d(new RegExpObjectData(regExp, 0))
     63 {
     64 }
     65 
     66 RegExpObject::~RegExpObject()
     67 {
     68 }
     69 
     70 bool RegExpObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
     71 {
     72     return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot);
     73 }
     74 
     75 bool RegExpObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     76 {
     77     return getStaticValueDescriptor<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, descriptor);
     78 }
     79 
     80 JSValue regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot& slot)
     81 {
     82     return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->global());
     83 }
     84 
     85 JSValue regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot& slot)
     86 {
     87     return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->ignoreCase());
     88 }
     89 
     90 JSValue regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot& slot)
     91 {
     92     return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->multiline());
     93 }
     94 
     95 JSValue regExpObjectSource(ExecState* exec, const Identifier&, const PropertySlot& slot)
     96 {
     97     return jsString(exec, asRegExpObject(slot.slotBase())->regExp()->pattern());
     98 }
     99 
    100 JSValue regExpObjectLastIndex(ExecState* exec, const Identifier&, const PropertySlot& slot)
    101 {
    102     return jsNumber(exec, asRegExpObject(slot.slotBase())->lastIndex());
    103 }
    104 
    105 void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
    106 {
    107     lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), this, slot);
    108 }
    109 
    110 void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValue value)
    111 {
    112     asRegExpObject(baseObject)->setLastIndex(value.toInteger(exec));
    113 }
    114 
    115 JSValue RegExpObject::test(ExecState* exec, const ArgList& args)
    116 {
    117     return jsBoolean(match(exec, args));
    118 }
    119 
    120 JSValue RegExpObject::exec(ExecState* exec, const ArgList& args)
    121 {
    122     if (match(exec, args))
    123         return exec->lexicalGlobalObject()->regExpConstructor()->arrayOfMatches(exec);
    124     return jsNull();
    125 }
    126 
    127 static JSValue JSC_HOST_CALL callRegExpObject(ExecState* exec, JSObject* function, JSValue, const ArgList& args)
    128 {
    129     return asRegExpObject(function)->exec(exec, args);
    130 }
    131 
    132 CallType RegExpObject::getCallData(CallData& callData)
    133 {
    134     callData.native.function = callRegExpObject;
    135     return CallTypeHost;
    136 }
    137 
    138 // Shared implementation used by test and exec.
    139 bool RegExpObject::match(ExecState* exec, const ArgList& args)
    140 {
    141     RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
    142 
    143     UString input = args.isEmpty() ? regExpConstructor->input() : args.at(0).toString(exec);
    144     if (input.isNull()) {
    145         throwError(exec, GeneralError, makeString("No input to ", toString(exec), "."));
    146         return false;
    147     }
    148 
    149     if (!regExp()->global()) {
    150         int position;
    151         int length;
    152         regExpConstructor->performMatch(d->regExp.get(), input, 0, position, length);
    153         return position >= 0;
    154     }
    155 
    156     if (d->lastIndex < 0 || d->lastIndex > input.size()) {
    157         d->lastIndex = 0;
    158         return false;
    159     }
    160 
    161     int position;
    162     int length = 0;
    163     regExpConstructor->performMatch(d->regExp.get(), input, static_cast<int>(d->lastIndex), position, length);
    164     if (position < 0) {
    165         d->lastIndex = 0;
    166         return false;
    167     }
    168 
    169     d->lastIndex = position + length;
    170     return true;
    171 }
    172 
    173 } // namespace JSC
    174