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

📄 jsiter.c

📁 java script test programing source code
💻 C
📖 第 1 页 / 共 3 页
字号:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=78: * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** *//* * JavaScript iterators. */#include "jsstddef.h"#include <string.h>     /* for memcpy */#include "jstypes.h"#include "jsutil.h"#include "jsarena.h"#include "jsapi.h"#include "jsarray.h"#include "jsatom.h"#include "jsbool.h"#include "jscntxt.h"#include "jsconfig.h"#include "jsexn.h"#include "jsfun.h"#include "jsgc.h"#include "jsinterp.h"#include "jsiter.h"#include "jslock.h"#include "jsnum.h"#include "jsobj.h"#include "jsopcode.h"#include "jsscope.h"#include "jsscript.h"#if JS_HAS_XML_SUPPORT#include "jsxml.h"#endifextern const char js_throw_str[]; /* from jsscan.h */#define JSSLOT_ITER_STATE       (JSSLOT_PRIVATE)#define JSSLOT_ITER_FLAGS       (JSSLOT_PRIVATE + 1)#if JSSLOT_ITER_FLAGS >= JS_INITIAL_NSLOTS#error JS_INITIAL_NSLOTS must be greater than JSSLOT_ITER_FLAGS.#endif/* * Shared code to close iterator's state either through an explicit call or * when GC detects that the iterator is no longer reachable. */voidjs_CloseIteratorState(JSContext *cx, JSObject *iterobj){    jsval *slots;    jsval state, parent;    JSObject *iterable;    JS_ASSERT(JS_InstanceOf(cx, iterobj, &js_IteratorClass, NULL));    slots = iterobj->slots;    /* Avoid double work if js_CloseNativeIterator was called on obj. */    state = slots[JSSLOT_ITER_STATE];    if (JSVAL_IS_NULL(state))        return;    /* Protect against failure to fully initialize obj. */    parent = slots[JSSLOT_PARENT];    if (!JSVAL_IS_PRIMITIVE(parent)) {        iterable = JSVAL_TO_OBJECT(parent);#if JS_HAS_XML_SUPPORT        if ((JSVAL_TO_INT(slots[JSSLOT_ITER_FLAGS]) & JSITER_FOREACH) &&            OBJECT_IS_XML(cx, iterable)) {            ((JSXMLObjectOps *) iterable->map->ops)->                enumerateValues(cx, iterable, JSENUMERATE_DESTROY, &state,                                NULL, NULL);        } else#endif            OBJ_ENUMERATE(cx, iterable, JSENUMERATE_DESTROY, &state, NULL);    }    slots[JSSLOT_ITER_STATE] = JSVAL_NULL;}JSClass js_IteratorClass = {    "Iterator",    JSCLASS_HAS_RESERVED_SLOTS(2) | /* slots for state and flags */    JSCLASS_HAS_CACHED_PROTO(JSProto_Iterator),    JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,    JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   JS_FinalizeStub,    JSCLASS_NO_OPTIONAL_MEMBERS};static JSBoolInitNativeIterator(JSContext *cx, JSObject *iterobj, JSObject *obj, uintN flags){    jsval state;    JSBool ok;    JS_ASSERT(JSVAL_TO_PRIVATE(iterobj->slots[JSSLOT_CLASS]) ==              &js_IteratorClass);    /* Initialize iterobj in case of enumerate hook failure. */    iterobj->slots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(obj);    iterobj->slots[JSSLOT_ITER_STATE] = JSVAL_NULL;    iterobj->slots[JSSLOT_ITER_FLAGS] = INT_TO_JSVAL(flags);    if (!js_RegisterCloseableIterator(cx, iterobj))        return JS_FALSE;    if (!obj)        return JS_TRUE;    ok =#if JS_HAS_XML_SUPPORT         ((flags & JSITER_FOREACH) && OBJECT_IS_XML(cx, obj))         ? ((JSXMLObjectOps *) obj->map->ops)->               enumerateValues(cx, obj, JSENUMERATE_INIT, &state, NULL, NULL)         :#endif           OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &state, NULL);    if (!ok)        return JS_FALSE;    iterobj->slots[JSSLOT_ITER_STATE] = state;    if (flags & JSITER_ENUMERATE) {        /*         * The enumerating iterator needs the original object to suppress         * enumeration of deleted or shadowed prototype properties. Since the         * enumerator never escapes to scripts, we use the prototype slot to         * store the original object.         */        JS_ASSERT(obj != iterobj);        iterobj->slots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(obj);    }    return JS_TRUE;}static JSBoolIterator(JSContext *cx, JSObject *iterobj, uintN argc, jsval *argv, jsval *rval){    JSBool keyonly;    uintN flags;    JSObject *obj;    keyonly = JS_FALSE;    if (!js_ValueToBoolean(cx, argv[1], &keyonly))        return JS_FALSE;    flags = keyonly ? 0 : JSITER_FOREACH;    if (cx->fp->flags & JSFRAME_CONSTRUCTING) {        /* XXX work around old valueOf call hidden beneath js_ValueToObject */        if (!JSVAL_IS_PRIMITIVE(argv[0])) {            obj = JSVAL_TO_OBJECT(argv[0]);        } else {            obj = js_ValueToNonNullObject(cx, argv[0]);            if (!obj)                return JS_FALSE;            argv[0] = OBJECT_TO_JSVAL(obj);        }        return InitNativeIterator(cx, iterobj, obj, flags);    }    *rval = argv[0];    return js_ValueToIterator(cx, flags, rval);}static JSBoolNewKeyValuePair(JSContext *cx, jsid key, jsval val, jsval *rval){    jsval vec[2];    JSTempValueRooter tvr;    JSObject *aobj;    vec[0] = ID_TO_VALUE(key);    vec[1] = val;    JS_PUSH_TEMP_ROOT(cx, 2, vec, &tvr);    aobj = js_NewArrayObject(cx, 2, vec);    *rval = OBJECT_TO_JSVAL(aobj);    JS_POP_TEMP_ROOT(cx, &tvr);    return aobj != NULL;}static JSBoolIteratorNextImpl(JSContext *cx, JSObject *obj, jsval *rval){    JSObject *iterable;    jsval state;    uintN flags;    JSBool foreach, ok;    jsid id;    JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_IteratorClass);    iterable = OBJ_GET_PARENT(cx, obj);    JS_ASSERT(iterable);    state = OBJ_GET_SLOT(cx, obj, JSSLOT_ITER_STATE);    if (JSVAL_IS_NULL(state))        goto stop;    flags = JSVAL_TO_INT(OBJ_GET_SLOT(cx, obj, JSSLOT_ITER_FLAGS));    JS_ASSERT(!(flags & JSITER_ENUMERATE));    foreach = (flags & JSITER_FOREACH) != 0;    ok =#if JS_HAS_XML_SUPPORT         (foreach && OBJECT_IS_XML(cx, iterable))         ? ((JSXMLObjectOps *) iterable->map->ops)->               enumerateValues(cx, iterable, JSENUMERATE_NEXT, &state,                               &id, rval)         :#endif           OBJ_ENUMERATE(cx, iterable, JSENUMERATE_NEXT, &state, &id);    if (!ok)        return JS_FALSE;    OBJ_SET_SLOT(cx, obj, JSSLOT_ITER_STATE, state);    if (JSVAL_IS_NULL(state))        goto stop;    if (foreach) {#if JS_HAS_XML_SUPPORT        if (!OBJECT_IS_XML(cx, iterable) &&            !OBJ_GET_PROPERTY(cx, iterable, id, rval)) {            return JS_FALSE;        }#endif        if (!NewKeyValuePair(cx, id, *rval, rval))            return JS_FALSE;    } else {        *rval = ID_TO_VALUE(id);    }    return JS_TRUE;  stop:    JS_ASSERT(OBJ_GET_SLOT(cx, obj, JSSLOT_ITER_STATE) == JSVAL_NULL);    *rval = JSVAL_HOLE;    return JS_TRUE;}static JSBooljs_ThrowStopIteration(JSContext *cx, JSObject *obj){    jsval v;    JS_ASSERT(!JS_IsExceptionPending(cx));    if (js_FindClassObject(cx, NULL, INT_TO_JSID(JSProto_StopIteration), &v))        JS_SetPendingException(cx, v);    return JS_FALSE;}static JSBooliterator_next(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,              jsval *rval){    if (!JS_InstanceOf(cx, obj, &js_IteratorClass, argv))        return JS_FALSE;    if (!IteratorNextImpl(cx, obj, rval))        return JS_FALSE;    if (*rval == JSVAL_HOLE) {        *rval = JSVAL_NULL;        js_ThrowStopIteration(cx, obj);        return JS_FALSE;    }    return JS_TRUE;}static JSBooliterator_self(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,              jsval *rval){    *rval = OBJECT_TO_JSVAL(obj);    return JS_TRUE;}static JSFunctionSpec iterator_methods[] = {    {js_iterator_str, iterator_self, 0,JSPROP_READONLY|JSPROP_PERMANENT,0},    {js_next_str,     iterator_next, 0,JSPROP_READONLY|JSPROP_PERMANENT,0},    {0,0,0,0,0}};uintNjs_GetNativeIteratorFlags(JSContext *cx, JSObject *iterobj){    if (OBJ_GET_CLASS(cx, iterobj) != &js_IteratorClass)        return 0;    return JSVAL_TO_INT(OBJ_GET_SLOT(cx, iterobj, JSSLOT_ITER_FLAGS));}voidjs_CloseNativeIterator(JSContext *cx, JSObject *iterobj){    uintN flags;    /*     * If this iterator is not an instance of the native default iterator     * class, leave it to be GC'ed.     */    if (!JS_InstanceOf(cx, iterobj, &js_IteratorClass, NULL))        return;    /*     * If this iterator was not created by js_ValueToIterator called from the     * for-in loop code in js_Interpret, leave it to be GC'ed.     */    flags = JSVAL_TO_INT(OBJ_GET_SLOT(cx, iterobj, JSSLOT_ITER_FLAGS));    if (!(flags & JSITER_ENUMERATE))        return;    js_CloseIteratorState(cx, iterobj);}/* * Call ToObject(v).__iterator__(keyonly) if ToObject(v).__iterator__ exists. * Otherwise construct the defualt iterator. */JSBooljs_ValueToIterator(JSContext *cx, uintN flags, jsval *vp){    JSObject *obj;    JSTempValueRooter tvr;    const JSAtom *atom;    JSBool ok;    JSObject *iterobj;    jsval arg;    JSString *str;    JS_ASSERT(!(flags & ~(JSITER_ENUMERATE |                          JSITER_FOREACH |

⌨️ 快捷键说明

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