jsarray.c

来自「java script test programing source code」· C语言 代码 · 共 1,865 行 · 第 1/4 页

C
1,865
字号
                                      vp)) {                    return JS_FALSE;                }                if (!ValueIsLength(cx, *vp, &alength))                    return JS_FALSE;                for (slot = 0; slot < alength; slot++) {                    if (!GetArrayElement(cx, aobj, slot, &hole, vp))                        return JS_FALSE;                    /*                     * Per ECMA 262, 15.4.4.4, step 9, ignore non-existent                     * properties.                     */                    if (!hole && !SetArrayElement(cx, nobj, length + slot, *vp))                        return JS_FALSE;                }                length += alength;                continue;            }        }        if (!SetArrayElement(cx, nobj, length, v))            return JS_FALSE;        length++;    }    return js_SetLengthProperty(cx, nobj, length);}static JSBoolarray_slice(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    jsval *vp;    JSObject *nobj;    jsuint length, begin, end, slot;    jsdouble d;    JSBool hole;    /* Hoist the explicit local root address computation. */    vp = argv + argc;    /* Create a new Array object and store it in the rval local root. */    nobj = js_NewArrayObject(cx, 0, NULL);    if (!nobj)        return JS_FALSE;    *rval = OBJECT_TO_JSVAL(nobj);    if (!js_GetLengthProperty(cx, obj, &length))        return JS_FALSE;    begin = 0;    end = length;    if (argc > 0) {        if (!js_ValueToNumber(cx, argv[0], &d))            return JS_FALSE;        d = js_DoubleToInteger(d);        if (d < 0) {            d += length;            if (d < 0)                d = 0;        } else if (d > length) {            d = length;        }        begin = (jsuint)d;        if (argc > 1) {            if (!js_ValueToNumber(cx, argv[1], &d))                return JS_FALSE;            d = js_DoubleToInteger(d);            if (d < 0) {                d += length;                if (d < 0)                    d = 0;            } else if (d > length) {                d = length;            }            end = (jsuint)d;        }    }    if (begin > end)        begin = end;    for (slot = begin; slot < end; slot++) {        if (!GetArrayElement(cx, obj, slot, &hole, vp))            return JS_FALSE;        if (!hole && !SetArrayElement(cx, nobj, slot - begin, *vp))            return JS_FALSE;    }    return js_SetLengthProperty(cx, nobj, end - begin);}#if JS_HAS_ARRAY_EXTRASstatic JSBoolarray_indexOfHelper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,                    jsval *rval, JSBool isLast){    jsuint length, i, stop;    jsint direction;    JSBool hole;    if (!js_GetLengthProperty(cx, obj, &length))        return JS_FALSE;    if (length == 0)        goto not_found;    if (argc <= 1) {        i = isLast ? length - 1 : 0;    } else {        jsdouble start;        if (!js_ValueToNumber(cx, argv[1], &start))            return JS_FALSE;        start = js_DoubleToInteger(start);        if (start < 0) {            start += length;            if (start < 0) {                if (isLast)                    goto not_found;                i = 0;            } else {                i = (jsuint)start;            }        } else if (start >= length) {            if (!isLast)                goto not_found;            i = length - 1;        } else {            i = (jsuint)start;        }    }    if (isLast) {        stop = 0;        direction = -1;    } else {        stop = length - 1;        direction = 1;    }    for (;;) {        if (!GetArrayElement(cx, obj, (jsuint)i, &hole, rval))            return JS_FALSE;        if (!hole && js_StrictlyEqual(*rval, argv[0]))            return js_NewNumberValue(cx, i, rval);        if (i == stop)            goto not_found;        i += direction;    }  not_found:    *rval = INT_TO_JSVAL(-1);    return JS_TRUE;}static JSBoolarray_indexOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,              jsval *rval){    return array_indexOfHelper(cx, obj, argc, argv, rval, JS_FALSE);}static JSBoolarray_lastIndexOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,                  jsval *rval){    return array_indexOfHelper(cx, obj, argc, argv, rval, JS_TRUE);}/* Order is important; extras that use a caller's predicate must follow MAP. */typedef enum ArrayExtraMode {    FOREACH,    MAP,    FILTER,    SOME,    EVERY} ArrayExtraMode;static JSBoolarray_extra(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval,            ArrayExtraMode mode){    jsval *vp, *sp, *origsp, *oldsp;    jsuint length, newlen, i;    JSObject *callable, *thisp, *newarr;    void *mark;    JSStackFrame *fp;    JSBool ok, cond, hole;    /* Hoist the explicit local root address computation. */    vp = argv + argc;    if (!js_GetLengthProperty(cx, obj, &length))        return JS_FALSE;    /*     * First, get or compute our callee, so that we error out consistently     * when passed a non-callable object.     */    callable = js_ValueToCallableObject(cx, &argv[0], JSV2F_SEARCH_STACK);    if (!callable)        return JS_FALSE;    /*     * Set our initial return condition, used for zero-length array cases     * (and pre-size our map return to match our known length, for all cases).     */#ifdef __GNUC__ /* quell GCC overwarning */    newlen = 0;    newarr = NULL;    ok = JS_TRUE;#endif    switch (mode) {      case MAP:      case FILTER:        newlen = (mode == MAP) ? length : 0;        newarr = js_NewArrayObject(cx, newlen, NULL);        if (!newarr)            return JS_FALSE;        *rval = OBJECT_TO_JSVAL(newarr);        break;      case SOME:        *rval = JSVAL_FALSE;        break;      case EVERY:        *rval = JSVAL_TRUE;        break;      case FOREACH:        break;    }    if (length == 0)        return JS_TRUE;    if (argc > 1) {        if (!js_ValueToObject(cx, argv[1], &thisp))            return JS_FALSE;        argv[1] = OBJECT_TO_JSVAL(thisp);    } else {        thisp = NULL;    }    /* We call with 3 args (value, index, array), plus room for rval. */    origsp = js_AllocStack(cx, 2 + 3 + 1, &mark);    if (!origsp)        return JS_FALSE;    /* Lift current frame to include our args. */    fp = cx->fp;    oldsp = fp->sp;    for (i = 0; i < length; i++) {        ok = GetArrayElement(cx, obj, i, &hole, vp);        if (!ok)            break;        if (hole)            continue;        /*         * Push callable and 'this', then args. We must do this for every         * iteration around the loop since js_Invoke uses origsp[0] for rval         * storage and some native functions use origsp[1] for local rooting.         */        sp = origsp;        *sp++ = OBJECT_TO_JSVAL(callable);        *sp++ = OBJECT_TO_JSVAL(thisp);        *sp++ = *vp;        *sp++ = INT_TO_JSVAL(i);        *sp++ = OBJECT_TO_JSVAL(obj);        /* Do the call. */        fp->sp = sp;        ok = js_Invoke(cx, 3, JSINVOKE_INTERNAL);        vp[1] = fp->sp[-1];        fp->sp = oldsp;        if (!ok)            break;        if (mode > MAP) {            if (vp[1] == JSVAL_NULL) {                cond = JS_FALSE;            } else if (JSVAL_IS_BOOLEAN(vp[1])) {                cond = JSVAL_TO_BOOLEAN(vp[1]);            } else {                ok = js_ValueToBoolean(cx, vp[1], &cond);                if (!ok)                    goto out;            }        }        switch (mode) {          case FOREACH:            break;          case MAP:            ok = SetArrayElement(cx, newarr, i, vp[1]);            if (!ok)                goto out;            break;          case FILTER:            if (!cond)                break;            /* Filter passed *vp, push as result. */            ok = SetArrayElement(cx, newarr, newlen++, *vp);            if (!ok)                goto out;            break;          case SOME:            if (cond) {                *rval = JSVAL_TRUE;                goto out;            }            break;          case EVERY:            if (!cond) {                *rval = JSVAL_FALSE;                goto out;            }            break;        }    } out:    js_FreeStack(cx, mark);    if (ok && mode == FILTER)        ok = js_SetLengthProperty(cx, newarr, newlen);    return ok;}static JSBoolarray_forEach(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,              jsval *rval){    return array_extra(cx, obj, argc, argv, rval, FOREACH);}static JSBoolarray_map(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,          jsval *rval){    return array_extra(cx, obj, argc, argv, rval, MAP);}static JSBoolarray_filter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,             jsval *rval){    return array_extra(cx, obj, argc, argv, rval, FILTER);}static JSBoolarray_some(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,           jsval *rval){    return array_extra(cx, obj, argc, argv, rval, SOME);}static JSBoolarray_every(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,           jsval *rval){    return array_extra(cx, obj, argc, argv, rval, EVERY);}#endifstatic JSFunctionSpec array_methods[] = {#if JS_HAS_TOSOURCE    {js_toSource_str,       array_toSource,         0,0,0},#endif    {js_toString_str,       array_toString,         0,0,0},    {js_toLocaleString_str, array_toLocaleString,   0,0,0},    /* Perl-ish methods. */    {"join",                array_join,             1,JSFUN_GENERIC_NATIVE,0},    {"reverse",             array_reverse,          0,JSFUN_GENERIC_NATIVE,2},    {"sort",                array_sort,             1,JSFUN_GENERIC_NATIVE,2},    {"push",                array_push,             1,JSFUN_GENERIC_NATIVE,0},    {"pop",                 array_pop,              0,JSFUN_GENERIC_NATIVE,0},    {"shift",               array_shift,            0,JSFUN_GENERIC_NATIVE,1},    {"unshift",             array_unshift,          1,JSFUN_GENERIC_NATIVE,1},    {"splice",              array_splice,           2,JSFUN_GENERIC_NATIVE,1},    /* Python-esque sequence methods. */    {"concat",              array_concat,           1,JSFUN_GENERIC_NATIVE,1},    {"slice",               array_slice,            2,JSFUN_GENERIC_NATIVE,1},#if JS_HAS_ARRAY_EXTRAS    {"indexOf",             array_indexOf,          1,JSFUN_GENERIC_NATIVE,0},    {"lastIndexOf",         array_lastIndexOf,      1,JSFUN_GENERIC_NATIVE,0},    {"forEach",             array_forEach,          1,JSFUN_GENERIC_NATIVE,2},    {"map",                 array_map,              1,JSFUN_GENERIC_NATIVE,2},    {"filter",              array_filter,           1,JSFUN_GENERIC_NATIVE,2},    {"some",                array_some,             1,JSFUN_GENERIC_NATIVE,2},    {"every",               array_every,            1,JSFUN_GENERIC_NATIVE,2},#endif    {0,0,0,0,0}};static JSBoolArray(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    jsuint length;    jsval *vector;    /* If called without new, replace obj with a new Array object. */    if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {        obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL);        if (!obj)            return JS_FALSE;        *rval = OBJECT_TO_JSVAL(obj);    }    if (argc == 0) {        length = 0;        vector = NULL;    } else if (argc > 1) {        length = (jsuint) argc;        vector = argv;    } else if (!JSVAL_IS_NUMBER(argv[0])) {        length = 1;        vector = argv;    } else {        if (!ValueIsLength(cx, argv[0], &length))            return JS_FALSE;        vector = NULL;    }    return InitArrayObject(cx, obj, length, vector);}JSObject *js_InitArrayClass(JSContext *cx, JSObject *obj){    JSObject *proto;    proto = JS_InitClass(cx, obj, NULL, &js_ArrayClass, Array, 1,                         NULL, array_methods, NULL, NULL);    /* Initialize the Array prototype object so it gets a length property. */    if (!proto || !InitArrayObject(cx, proto, 0, NULL))        return NULL;    return proto;}JSObject *js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector){    JSTempValueRooter tvr;    JSObject *obj;    obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL);    if (!obj)        return NULL;    JS_PUSH_TEMP_ROOT_OBJECT(cx, obj, &tvr);    if (!InitArrayObject(cx, obj, length, vector))        obj = NULL;    JS_POP_TEMP_ROOT(cx, &tvr);    /* Set/clear newborn root, in case we lost it.  */    cx->weakRoots.newborn[GCX_OBJECT] = (JSGCThing *) obj;    return obj;}

⌨️ 快捷键说明

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