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 + -
显示快捷键?