Ignore:
Timestamp:
Nov 3, 2007, 9:28:51 AM (18 years ago)
Author:
Darin Adler
Message:

Reviewed by Maciej.

Two or three fixes get 7 more of the Mozilla tests passing.
This gets us down from 61 failing tests to 54.

  • kjs/interpreter.h: (KJS::Interpreter::builtinRegExp): Made this inline and gave it a more specific type. Some day we should probably do that for all of these -- might even get a bit of a speed boost from it.
  • kjs/interpreter.cpp: Removed Interpreter::builtinRegExp now that it's inline in the header.
  • kjs/regexp_object.h:
  • kjs/regexp_object.cpp: (KJS::RegExpProtoFunc::callAsFunction): Moved test and exec out of the switch statement into the RegExpImp object, so they can be shared with RegExpImp::callAsFunction. (KJS::RegExpImp::match): Added. Common code used by both test and exec. (KJS::RegExpImp::test): Added. (KJS::RegExpImp::exec): Added. (KJS::RegExpImp::implementsCall): Added. (KJS::RegExpImp::callAsFunction): Added. (KJS::RegExpObjectImpPrivate::RegExpObjectImpPrivate): Initialize lastInput to null rather than empty string -- we take advantage of the difference in RegExpImp::match. (KJS::RegExpObjectImp::input): Added. No reason to go through hash tables just to get at a field like this.
  • pcre/pcre_compile.c: (check_escape): Changed the \u handling to match the JavaScript specification. If there are not 4 hex digits after the \u, then it's processed as if it wasn't an escape sequence at all.
  • pcre/pcre_internal.h: Added IS_NEWLINE, with the appropriate definition for JavaScript (4 specific Unicode values).
  • pcre/pcre_exec.c: (match): Changed all call sites to use IS_NEWLINE. (pcre_exec): Ditto.
  • tests/mozilla/expected.html: Updated to expect 7 more successful tests.
File:
1 edited

