⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 array_object.cpp

📁 khtml在gtk上的移植版本
💻 CPP
📖 第 1 页 / 共 2 页
字号:
{  Value protect(this);  setInternalValue(Null());}Value ArrayPrototypeImp::get(ExecState *exec, const Identifier &propertyName) const{  //fprintf( stderr, "ArrayPrototypeImp::get(%s)\n", propertyName.ascii() );  return lookupGetFunction<ArrayProtoFuncImp, ArrayInstanceImp>( exec, propertyName, &arrayTable, this );}// ------------------------------ ArrayProtoFuncImp ----------------------------ArrayProtoFuncImp::ArrayProtoFuncImp(ExecState *exec, int i, int len)  : InternalFunctionImp(    static_cast<FunctionPrototypeImp*>(exec->lexicalInterpreter()->builtinFunctionPrototype().imp())    ), id(i){  Value protect(this);  put(exec,lengthPropertyName,Number(len),DontDelete|ReadOnly|DontEnum);}bool ArrayProtoFuncImp::implementsCall() const{  return true;}// ECMA 15.4.4Value ArrayProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args){  unsigned int length = thisObj.get(exec,lengthPropertyName).toUInt32(exec);  Value result;  switch (id) {  case ToLocaleString:    // TODO  - see 15.4.4.3    // fall through  case ToString:    if (!thisObj.inherits(&ArrayInstanceImp::info)) {      Object err = Error::create(exec,TypeError);      exec->setException(err);      return err;    }    // fall through  case Join: {    UString separator = ",";    UString str = "";    if (args.size() > 0)      separator = args[0].toString(exec);    for (unsigned int k = 0; k < length; k++) {      if (k >= 1)        str += separator;      Value element = thisObj.get(exec,k);      if (element.type() != UndefinedType && element.type() != NullType)        str += element.toString(exec);      if ( exec->hadException() )	break;    }    result = String(str);    break;  }  case Concat: {    Object arr = Object::dynamicCast(exec->lexicalInterpreter()->builtinArray().construct(exec,List::empty()));    int n = 0;    Value curArg = thisObj;    Object curObj = Object::dynamicCast(thisObj);    ListIterator it = args.begin();    for (;;) {      if (curArg.type() == ObjectType &&          curObj.inherits(&ArrayInstanceImp::info)) {        unsigned int k = 0;        // Older versions tried to optimize out getting the length of thisObj        // by checking for n != 0, but that doesn't work if thisObj is an empty array.        length = curObj.get(exec,lengthPropertyName).toUInt32(exec);        while (k < length) {          if (curObj.hasProperty(exec,k))            arr.put(exec, n, curObj.get(exec, k));          n++;          k++;        }      } else {        arr.put(exec, n, curArg);        n++;      }      if (it == args.end())        break;      curArg = *it;      curObj = Object::dynamicCast(it++); // may be 0    }    arr.put(exec,lengthPropertyName, Number(n), DontEnum | DontDelete);    result = arr;    break;  }  case Pop:{    if (length == 0) {      thisObj.put(exec, lengthPropertyName, Number(length), DontEnum | DontDelete);      result = Undefined();    } else {      result = thisObj.get(exec, length - 1);      thisObj.put(exec, lengthPropertyName, Number(length - 1), DontEnum | DontDelete);    }    break;  }  case Push: {    for (int n = 0; n < args.size(); n++)      thisObj.put(exec, length + n, args[n]);    length += args.size();    thisObj.put(exec,lengthPropertyName, Number(length), DontEnum | DontDelete);    result = Number(length);    break;  }  case Reverse: {    unsigned int middle = length / 2;    for (unsigned int k = 0; k < middle; k++) {      unsigned lk1 = length - k - 1;      Value obj = thisObj.get(exec,k);      Value obj2 = thisObj.get(exec,lk1);      if (thisObj.hasProperty(exec,lk1)) {        if (thisObj.hasProperty(exec,k)) {          thisObj.put(exec, k, obj2);          thisObj.put(exec, lk1, obj);        } else {          thisObj.put(exec, k, obj2);          thisObj.deleteProperty(exec, lk1);        }      } else {        if (thisObj.hasProperty(exec, k)) {          thisObj.deleteProperty(exec, k);          thisObj.put(exec, lk1, obj);        } else {          // why delete something that's not there ? Strange.          thisObj.deleteProperty(exec, k);          thisObj.deleteProperty(exec, lk1);        }      }    }    result = thisObj;    break;  }  case Shift: {    if (length == 0) {      thisObj.put(exec, lengthPropertyName, Number(length), DontEnum | DontDelete);      result = Undefined();    } else {      result = thisObj.get(exec, 0);      for(unsigned int k = 1; k < length; k++) {        if (thisObj.hasProperty(exec, k)) {          Value obj = thisObj.get(exec, k);          thisObj.put(exec, k-1, obj);        } else          thisObj.deleteProperty(exec, k-1);      }      thisObj.deleteProperty(exec, length - 1);      thisObj.put(exec, lengthPropertyName, Number(length - 1), DontEnum | DontDelete);    }    break;  }  case Slice: {    // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10    // We return a new array    Object resObj = Object::dynamicCast(exec->lexicalInterpreter()->builtinArray().construct(exec,List::empty()));    result = resObj;    double begin = args[0].toInteger(exec);    if (begin < 0) {      begin += length;      if (begin < 0)        begin = 0;    } else {      if (begin > length)        begin = length;    }    double end = length;    if (args[1].type() != UndefinedType) {      end = args[1].toInteger(exec);      if (end < 0) {        end += length;        if (end < 0)          end = 0;      } else {        if (end > length)          end = length;      }    }    //printf( "Slicing from %d to %d \n", begin, end );    int n = 0;    int b = static_cast<int>(begin);    int e = static_cast<int>(end);    for(int k = b; k < e; k++, n++) {      if (thisObj.hasProperty(exec, k)) {        Value obj = thisObj.get(exec, k);        resObj.put(exec, n, obj);      }    }    resObj.put(exec, lengthPropertyName, Number(n), DontEnum | DontDelete);    break;  }  case Sort:{#if 0    printf("KJS Array::Sort length=%d\n", length);    for ( unsigned int i = 0 ; i<length ; ++i )      printf("KJS Array::Sort: %d: %s\n", i, thisObj.get(exec, i).toString(exec).ascii() );#endif    Object sortFunction;    bool useSortFunction = (args[0].type() != UndefinedType);    if (useSortFunction)      {        sortFunction = args[0].toObject(exec);        if (!sortFunction.implementsCall())          useSortFunction = false;      }        if (thisObj.imp()->classInfo() == &ArrayInstanceImp::info) {      if (useSortFunction)        ((ArrayInstanceImp *)thisObj.imp())->sort(exec, sortFunction);      else        ((ArrayInstanceImp *)thisObj.imp())->sort(exec);      result = thisObj;      break;    }    if (length == 0) {      thisObj.put(exec, lengthPropertyName, Number(0), DontEnum | DontDelete);      result = thisObj;      break;    }    // "Min" sort. Not the fastest, but definitely less code than heapsort    // or quicksort, and much less swapping than bubblesort/insertionsort.    for ( unsigned int i = 0 ; i<length-1 ; ++i )      {        Value iObj = thisObj.get(exec,i);        unsigned int themin = i;        Value minObj = iObj;        for ( unsigned int j = i+1 ; j<length ; ++j )          {            Value jObj = thisObj.get(exec,j);            double cmp;            if (jObj.type() == UndefinedType) {              cmp = 1; // don't check minObj because there's no need to differentiate == (0) from > (1)            } else if (minObj.type() == UndefinedType) {              cmp = -1;            } else if (useSortFunction) {                List l;                l.append(jObj);                l.append(minObj);                cmp = sortFunction.call(exec, exec->dynamicInterpreter()->globalObject(), l).toNumber(exec);            } else {              cmp = (jObj.toString(exec) < minObj.toString(exec)) ? -1 : 1;            }            if ( cmp < 0 )              {                themin = j;                minObj = jObj;              }          }        // Swap themin and i        if ( themin > i )          {            //printf("KJS Array::Sort: swapping %d and %d\n", i, themin );            thisObj.put( exec, i, minObj );            thisObj.put( exec, themin, iObj );          }      }#if 0    printf("KJS Array::Sort -- Resulting array:\n");    for ( unsigned int i = 0 ; i<length ; ++i )      printf("KJS Array::Sort: %d: %s\n", i, thisObj.get(exec, i).toString(exec).ascii() );#endif    result = thisObj;    break;  }  case Splice: {    // 15.4.4.12 - oh boy this is huge    Object resObj = Object::dynamicCast(exec->lexicalInterpreter()->builtinArray().construct(exec,List::empty()));    result = resObj;    int begin = args[0].toUInt32(exec);    if ( begin < 0 )      begin = maxInt( begin + length, 0 );    else      begin = minInt( begin, length );    unsigned int deleteCount = minInt( maxInt( args[1].toUInt32(exec), 0 ), length - begin );    //printf( "Splicing from %d, deleteCount=%d \n", begin, deleteCount );    for(unsigned int k = 0; k < deleteCount; k++) {      if (thisObj.hasProperty(exec,k+begin)) {        Value obj = thisObj.get(exec, k+begin);        resObj.put(exec, k, obj);      }    }    resObj.put(exec, lengthPropertyName, Number(deleteCount), DontEnum | DontDelete);    unsigned int additionalArgs = maxInt( args.size() - 2, 0 );    if ( additionalArgs != deleteCount )    {      if ( additionalArgs < deleteCount )      {        for ( unsigned int k = begin; k < length - deleteCount; ++k )        {          if (thisObj.hasProperty(exec,k+deleteCount)) {            Value obj = thisObj.get(exec, k+deleteCount);            thisObj.put(exec, k+additionalArgs, obj);          }          else            thisObj.deleteProperty(exec, k+additionalArgs);        }        for ( unsigned int k = length ; k > length - deleteCount + additionalArgs; --k )          thisObj.deleteProperty(exec, k-1);      }      else      {        for ( unsigned int k = length - deleteCount; (int)k > begin; --k )        {          if (thisObj.hasProperty(exec,k+deleteCount-1)) {            Value obj = thisObj.get(exec, k+deleteCount-1);            thisObj.put(exec, k+additionalArgs-1, obj);          }          else            thisObj.deleteProperty(exec, k+additionalArgs-1);        }      }    }    for ( unsigned int k = 0; k < additionalArgs; ++k )    {      thisObj.put(exec, k+begin, args[k+2]);    }    thisObj.put(exec, lengthPropertyName, Number(length - deleteCount + additionalArgs), DontEnum | DontDelete);    break;  }  case UnShift: { // 15.4.4.13    unsigned int nrArgs = args.size();    for ( unsigned int k = length; k > 0; --k )    {      if (thisObj.hasProperty(exec,k-1)) {        Value obj = thisObj.get(exec, k-1);        thisObj.put(exec, k+nrArgs-1, obj);      } else {        thisObj.deleteProperty(exec, k+nrArgs-1);      }    }    for ( unsigned int k = 0; k < nrArgs; ++k )      thisObj.put(exec, k, args[k]);    result = Number(length + nrArgs);    thisObj.put(exec, lengthPropertyName, result, DontEnum | DontDelete);    break;  }  default:    assert(0);    break;  }  return result;}// ------------------------------ ArrayObjectImp -------------------------------ArrayObjectImp::ArrayObjectImp(ExecState *exec,                               FunctionPrototypeImp *funcProto,                               ArrayPrototypeImp *arrayProto)  : InternalFunctionImp(funcProto){  Value protect(this);  // ECMA 15.4.3.1 Array.prototype  put(exec,prototypePropertyName, Object(arrayProto), DontEnum|DontDelete|ReadOnly);  // no. of arguments for constructor  put(exec,lengthPropertyName, Number(1), ReadOnly|DontDelete|DontEnum);}bool ArrayObjectImp::implementsConstruct() const{  return true;}// ECMA 15.4.2Object ArrayObjectImp::construct(ExecState *exec, const List &args){  // a single numeric argument denotes the array size (!)  if (args.size() == 1 && args[0].type() == NumberType) {    uint32_t n = args[0].toUInt32(exec);    if (n != args[0].toNumber(exec)) {      Object error = Error::create(exec, RangeError, "Array size is not a small enough positive integer.");      exec->setException(error);      return error;    }    return Object(new ArrayInstanceImp(exec->lexicalInterpreter()->builtinArrayPrototype().imp(), n));  }  // otherwise the array is constructed with the arguments in it  return Object(new ArrayInstanceImp(exec->lexicalInterpreter()->builtinArrayPrototype().imp(), args));}bool ArrayObjectImp::implementsCall() const{  return true;}// ECMA 15.6.1Value ArrayObjectImp::call(ExecState *exec, Object &/*thisObj*/, const List &args){  // equivalent to 'new Array(....)'  return construct(exec,args);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -