📄 jsobj.c
字号:
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; /* 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; } ida = NULL; if (map->depth == 0) { he = MarkSharpObjects(cx, obj, &ida); if (!he) goto bad; JS_ASSERT (!IS_SHARP (he)); 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; } *sp = NULL; sharpid = 0; goto out; } } sharpid = JS_PTR_TO_UINT32(he->value); if (sharpid == 0) { *sp = NULL; } else { 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) { 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) { map->sharpgen = 0; JS_HashTableDestroy(map->table); map->table = NULL; } if (idap) { ida = *idap; if (ida) { JS_DestroyIdArray(cx, ida); *idap = NULL; } }}#define OBJ_TOSTRING_EXTRA 3 /* for 3 local GC roots */#if JS_HAS_INITIALIZERS || 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; char *comma; jsint i, j, length, valcnt; jsid id;#if JS_HAS_GETTER_SETTER JSObject *obj2; JSProperty *prop; uintN attrs;#endif jsval val[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; } /* * obj_toString for 1.2 calls toSource, and doesn't want the extra parens * on the outside. */ outermost = (cx->version != JSVERSION_1_2 && 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; } } chars[nchars++] = '{'; comma = NULL; for (i = 0, length = ida->length; i < length; i++) { /* Get strings for id and value and GC-root them via argv. */ id = ida->vector[i];#if JS_HAS_GETTER_SETTER ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop); if (!ok) goto error; valcnt = 0; if (prop) { ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs); if (!ok) { OBJ_DROP_PROPERTY(cx, obj2, prop); goto error; } if (OBJ_IS_NATIVE(obj2) && (attrs & (JSPROP_GETTER | JSPROP_SETTER))) { if (attrs & JSPROP_GETTER) { val[valcnt] = (jsval) ((JSScopeProperty *)prop)->getter;#ifdef OLD_GETTER_SETTER gsop[valcnt] = ATOM_TO_STRING(cx->runtime->atomState.getterAtom);#else gsop[valcnt] = ATOM_TO_STRING(cx->runtime->atomState.getAtom);#endif valcnt++; } if (attrs & JSPROP_SETTER) { val[valcnt] = (jsval) ((JSScopeProperty *)prop)->setter;#ifdef OLD_GETTER_SETTER gsop[valcnt] = ATOM_TO_STRING(cx->runtime->atomState.setterAtom);#else gsop[valcnt] = ATOM_TO_STRING(cx->runtime->atomState.setAtom);#endif valcnt++; } } else { valcnt = 1; gsop[0] = NULL; ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]); } OBJ_DROP_PROPERTY(cx, obj2, prop); }#else /* !JS_HAS_GETTER_SETTER */ valcnt = 1; gsop[0] = NULL; ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]);#endif /* !JS_HAS_GETTER_SETTER */ if (!ok) goto error; /* Convert id to a jsval and then to a string. */ atom = JSVAL_IS_INT(id) ? NULL : (JSAtom *)id; id = ID_TO_VALUE(id); idstr = js_ValueToString(cx, id); if (!idstr) { ok = JS_FALSE; goto error; } argv[0] = STRING_TO_JSVAL(idstr); /* * If id is a string that's a reserved identifier, or else id is not * an identifier at all, then it needs to be quoted. Also, negative * integer ids must be quoted. */ if (atom ? (ATOM_KEYWORD(atom) || !js_IsIdentifier(idstr)) : JSVAL_TO_INT(id) < 0) { idstr = js_QuoteString(cx, idstr, (jschar)'\''); if (!idstr) { ok = JS_FALSE; goto error; } argv[0] = STRING_TO_JSVAL(idstr); } idstrchars = JSSTRING_CHARS(idstr); idstrlength = JSSTRING_LENGTH(idstr); for (j = 0; j < valcnt; j++) { /* Convert val[j] to its canonical source form. */ valstr = js_ValueToSource(cx, val[j]); if (!valstr) { ok = JS_FALSE; goto error; } argv[1+j] = STRING_TO_JSVAL(valstr); vchars = JSSTRING_CHARS(valstr); vlength = JSSTRING_LENGTH(valstr);#ifndef OLD_GETTER_SETTER /* Remove 'function ' from beginning of valstr. */ if (gsop[j]) { int n = strlen(js_function_str) + 1; vchars += n; vlength -= n; }#endif /* If val[j] is a non-sharp object, consider sharpening it. */ vsharp = NULL; vsharplength = 0;#if JS_HAS_SHARP_VARS if (!JSVAL_IS_PRIMITIVE(val[j]) && vchars[0] != '#') { he = js_EnterSharpObject(cx, JSVAL_TO_OBJECT(val[j]), NULL, &vsharp); if (!he) { ok = JS_FALSE; goto error; } if (IS_SHARP(he)) { vchars = vsharp; vlength = js_strlen(vchars); } else { if (vsharp) { vsharplength = js_strlen(vsharp); MAKE_SHARP(he); } js_LeaveSharpObject(cx, NULL); } }#endif /* Allocate 1 + 1 at end for closing brace and terminating 0. */ chars = (jschar *) realloc((ochars = chars), (nchars + (comma ? 2 : 0) + idstrlength + 1 + (gsop[j] ? 1 + JSSTRING_LENGTH(gsop[j]) : 0) + vsharplength + vlength + (outermost ? 2 : 1) + 1) * sizeof(jschar)); if (!chars) { /* Save code space on error: let JS_free ignore null vsharp. */ JS_free(cx, vsharp); free(ochars); goto error; } if (comma) { chars[nchars++] = comma[0]; chars[nchars++] = comma[1]; } comma = ", ";#ifdef OLD_GETTER_SETTER js_strncpy(&chars[nchars], idstrchars, idstrlength); nchars += idstrlength; if (gsop[j]) { chars[nchars++] = ' '; gsoplength = JSSTRING_LENGTH(gsop[j]); js_strncpy(&chars[nchars], JSSTRING_CHARS(gsop[j]), gsoplength); nchars += gsoplength; } chars[nchars++] = ':';#else if (gsop[j]) { gsoplength = JSSTRING_LENGTH(gsop[j]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -