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

📄 jsobj.c

📁 java script test programing source code
💻 C
📖 第 1 页 / 共 5 页
字号:
}static JSHashEntry *MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap){    JSSharpObjectMap *map;    JSHashTable *table;    JSHashNumber hash;    JSHashEntry **hep, *he;    jsatomid sharpid;    JSIdArray *ida;    JSBool ok;    jsint i, length;    jsid id;#if JS_HAS_GETTER_SETTER    JSObject *obj2;    JSProperty *prop;    uintN attrs;#endif    jsval val;    int stackDummy;    if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) {        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED);        return NULL;    }    map = &cx->sharpObjectMap;    table = map->table;    hash = js_hash_object(obj);    hep = JS_HashTableRawLookup(table, hash, obj);    he = *hep;    if (!he) {        sharpid = 0;        he = JS_HashTableRawAdd(table, hep, hash, obj,                                JS_UINT32_TO_PTR(sharpid));        if (!he) {            JS_ReportOutOfMemory(cx);            return NULL;        }        /*         * Increment map->depth to protect js_EnterSharpObject from reentering         * itself badly.  Without this fix, if we reenter the basis case where         * map->depth == 0, when unwinding the inner call we will destroy the         * newly-created hash table and crash.         */        ++map->depth;        ida = JS_Enumerate(cx, obj);        --map->depth;        if (!ida)            return NULL;        ok = JS_TRUE;        for (i = 0, length = ida->length; i < length; i++) {            id = ida->vector[i];#if JS_HAS_GETTER_SETTER            ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop);            if (!ok)                break;            if (!prop)                continue;            ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs);            if (ok) {                if (OBJ_IS_NATIVE(obj2) &&                    (attrs & (JSPROP_GETTER | JSPROP_SETTER))) {                    val = JSVAL_NULL;                    if (attrs & JSPROP_GETTER)                        val = (jsval) ((JSScopeProperty*)prop)->getter;                    if (attrs & JSPROP_SETTER) {                        if (val != JSVAL_NULL) {                            /* Mark the getter, then set val to setter. */                            ok = (MarkSharpObjects(cx, JSVAL_TO_OBJECT(val),                                                   NULL)                                  != NULL);                        }                        val = (jsval) ((JSScopeProperty*)prop)->setter;                    }                } else {                    ok = OBJ_GET_PROPERTY(cx, obj, id, &val);                }            }            OBJ_DROP_PROPERTY(cx, obj2, prop);#else            ok = OBJ_GET_PROPERTY(cx, obj, id, &val);#endif            if (!ok)                break;            if (!JSVAL_IS_PRIMITIVE(val) &&                !MarkSharpObjects(cx, JSVAL_TO_OBJECT(val), NULL)) {                ok = JS_FALSE;                break;            }        }        if (!ok || !idap)            JS_DestroyIdArray(cx, ida);        if (!ok)            return NULL;    } else {        sharpid = JS_PTR_TO_UINT32(he->value);        if (sharpid == 0) {            sharpid = ++map->sharpgen << SHARP_ID_SHIFT;            he->value = JS_UINT32_TO_PTR(sharpid);        }        ida = NULL;    }    if (idap)        *idap = ida;    return he;}JSHashEntry *js_EnterSharpObject(JSContext *cx, JSObject *obj, JSIdArray **idap,                    jschar **sp){    JSSharpObjectMap *map;    JSHashTable *table;    JSIdArray *ida;    JSHashNumber hash;    JSHashEntry *he, **hep;    jsatomid sharpid;    char buf[20];    size_t len;    if (JS_HAS_NATIVE_BRANCH_CALLBACK_OPTION(cx) &&        cx->branchCallback &&        !cx->branchCallback(cx, NULL)) {        return NULL;    }    /* Set to null in case we return an early error. */    *sp = NULL;    map = &cx->sharpObjectMap;    table = map->table;    if (!table) {        table = JS_NewHashTable(8, js_hash_object, JS_CompareValues,                                JS_CompareValues, NULL, NULL);        if (!table) {            JS_ReportOutOfMemory(cx);            return NULL;        }        map->table = table;        JS_KEEP_ATOMS(cx->runtime);    }    /* From this point the control must flow either through out: or bad:. */    ida = NULL;    if (map->depth == 0) {        he = MarkSharpObjects(cx, obj, &ida);        if (!he)            goto bad;        JS_ASSERT((JS_PTR_TO_UINT32(he->value) & SHARP_BIT) == 0);        if (!idap) {            JS_DestroyIdArray(cx, ida);            ida = NULL;        }    } else {        hash = js_hash_object(obj);        hep = JS_HashTableRawLookup(table, hash, obj);        he = *hep;        /*         * It's possible that the value of a property has changed from the         * first time the object's properties are traversed (when the property         * ids are entered into the hash table) to the second (when they are         * converted to strings), i.e., the OBJ_GET_PROPERTY() call is not         * idempotent.         */        if (!he) {            he = JS_HashTableRawAdd(table, hep, hash, obj, NULL);            if (!he) {                JS_ReportOutOfMemory(cx);                goto bad;            }            sharpid = 0;            goto out;        }    }    sharpid = JS_PTR_TO_UINT32(he->value);    if (sharpid != 0) {        len = JS_snprintf(buf, sizeof buf, "#%u%c",                          sharpid >> SHARP_ID_SHIFT,                          (sharpid & SHARP_BIT) ? '#' : '=');        *sp = js_InflateString(cx, buf, &len);        if (!*sp) {            if (ida)                JS_DestroyIdArray(cx, ida);            goto bad;        }    }out:    JS_ASSERT(he);    if ((sharpid & SHARP_BIT) == 0) {        if (idap && !ida) {            ida = JS_Enumerate(cx, obj);            if (!ida) {                if (*sp) {                    JS_free(cx, *sp);                    *sp = NULL;                }                goto bad;            }        }        map->depth++;    }    if (idap)        *idap = ida;    return he;bad:    /* Clean up the sharpObjectMap table on outermost error. */    if (map->depth == 0) {        JS_UNKEEP_ATOMS(cx->runtime);        map->sharpgen = 0;        JS_HashTableDestroy(map->table);        map->table = NULL;    }    return NULL;}voidjs_LeaveSharpObject(JSContext *cx, JSIdArray **idap){    JSSharpObjectMap *map;    JSIdArray *ida;    map = &cx->sharpObjectMap;    JS_ASSERT(map->depth > 0);    if (--map->depth == 0) {        JS_UNKEEP_ATOMS(cx->runtime);        map->sharpgen = 0;        JS_HashTableDestroy(map->table);        map->table = NULL;    }    if (idap) {        ida = *idap;        if (ida) {            JS_DestroyIdArray(cx, ida);            *idap = NULL;        }    }}JS_STATIC_DLL_CALLBACK(intN)gc_sharp_table_entry_marker(JSHashEntry *he, intN i, void *arg){    GC_MARK((JSContext *)arg, (JSObject *)he->key, "sharp table entry");    return JS_DHASH_NEXT;}voidjs_GCMarkSharpMap(JSContext *cx, JSSharpObjectMap *map){    JS_ASSERT(map->depth > 0);    JS_ASSERT(map->table);    /*     * During recursive calls to MarkSharpObjects a non-native object or     * object with a custom getProperty method can potentially return an     * unrooted value or even cut from the object graph an argument of one of     * MarkSharpObjects recursive invocations. So we must protect map->table     * entries against GC.     *     * We can not simply use JSTempValueRooter to mark the obj argument of     * MarkSharpObjects during recursion as we have to protect *all* entries     * in JSSharpObjectMap including those that contains otherwise unreachable     * objects just allocated through custom getProperty. Otherwise newer     * allocations can re-use the address of an object stored in the hashtable     * confusing js_EnterSharpObject. So to address the problem we simply     * mark all objects from map->table.     *     * An alternative "proper" solution is to use JSTempValueRooter in     * MarkSharpObjects with code to remove during finalization entries     * with otherwise unreachable objects. But this is way too complex     * to justify spending efforts.     */    JS_HashTableEnumerateEntries(map->table, gc_sharp_table_entry_marker, cx);}#define OBJ_TOSTRING_EXTRA      4       /* for 4 local GC roots */#if JS_HAS_TOSOURCEJSBooljs_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,                jsval *rval){    JSBool ok, outermost;    JSHashEntry *he;    JSIdArray *ida;    jschar *chars, *ochars, *vsharp;    const jschar *idstrchars, *vchars;    size_t nchars, idstrlength, gsoplength, vlength, vsharplength, curlen;    char *comma;    jsint i, j, length, valcnt;    jsid id;#if JS_HAS_GETTER_SETTER    JSObject *obj2;    JSProperty *prop;    uintN attrs;#endif    jsval *val;    JSString *gsopold[2];    JSString *gsop[2];    JSAtom *atom;    JSString *idstr, *valstr, *str;    int stackDummy;    if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) {        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED);        return JS_FALSE;    }    /* If outermost, we need parentheses to be an expression, not a block. */    outermost = (cx->sharpObjectMap.depth == 0);    he = js_EnterSharpObject(cx, obj, &ida, &chars);    if (!he)        return JS_FALSE;    if (IS_SHARP(he)) {        /*         * We didn't enter -- obj is already "sharp", meaning we've visited it         * already in our depth first search, and therefore chars contains a         * string of the form "#n#".         */        JS_ASSERT(!ida);#if JS_HAS_SHARP_VARS        nchars = js_strlen(chars);#else        chars[0] = '{';        chars[1] = '}';        chars[2] = 0;        nchars = 2;#endif        goto make_string;    }    JS_ASSERT(ida);    ok = JS_TRUE;    if (!chars) {        /* If outermost, allocate 4 + 1 for "({})" and the terminator. */        chars = (jschar *) malloc(((outermost ? 4 : 2) + 1) * sizeof(jschar));        nchars = 0;        if (!chars)            goto error;        if (outermost)            chars[nchars++] = '(';    } else {        /* js_EnterSharpObject returned a string of the form "#n=" in chars. */        MAKE_SHARP(he);        nchars = js_strlen(chars);        chars = (jschar *)            realloc((ochars = chars), (nchars + 2 + 1) * sizeof(jschar));        if (!chars) {            free(ochars);            goto error;        }        if (outermost) {            /*             * No need for parentheses around the whole shebang, because #n=             * unambiguously begins an object initializer, and never a block             * statement.             */            outermost = JS_FALSE;        }    }#ifdef DUMP_CALL_TABLE    if (cx->options & JSOPTION_LOGCALL_TOSOURCE) {        const char *classname = OBJ_GET_CLASS(cx, obj)->name;        size_t classnchars = strlen(classname);        static const char classpropid[] = "C";        const char *cp;        size_t onchars = nchars;        /* 2 for ': ', 2 quotes around classname, 2 for ', ' after. */        classnchars += sizeof classpropid - 1 + 2 + 2;        if (ida->length)            classnchars += 2;        /* 2 for the braces, 1 for the terminator */        chars = (jschar *)            realloc((ochars = chars),                    (nchars + classnchars + 2 + 1) * sizeof(jschar));        if (!chars) {            free(ochars);            goto error;        }        chars[nchars++] = '{';          /* 1 from the 2 braces */        for (cp = classpropid; *cp; cp++)            chars[nchars++] = (jschar) *cp;        chars[nchars++] = ':';        chars[nchars++] = ' ';          /* 2 for ': ' */        chars[nchars++] = '"';        for (cp = classname; *cp; cp++)            chars[nchars++] = (jschar) *cp;        chars[nchars++] = '"';          /* 2 quotes */        if (ida->length) {            chars[nchars++] = ',';            chars[nchars++] = ' ';      /* 2 for ', ' */        }        JS_ASSERT(nchars - onchars == 1 + classnchars);    } else#endif    chars[nchars++] = '{';    comma = NULL;    /*     * We have four local roots for cooked and raw value GC safety.  Hoist the     * "argv + 2" out of the loop using the val local, which refers to the raw     * (unconverted, "uncooked") values.     */

⌨️ 快捷键说明

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