Beispiel #1
0
// ECMA 15.10.4
Object RegExpObjectImp::construct(ExecState *exec, const List &args)
{
  UString p;
  if (args.isEmpty()) {
      p = "";
  } else {
    Value a0 = args[0];
    if (a0.isA(ObjectType) && a0.toObject(exec).inherits(&RegExpImp::info)) {
      // It's a regexp. Check that no flags were passed.
      if (args.size() > 1 && args[1].type() != UndefinedType) {
          Object err = Error::create(exec,TypeError);
          exec->setException(err);
          return err;
      }
      RegExpImp *rimp = static_cast<RegExpImp*>(Object::dynamicCast(a0).imp());
      p = rimp->regExp()->pattern();
    } else {
      p = a0.toString(exec);
    }
  }

  RegExp* re = makeEngine(exec, p, args[1]);
  if (!re)
    return exec->exception().toObject(exec);

  RegExpPrototypeImp *proto = static_cast<RegExpPrototypeImp*>(exec->lexicalInterpreter()->builtinRegExpPrototype().imp());
  RegExpImp *dat = new RegExpImp(proto);
  Object obj(dat); // protect from GC
  dat->setRegExp(re);

  return obj;
}
Beispiel #2
0
// ECMA 15.10.4
Object RegExpObjectImp::construct(ExecState *exec, const List &args)
{
  UString p = args.isEmpty() ? UString("") : args[0].toString(exec);
  UString flags = args[1].toString(exec);

  RegExpPrototypeImp *proto = static_cast<RegExpPrototypeImp*>(exec->interpreter()->builtinRegExpPrototype().imp());
  RegExpImp *dat = new RegExpImp(proto);
  Object obj(dat); // protect from GC

  bool global = (flags.find("g") >= 0);
  bool ignoreCase = (flags.find("i") >= 0);
  bool multiline = (flags.find("m") >= 0);
  // TODO: throw a syntax error on invalid flags

  dat->putDirect("global", global ? BooleanImp::staticTrue : BooleanImp::staticFalse);
  dat->putDirect("ignoreCase", ignoreCase ? BooleanImp::staticTrue : BooleanImp::staticFalse);
  dat->putDirect("multiline", multiline ? BooleanImp::staticTrue : BooleanImp::staticFalse);

  dat->putDirect("source", new StringImp(p));
  dat->putDirect("lastIndex", NumberImp::zero(), DontDelete | DontEnum);

  int reflags = RegExp::None;
  if (global)
      reflags |= RegExp::Global;
  if (ignoreCase)
      reflags |= RegExp::IgnoreCase;
  if (multiline)
      reflags |= RegExp::Multiline;
  dat->setRegExp(new RegExp(p, reflags));

  return obj;
}
Beispiel #3
0
// ECMA 15.10.4
JSObject *RegExpObjectImp::construct(ExecState *exec, const List &args)
{
  JSObject *o = args[0]->getObject();
  if (o && o->inherits(&RegExpImp::info)) {
    if (!args[1]->isUndefined())
      return throwError(exec, TypeError);
    return o;
  }
  
  UString p = args[0]->isUndefined() ? UString("") : args[0]->toString(exec);
  UString flags = args[1]->isUndefined() ? UString("") : args[1]->toString(exec);

  RegExpPrototype *proto = static_cast<RegExpPrototype*>(exec->lexicalInterpreter()->builtinRegExpPrototype());
  RegExpImp *dat = new RegExpImp(proto);

  bool global = (flags.find("g") >= 0);
  bool ignoreCase = (flags.find("i") >= 0);
  bool multiline = (flags.find("m") >= 0);

  dat->putDirect(exec->propertyNames().global, jsBoolean(global), DontDelete | ReadOnly | DontEnum);
  dat->putDirect(exec->propertyNames().ignoreCase, jsBoolean(ignoreCase), DontDelete | ReadOnly | DontEnum);
  dat->putDirect(exec->propertyNames().multiline, jsBoolean(multiline), DontDelete | ReadOnly | DontEnum);

  dat->putDirect(exec->propertyNames().source, jsString(p), DontDelete | ReadOnly | DontEnum);
  dat->putDirect(exec->propertyNames().lastIndex, jsNumber(0), DontDelete | DontEnum);

  int reflags = RegExp::None;
  if (global)
      reflags |= RegExp::Global;
  if (ignoreCase)
      reflags |= RegExp::IgnoreCase;
  if (multiline)
      reflags |= RegExp::Multiline;

  OwnPtr<RegExp> re(new RegExp(p, reflags));
  if (!re->isValid())
      return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(re->errorMessage()));

  dat->setRegExp(re.release());

  return dat;
}
Beispiel #4
0
// ECMA 15.10.4
JSObject *RegExpObjectImp::construct(ExecState *exec, const List &args)
{
  JSObject *o = args[0]->getObject();
  if (o && o->inherits(&RegExpImp::info)) {
    if (!args[1]->isUndefined())
      return throwError(exec, TypeError);
    return o;
  }

  UString p = args[0]->isUndefined() ? UString("") : args[0]->toString(exec);

  RegExp* re = makeEngine(exec, p, args[1]);
  if (!re)
    return exec->exception()->toObject(exec);


  RegExpPrototype *proto = static_cast<RegExpPrototype*>(exec->lexicalInterpreter()->builtinRegExpPrototype());
  RegExpImp *dat = new RegExpImp(proto);

  dat->setRegExp(exec, re);

  return dat;
}
Beispiel #5
0
JSValue *RegExpProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
{
  if (!thisObj->inherits(&RegExpImp::info)) {
    if (thisObj->inherits(&RegExpPrototype::info)) {
      switch (id) {
        case ToString: return jsString("//");
      }
    }

    return throwError(exec, TypeError);
  }

  switch (id) {
  case Test:      // 15.10.6.2
  case Exec:
  {
    RegExp *regExp = static_cast<RegExpImp*>(thisObj)->regExp();
    RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->lexicalInterpreter()->builtinRegExp());

    UString input;
    if (args.isEmpty())
      input = regExpObj->get(exec, exec->propertyNames().input)->toString(exec);
    else
      input = args[0]->toString(exec);

    double lastIndex = thisObj->get(exec, exec->propertyNames().lastIndex)->toInteger(exec);

    bool globalFlag = thisObj->get(exec, exec->propertyNames().global)->toBoolean(exec);
    if (!globalFlag)
      lastIndex = 0;
    if (lastIndex < 0 || lastIndex > input.size()) {
      thisObj->put(exec, exec->propertyNames().lastIndex, jsNumber(0), DontDelete | DontEnum);
      return jsNull();
    }

    int foundIndex;

    RegExpStringContext ctx(input);
    UString match = regExpObj->performMatch(regExp, exec, ctx, input, static_cast<int>(lastIndex), &foundIndex);

    if (exec->hadException())
      return jsUndefined();

    bool didMatch = !match.isNull();

    if (globalFlag) {
      if (didMatch)
        thisObj->put(exec, exec->propertyNames().lastIndex, jsNumber(foundIndex + match.size()), DontDelete | DontEnum);
      else
        thisObj->put(exec, exec->propertyNames().lastIndex, jsNumber(0), DontDelete | DontEnum);
    }

    // Test
    if (id == Test)
      return jsBoolean(didMatch);

    // Exec
    if (didMatch) {
      return regExpObj->arrayOfMatches(exec, match);
    } else {
      return jsNull();
    }
  }
  break;
  case ToString: {
    UString result = "/" + thisObj->get(exec, exec->propertyNames().source)->toString(exec) + "/";
    if (thisObj->get(exec, exec->propertyNames().global)->toBoolean(exec)) {
      result += "g";
    }
    if (thisObj->get(exec, exec->propertyNames().ignoreCase)->toBoolean(exec)) {
      result += "i";
    }
    if (thisObj->get(exec, exec->propertyNames().multiline)->toBoolean(exec)) {
      result += "m";
    }
    return jsString(result);
  }
  case Compile: { // JS1.2 legacy, but still in use in the wild somewhat
      RegExpImp* instance = static_cast<RegExpImp*>(thisObj);
      RegExp* newEngine   = RegExpObjectImp::makeEngine(exec, args[0]->toString(exec), args[1]);
      if (!newEngine)
        return exec->exception();
      instance->setRegExp(exec, newEngine);
      return instance;
    }
  }

  return jsUndefined();
}
Beispiel #6
0
JSObject* RegExpImp::valueClone(Interpreter* targetCtx) const
{
    RegExpImp* copy = new RegExpImp(static_cast<RegExpPrototype*>(targetCtx->builtinRegExpPrototype()));
    copy->setRegExp(targetCtx->globalExec(), new RegExp(reg->pattern(), reg->flags()));
    return copy;
}
Beispiel #7
0
Value RegExpProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args)
{
  if (!thisObj.inherits(&RegExpImp::info)) {
    if (thisObj.inherits(&RegExpPrototypeImp::info)) {
      switch (id) {
        case ToString: return String("//"); // FireFox returns /(?:)/
      }
    }
    Object err = Error::create(exec,TypeError);
    exec->setException(err);
    return err;
  }

  RegExpImp *reimp = static_cast<RegExpImp*>(thisObj.imp());
  RegExp *re = reimp->regExp();
  String s;
  UString str;
  switch (id) {
  case Exec:      // 15.10.6.2
  case Test:
  {
    s = args[0].toString(exec);
    int length = s.value().size();

    // Get values from the last time (in case of /g)
    Value lastIndex = thisObj.get(exec,"lastIndex");
    int i = lastIndex.isValid() ? lastIndex.toInt32(exec) : 0;
    bool globalFlag = thisObj.get(exec,"global").toBoolean(exec);
    if (!globalFlag)
      i = 0;
    if (i < 0 || i > length) {
      thisObj.put(exec,"lastIndex", Number(0), DontDelete | DontEnum);
      if (id == Test)
        return Boolean(false);
      else
        return Null();
    }
    RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->lexicalInterpreter()->builtinRegExp().imp());
    int **ovector = regExpObj->registerRegexp( re, s.value() );

    re->prepareMatch(s.value());
    str = re->match(s.value(), i, 0L, ovector);
    re->doneMatch();
    regExpObj->setSubPatterns(re->subPatterns());

    if (id == Test)
      return Boolean(!str.isNull());

    if (str.isNull()) // no match
    {
      if (globalFlag)
        thisObj.put(exec,"lastIndex",Number(0), DontDelete | DontEnum);
      return Null();
    }
    else // success
    {
      if (globalFlag)
        thisObj.put(exec,"lastIndex",Number( (*ovector)[1] ), DontDelete | DontEnum);
      return regExpObj->arrayOfMatches(exec,str);
    }
  }
  break;
  case ToString:
    s = thisObj.get(exec,"source").toString(exec);
    str = "/";
    str += s.value();
    str += "/";
    if (thisObj.get(exec,"global").toBoolean(exec)) {
      str += "g";
    }
    if (thisObj.get(exec,"ignoreCase").toBoolean(exec)) {
      str += "i";
    }
    if (thisObj.get(exec,"multiline").toBoolean(exec)) {
      str += "m";
    }
    return String(str);
  case Compile: {
      RegExp* newEngine = RegExpObjectImp::makeEngine(exec, args[0].toString(exec), args[1]);
      if (!newEngine)
        return exec->exception();
      reimp->setRegExp(newEngine);
      return Value(reimp);
    }
  }
  

  return Undefined();
}