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

📄 arrayprototype.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org) *  Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved. *  Copyright (C) 2003 Peter Kelly (pmk@post.com) *  Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) * *  This library is free software; you can redistribute it and/or *  modify it under the terms of the GNU Lesser General Public *  License as published by the Free Software Foundation; either *  version 2 of the License, or (at your option) any later version. * *  This library is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *  Lesser General Public License for more details. * *  You should have received a copy of the GNU Lesser General Public *  License along with this library; if not, write to the Free Software *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 *  USA * */#include "config.h"#include "ArrayPrototype.h"#include "CodeBlock.h"#include "Interpreter.h"#include "JIT.h"#include "ObjectPrototype.h"#include "Lookup.h"#include "Operations.h"#include <algorithm>#include <wtf/Assertions.h>#include <wtf/HashSet.h>namespace JSC {ASSERT_CLASS_FITS_IN_CELL(ArrayPrototype);static JSValuePtr arrayProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr arrayProtoFuncToLocaleString(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr arrayProtoFuncConcat(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr arrayProtoFuncJoin(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr arrayProtoFuncPop(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr arrayProtoFuncPush(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr arrayProtoFuncReverse(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr arrayProtoFuncShift(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr arrayProtoFuncSlice(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr arrayProtoFuncSort(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr arrayProtoFuncSplice(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr arrayProtoFuncUnShift(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr arrayProtoFuncEvery(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr arrayProtoFuncForEach(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr arrayProtoFuncSome(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr arrayProtoFuncIndexOf(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr arrayProtoFuncFilter(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr arrayProtoFuncMap(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr arrayProtoFuncLastIndexOf(ExecState*, JSObject*, JSValuePtr, const ArgList&);}#include "ArrayPrototype.lut.h"namespace JSC {static inline bool isNumericCompareFunction(CallType callType, const CallData& callData){    if (callType != CallTypeJS)        return false;    CodeBlock& codeBlock = callData.js.functionBody->bytecode(callData.js.scopeChain);#if ENABLE(JIT)    // If the JIT is enabled then we need to preserve the invariant that every    // function with a CodeBlock also has JIT code.    if (!codeBlock.jitCode())        JIT::compile(callData.js.scopeChain->globalData, &codeBlock);#endif    return codeBlock.isNumericCompareFunction();}// ------------------------------ ArrayPrototype ----------------------------const ClassInfo ArrayPrototype::info = {"Array", &JSArray::info, 0, ExecState::arrayTable};/* Source for ArrayPrototype.lut.h@begin arrayTable 16  toString       arrayProtoFuncToString       DontEnum|Function 0  toLocaleString arrayProtoFuncToLocaleString DontEnum|Function 0  concat         arrayProtoFuncConcat         DontEnum|Function 1  join           arrayProtoFuncJoin           DontEnum|Function 1  pop            arrayProtoFuncPop            DontEnum|Function 0  push           arrayProtoFuncPush           DontEnum|Function 1  reverse        arrayProtoFuncReverse        DontEnum|Function 0  shift          arrayProtoFuncShift          DontEnum|Function 0  slice          arrayProtoFuncSlice          DontEnum|Function 2  sort           arrayProtoFuncSort           DontEnum|Function 1  splice         arrayProtoFuncSplice         DontEnum|Function 2  unshift        arrayProtoFuncUnShift        DontEnum|Function 1  every          arrayProtoFuncEvery          DontEnum|Function 1  forEach        arrayProtoFuncForEach        DontEnum|Function 1  some           arrayProtoFuncSome           DontEnum|Function 1  indexOf        arrayProtoFuncIndexOf        DontEnum|Function 1  lastIndexOf    arrayProtoFuncLastIndexOf    DontEnum|Function 1  filter         arrayProtoFuncFilter         DontEnum|Function 1  map            arrayProtoFuncMap            DontEnum|Function 1@end*/// ECMA 15.4.4ArrayPrototype::ArrayPrototype(PassRefPtr<Structure> structure)    : JSArray(structure){}bool ArrayPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot){    return getStaticFunctionSlot<JSArray>(exec, ExecState::arrayTable(exec), this, propertyName, slot);}// ------------------------------ Array Functions ----------------------------// Helper functionstatic JSValuePtr getProperty(ExecState* exec, JSObject* obj, unsigned index){    PropertySlot slot(obj);    if (!obj->getPropertySlot(exec, index, slot))        return noValue();    return slot.getValue(exec, index);}static void putProperty(ExecState* exec, JSObject* obj, const Identifier& propertyName, JSValuePtr value){    PutPropertySlot slot;    obj->put(exec, propertyName, value, slot);}JSValuePtr arrayProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&){    if (!thisValue.isObject(&JSArray::info))        return throwError(exec, TypeError);    JSObject* thisObj = asArray(thisValue);    HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;    if (arrayVisitedElements.size() > MaxReentryDepth)        return throwError(exec, RangeError, "Maximum call stack size exceeded.");    bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;    if (alreadyVisited)        return jsEmptyString(exec); // return an empty string, avoiding infinite recursion.    Vector<UChar, 256> strBuffer;    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);    for (unsigned k = 0; k < length; k++) {        if (k >= 1)            strBuffer.append(',');        if (!strBuffer.data()) {            JSObject* error = Error::create(exec, GeneralError, "Out of memory");            exec->setException(error);            break;        }        JSValuePtr element = thisObj->get(exec, k);        if (element.isUndefinedOrNull())            continue;        UString str = element.toString(exec);        strBuffer.append(str.data(), str.size());        if (!strBuffer.data()) {            JSObject* error = Error::create(exec, GeneralError, "Out of memory");            exec->setException(error);        }        if (exec->hadException())            break;    }    arrayVisitedElements.remove(thisObj);    return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));}JSValuePtr arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&){    if (!thisValue.isObject(&JSArray::info))        return throwError(exec, TypeError);    JSObject* thisObj = asArray(thisValue);    HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;    if (arrayVisitedElements.size() > MaxReentryDepth)        return throwError(exec, RangeError, "Maximum call stack size exceeded.");    bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;    if (alreadyVisited)        return jsEmptyString(exec); // return an empty string, avoding infinite recursion.    Vector<UChar, 256> strBuffer;    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);    for (unsigned k = 0; k < length; k++) {        if (k >= 1)            strBuffer.append(',');        if (!strBuffer.data()) {            JSObject* error = Error::create(exec, GeneralError, "Out of memory");            exec->setException(error);            break;        }        JSValuePtr element = thisObj->get(exec, k);        if (element.isUndefinedOrNull())            continue;        JSObject* o = element.toObject(exec);        JSValuePtr conversionFunction = o->get(exec, exec->propertyNames().toLocaleString);        UString str;        CallData callData;        CallType callType = conversionFunction.getCallData(callData);        if (callType != CallTypeNone)            str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec);        else            str = element.toString(exec);        strBuffer.append(str.data(), str.size());        if (!strBuffer.data()) {            JSObject* error = Error::create(exec, GeneralError, "Out of memory");            exec->setException(error);        }        if (exec->hadException())            break;    }    arrayVisitedElements.remove(thisObj);    return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));}JSValuePtr arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args){    JSObject* thisObj = thisValue.toThisObject(exec);    HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;    if (arrayVisitedElements.size() > MaxReentryDepth)        return throwError(exec, RangeError, "Maximum call stack size exceeded.");    bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;    if (alreadyVisited)        return jsEmptyString(exec); // return an empty string, avoding infinite recursion.    Vector<UChar, 256> strBuffer;    UChar comma = ',';    UString separator = args.at(exec, 0).isUndefined() ? UString(&comma, 1) : args.at(exec, 0).toString(exec);    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);    for (unsigned k = 0; k < length; k++) {        if (k >= 1)            strBuffer.append(separator.data(), separator.size());        if (!strBuffer.data()) {            JSObject* error = Error::create(exec, GeneralError, "Out of memory");            exec->setException(error);            break;        }        JSValuePtr element = thisObj->get(exec, k);        if (element.isUndefinedOrNull())            continue;        UString str = element.toString(exec);        strBuffer.append(str.data(), str.size());        if (!strBuffer.data()) {            JSObject* error = Error::create(exec, GeneralError, "Out of memory");            exec->setException(error);        }        if (exec->hadException())            break;    }    arrayVisitedElements.remove(thisObj);    return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));}JSValuePtr arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args){    JSArray* arr = constructEmptyArray(exec);    int n = 0;    JSValuePtr curArg = thisValue.toThisObject(exec);    ArgList::const_iterator it = args.begin();    ArgList::const_iterator end = args.end();    while (1) {        if (curArg.isObject(&JSArray::info)) {            unsigned length = curArg.get(exec, exec->propertyNames().length).toUInt32(exec);            JSObject* curObject = curArg.toObject(exec);            for (unsigned k = 0; k < length; ++k) {                if (JSValuePtr v = getProperty(exec, curObject, k))                    arr->put(exec, n, v);                n++;            }        } else {            arr->put(exec, n, curArg);            n++;        }        if (it == end)            break;        curArg = (*it).jsValue(exec);        ++it;    }    arr->setLength(n);    return arr;}JSValuePtr arrayProtoFuncPop(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&){    if (isJSArray(&exec->globalData(), thisValue))        return asArray(thisValue)->pop();    JSObject* thisObj = thisValue.toThisObject(exec);    JSValuePtr result;    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);    if (length == 0) {        putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length));        result = jsUndefined();    } else {        result = thisObj->get(exec, length - 1);        thisObj->deleteProperty(exec, length - 1);        putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length - 1));    }    return result;}JSValuePtr arrayProtoFuncPush(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args){    if (isJSArray(&exec->globalData(), thisValue) && args.size() == 1) {        JSArray* array = asArray(thisValue);        array->push(exec, args.begin()->jsValue(exec));        return jsNumber(exec, array->length());    }    JSObject* thisObj = thisValue.toThisObject(exec);    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);    for (unsigned n = 0; n < args.size(); n++)        thisObj->put(exec, length + n, args.at(exec, n));    length += args.size();    putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length));    return jsNumber(exec, length);}JSValuePtr arrayProtoFuncReverse(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&){    JSObject* thisObj = thisValue.toThisObject(exec);    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);    unsigned middle = length / 2;    for (unsigned k = 0; k < middle; k++) {        unsigned lk1 = length - k - 1;        JSValuePtr obj2 = getProperty(exec, thisObj, lk1);        JSValuePtr obj = getProperty(exec, thisObj, k);        if (obj2)            thisObj->put(exec, k, obj2);        else            thisObj->deleteProperty(exec, k);        if (obj)            thisObj->put(exec, lk1, obj);        else            thisObj->deleteProperty(exec, lk1);    }    return thisObj;}JSValuePtr arrayProtoFuncShift(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&){    JSObject* thisObj = thisValue.toThisObject(exec);    JSValuePtr result;    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);    if (length == 0) {        putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length));        result = jsUndefined();    } else {        result = thisObj->get(exec, 0);        for (unsigned k = 1; k < length; k++) {            if (JSValuePtr obj = getProperty(exec, thisObj, k))                thisObj->put(exec, k - 1, obj);            else                thisObj->deleteProperty(exec, k - 1);        }        thisObj->deleteProperty(exec, length - 1);        putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length - 1));    }    return result;}JSValuePtr arrayProtoFuncSlice(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args){    // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10    JSObject* thisObj = thisValue.toThisObject(exec);    // We return a new array    JSArray* resObj = constructEmptyArray(exec);    JSValuePtr result = resObj;    double begin = args.at(exec, 0).toInteger(exec);    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);    if (begin >= 0) {        if (begin > length)            begin = length;    } else {        begin += length;

⌨️ 快捷键说明

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