jsobj.c
来自「一个基于alice开发的机器人」· C语言 代码 · 共 2,081 行 · 第 1/5 页
C
2,081 行
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) {
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 = (jsatomid) he->value;
if (sharpid == 0) {
sharpid = ++map->sharpgen << SHARP_ID_SHIFT;
he->value = (void *) 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((((jsatomid) 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;
}
*sp = NULL;
sharpid = 0;
goto out;
}
}
sharpid = (jsatomid) 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;
}
void
js_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_TOSOURCE
JSBool
js_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.
*/
if (atom && (ATOM_KEYWORD(atom) || !js_IsIdentifier(idstr))) {
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);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?