Legend:

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

    r27393 r27405  
    1 // -*- c-basic-offset: 2 -*-
    21/*
    32 *  Copyright (C) 1999-2000 Harri Porten ([email protected])
     
    3635#include <stdio.h>
    3736
    38 using namespace KJS;
     37namespace KJS {
    3938
    4039// ------------------------------ RegExpPrototype ---------------------------
     
    7978  }
    8079
    81   switch (id) {
    82   case Test:      // 15.10.6.2
    83   case Exec:
    84   {
    85     RegExp *regExp = static_cast<RegExpImp*>(thisObj)->regExp();
    86     RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->lexicalInterpreter()->builtinRegExp());
    87 
    88     UString input;
    89     if (args.isEmpty())
    90       input = regExpObj->get(exec, exec->propertyNames().input)->toString(exec);
    91     else
    92       input = args[0]->toString(exec);
    93 
    94     double lastIndex = thisObj->get(exec, exec->propertyNames().lastIndex)->toInteger(exec);
    95 
    96     bool globalFlag = thisObj->get(exec, exec->propertyNames().global)->toBoolean(exec);
    97     if (!globalFlag)
    98       lastIndex = 0;
    99     if (lastIndex < 0 || lastIndex > input.size()) {
    100       thisObj->put(exec, exec->propertyNames().lastIndex, jsNumber(0), DontDelete | DontEnum);
    101       return jsNull();
    102     }
    103 
    104     int foundIndex;
    105     int foundLength;
    106     regExpObj->performMatch(regExp, input, static_cast<int>(lastIndex), foundIndex, foundLength);
    107 
    108     // Test
    109     if (id == Test)
    110       return jsBoolean(foundIndex >= 0);
    111 
    112     // Exec
    113     if (foundIndex < 0) {
    114       if (globalFlag)
    115         thisObj->put(exec, exec->propertyNames().lastIndex, jsNumber(0), DontDelete | DontEnum);
    116       return jsNull();
    117     }
    118     if (globalFlag)
    119       thisObj->put(exec, exec->propertyNames().lastIndex, jsNumber(foundIndex + foundLength), DontDelete | DontEnum);
    120     return regExpObj->arrayOfMatches(exec);
    121   }
    122   break;
     80    switch (id) {
     81        case Test:
     82            return static_cast<RegExpImp*>(thisObj)->test(exec, args);
     83        case Exec:
     84            return static_cast<RegExpImp*>(thisObj)->exec(exec, args);
    12385  case Compile:
    12486  {
     
    192154const ClassInfo RegExpImp::info = {"RegExp", 0, 0, 0};
    193155
    194 RegExpImp::RegExpImp(RegExpPrototype* regexpProto)
     156RegExpImp::RegExpImp(RegExpPrototype* regexpProto, RegExp* exp)
    195157  : JSObject(regexpProto)
     158  , m_regExp(exp)
    196159{
    197160}
     
    199162RegExpImp::~RegExpImp()
    200163{
     164}
     165
     166bool RegExpImp::match(ExecState* exec, const List& args)
     167{
     168    RegExpObjectImp* regExpObj = exec->lexicalInterpreter()->builtinRegExp();
     169
     170    UString input;
     171    if (!args.isEmpty())
     172        input = args[0]->toString(exec);
     173    else {
     174        input = regExpObj->input();
     175        if (input.isNull()) {
     176            throwError(exec, GeneralError, "No input.");
     177            return false;
     178        }
     179    }
     180
     181    bool global = get(exec, exec->propertyNames().global)->toBoolean(exec);
     182    int lastIndex = 0;
     183    if (global) {
     184        double lastIndexDouble = get(exec, exec->propertyNames().lastIndex)->toInteger(exec);
     185        if (lastIndexDouble < 0 || lastIndexDouble > input.size()) {
     186            put(exec, exec->propertyNames().lastIndex, jsNumber(0), DontDelete | DontEnum);
     187            return false;
     188        }
     189        lastIndex = static_cast<int>(lastIndexDouble);
     190    }
     191
     192    int foundIndex;
     193    int foundLength;
     194    regExpObj->performMatch(m_regExp.get(), input, lastIndex, foundIndex, foundLength);
     195
     196    if (global) {
     197        lastIndex = foundIndex < 0 ? 0 : foundIndex + foundLength;
     198        put(exec, exec->propertyNames().lastIndex, jsNumber(lastIndex), DontDelete | DontEnum);
     199    }
     200
     201    return foundIndex >= 0;
     202}
     203
     204JSValue* RegExpImp::test(ExecState* exec, const List& args)
     205{
     206    return jsBoolean(match(exec, args));
     207}
     208
     209JSValue* RegExpImp::exec(ExecState* exec, const List& args)
     210{
     211    return match(exec, args)
     212        ? exec->lexicalInterpreter()->builtinRegExp()->arrayOfMatches(exec)
     213        :  jsNull();
     214}
     215
     216bool RegExpImp::implementsCall() const
     217{
     218    return true;
     219}
     220
     221JSValue* RegExpImp::callAsFunction(ExecState* exec, JSObject*, const List& args)
     222{
     223    return RegExpImp::exec(exec, args);
    201224}
    202225
     
    231254*/
    232255
    233 struct KJS::RegExpObjectImpPrivate {
     256struct RegExpObjectImpPrivate {
    234257  // Global search cache / settings
    235   RegExpObjectImpPrivate() : lastInput(""), lastNumSubPatterns(0), multiline(false) { }
     258  RegExpObjectImpPrivate() : lastNumSubPatterns(0), multiline(false) { }
    236259  UString lastInput;
    237260  OwnArrayPtr<int> lastOvector;
     
    404427  UString flags = args[1]->isUndefined() ? UString("") : args[1]->toString(exec);
    405428
    406   RegExpPrototype *proto = static_cast<RegExpPrototype*>(exec->lexicalInterpreter()->builtinRegExpPrototype());
    407   RegExpImp *dat = new RegExpImp(proto);
     429  RegExpPrototype* proto = static_cast<RegExpPrototype*>(exec->lexicalInterpreter()->builtinRegExpPrototype());
    408430
    409431  bool global = (flags.find("g") >= 0);
    410432  bool ignoreCase = (flags.find("i") >= 0);
    411433  bool multiline = (flags.find("m") >= 0);
    412 
    413   dat->putDirect(exec->propertyNames().global, jsBoolean(global), DontDelete | ReadOnly | DontEnum);
    414   dat->putDirect(exec->propertyNames().ignoreCase, jsBoolean(ignoreCase), DontDelete | ReadOnly | DontEnum);
    415   dat->putDirect(exec->propertyNames().multiline, jsBoolean(multiline), DontDelete | ReadOnly | DontEnum);
    416 
    417   dat->putDirect(exec->propertyNames().source, jsString(p), DontDelete | ReadOnly | DontEnum);
    418   dat->putDirect(exec->propertyNames().lastIndex, jsNumber(0), DontDelete | DontEnum);
    419434
    420435  int reflags = RegExp::None;
     
    430445      return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(re->errorMessage()));
    431446
    432   dat->setRegExp(re.release());
     447  RegExpImp* dat = new RegExpImp(proto, re.release());
     448
     449  dat->putDirect(exec->propertyNames().global, jsBoolean(global), DontDelete | ReadOnly | DontEnum);
     450  dat->putDirect(exec->propertyNames().ignoreCase, jsBoolean(ignoreCase), DontDelete | ReadOnly | DontEnum);
     451  dat->putDirect(exec->propertyNames().multiline, jsBoolean(multiline), DontDelete | ReadOnly | DontEnum);
     452
     453  dat->putDirect(exec->propertyNames().source, jsString(p), DontDelete | ReadOnly | DontEnum);
     454  dat->putDirect(exec->propertyNames().lastIndex, jsNumber(0), DontDelete | DontEnum);
    433455
    434456  return dat;
     
    440462  return construct(exec, args);
    441463}
     464
     465const UString& RegExpObjectImp::input() const
     466{
     467    // Can detect a distinct initial state that is invisible to JavaScript, by checking for null
     468    // state (since jsString turns null strings to empty strings).
     469    return d->lastInput;
     470}
     471
     472}
Note: See TracChangeset for help on using the changeset viewer.