예제 #1
0
JSProperty *
js_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
    JSProperty *prop;
    JSObject *obj2;
    jsint slot;

    PR_ASSERT(JS_IS_LOCKED(cx));

    if (!js_LookupProperty(cx, obj, id, &obj, &prop))
	return NULL;
    if (!prop) {
	prop = js_DefineProperty(cx, obj, id,
#if JS_BUG_NULL_INDEX_PROPS
				 (JSVAL_IS_INT(id) && JSVAL_TO_INT(id) >= 0)
				 ? JSVAL_NULL
				 : JSVAL_VOID,
#else
				 JSVAL_VOID,
#endif
				 NULL, NULL, 0);
	if (!prop)
	    return NULL;
    }
    obj2 = prop->object;
    slot = prop->slot;
    *vp = obj2->slots[slot];
    if (!prop->getter(cx, obj, prop->id, vp))
	return NULL;
    obj2->slots[slot] = *vp;
    return prop;
}
예제 #2
0
void
js_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot)
{
    JSObjectMap *map;
    uint32 nslots;
    size_t nbytes;
    jsval *newslots;

    PR_ASSERT(JS_IS_LOCKED(cx));
    map = obj->map;
    PR_ASSERT(((JSScope *)map)->object == obj);
    if (map->freeslot == slot + 1)
	map->freeslot = slot;
    nslots = map->nslots;
    if (nslots > JS_INITIAL_NSLOTS && map->freeslot < nslots / 2) {
	nslots = map->freeslot;
	nslots += nslots / 2;
	nbytes = (size_t)nslots * sizeof(jsval);
	newslots = JS_realloc(cx, obj->slots, nbytes);
	if (!newslots)
	    return;
	obj->slots = newslots;
	map->nslots = nslots;
    }
}
예제 #3
0
js_free_symbol(void *priv, PRHashEntry *he, uintN flag)
{
    JSContext *cx;
    JSSymbol *sym, **sp;
    JSProperty *prop;

    cx = priv;
    PR_ASSERT(JS_IS_LOCKED(cx));
    sym = (JSSymbol *)he;
    prop = sym->entry.value;
    if (prop) {
        sym->entry.value = NULL;
        prop = js_DropProperty(cx, prop);
        if (prop) {
            for (sp = &prop->symbols; *sp; sp = &(*sp)->next) {
                if (*sp == sym) {
                    *sp = sym->next;
                    if (!*sp)
                        break;
                }
            }
            sym->next = NULL;
        }
    }

    if (flag == HT_FREE_ENTRY) {
        if (!JSVAL_IS_INT(sym_id(sym)))
            JS_LOCK_VOID(cx, js_DropAtom(cx, sym_atom(sym)));
        JS_free(cx, he);
    }
}
예제 #4
0
JSObject *
js_FindVariableScope(JSContext *cx, JSFunction **funp)
{
    JSStackFrame *fp;
    JSObject *obj, *parent, *withobj;
    JSClass *clasp;
    JSFunction *fun;

    PR_ASSERT(JS_IS_LOCKED(cx));

    fp = cx->fp;
    for (obj = fp->scopeChain, withobj = NULL; ; obj = parent) {
	parent = OBJ_GET_PARENT(obj);
	clasp = obj->map->clasp;
	if (!parent || clasp != &js_WithClass)
	    break;
	withobj = obj;
    }

    fun = (clasp == &js_FunctionClass) ? JS_GetPrivate(cx, obj) : NULL;
#if JS_HAS_CALL_OBJECT
    if (fun && fun->script) {
	for (; fp && fp->fun != fun; fp = fp->down)
	    ;
	if (fp) {
	    obj = js_GetCallObject(cx, fp, parent);
	    if (withobj)
		OBJ_SET_PARENT(withobj, obj);
	}
    }
#endif

    *funp = fun;
    return obj;
}
예제 #5
0
js_DropAtom(JSContext *cx, JSAtom *atom)
{
#ifdef DEBUG_DUPLICATE_ATOMS
    jsval key;
    PRHashNumber keyHash;
    PRHashEntry *he, **hep;

    key = ATOM_KEY(atom);
    keyHash = js_hash_atom_key((void *)key);
    hep = PR_HashTableRawLookup(cx->runtime->atomState.table, keyHash,
				(void*)key);
    he = *hep;
    PR_ASSERT(atom == (JSAtom *)he);
#endif
    PR_ASSERT(JS_IS_LOCKED(cx));
    PR_ASSERT(atom->nrefs > 0);
    if (atom->nrefs <= 0)
	return NULL;
    if (--atom->nrefs == 0) {
	PR_HashTableRemove(cx->runtime->atomState.table, atom->entry.key);
#ifdef DEBUG_DUPLICATE_ATOMS
	hep = PR_HashTableRawLookup(cx->runtime->atomState.table, keyHash,
				    (void *)key);
	he = *hep;
	PR_ASSERT(he == NULL);
#endif
	atom = NULL;
    }
    return atom;
}
예제 #6
0
static JSAtom *
js_AtomizeHashedKey(JSContext *cx, jsval key, PRHashNumber keyHash, uintN flags)
{
    PRHashTable *table;
    PRHashEntry *he, **hep;
    JSAtom *atom;

    PR_ASSERT(JS_IS_LOCKED(cx));
    table = cx->runtime->atomState.table;
    hep = PR_HashTableRawLookup(table, keyHash, (void *)key);
    if ((he = *hep) == NULL) {
	he = PR_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL);
	if (!he) {
	    JS_ReportOutOfMemory(cx);
	    return NULL;
	}
    }

    atom = (JSAtom *)he;
#ifdef DEBUG_DUPLICATE_ATOMS
    hep = PR_HashTableRawLookup(table, keyHash, (void *)key);
    he = *hep;
    PR_ASSERT(atom == (JSAtom *)he);
#endif

    if (flags & ATOM_NOHOLD)
	return atom;
    return js_HoldAtom(cx, atom);
}
예제 #7
0
void
js_FinalizeObject(JSContext *cx, JSObject *obj)
{
    JSScope *scope;

    PR_ASSERT(JS_IS_LOCKED(cx));

    /* Cope with stillborn objects that have no scope. */
    scope = (JSScope *)obj->map;
    if (!scope)
	return;

#if JS_HAS_OBJ_WATCHPOINT
    /* Remove all watchpoints with weak links to obj. */
    JS_ClearWatchPointsForObject(cx, obj);
#endif

    /* Finalize obj first, in case it needs map and slots. */
    scope->map.clasp->finalize(cx, obj);
    if (scope->object == obj)
	scope->object = NULL;

    /* Drop scope and free slots. */
    js_DropScope(cx, scope);
    obj->map = NULL;
    JS_free(cx, obj->slots);
    obj->slots = NULL;
}
예제 #8
0
static JSBool
FindConstructor(JSContext *cx, JSClass *clasp, jsval *vp)
{
    JSAtom *atom;
    JSObject *obj, *tmp;
    JSBool ok;

    PR_ASSERT(JS_IS_LOCKED(cx));

    /* XXX pre-atomize in JS_InitClass! */
    atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
    if (!atom)
	return JS_FALSE;

    if (cx->fp && (tmp = cx->fp->scopeChain)) {
	/* Find the topmost object in the scope chain. */
	do {
	    obj = tmp;
	    tmp = OBJ_GET_PARENT(obj);
	} while (tmp);
    } else {
	obj = cx->globalObject;
	if (!obj) {
	    *vp = JSVAL_VOID;
	    return JS_TRUE;
	}
    }

    ok = (js_GetProperty(cx, obj, (jsval)atom, vp) != NULL);
    js_DropAtom(cx, atom);
    return JS_TRUE;
}
예제 #9
0
js_LookupProperty(JSContext *cx, JSObject *obj, jsval id, JSObject **objp,
		  JSProperty **propp)
{
    JSObject *pobj;
    PRHashNumber hash;
    JSScope *prevscope, *scope;
    JSSymbol *sym;
    JSClass *clasp;
    JSResolveOp resolve;
    JSNewResolveOp newresolve;

    PR_ASSERT(JS_IS_LOCKED(cx));

    /* Handle old bug that treated empty string as zero index. */
    CHECK_FOR_FUNNY_INDEX(id);

    /* Search scopes starting with obj and following the prototype link. */
    hash = js_HashValue(id);
    prevscope = NULL;
    do {
	scope = (JSScope *)obj->map;
	if (scope == prevscope)
	    continue;
	sym = scope->ops->lookup(cx, scope, id, hash);
	if (!sym && objp) {
	    clasp = scope->map.clasp;
	    resolve = clasp->resolve;
	    if (resolve != JS_ResolveStub) {
		if (clasp->flags & JSCLASS_NEW_RESOLVE) {
		    newresolve = (JSNewResolveOp)resolve;
		    pobj = NULL;
		    if (!newresolve(cx, obj, js_IdToValue(id), &pobj))
			return JS_FALSE;
		    if (pobj) {
			*objp = pobj;
			scope = (JSScope *)pobj->map;
			sym = scope->ops->lookup(cx, scope, id, hash);
		    }
		} else {
		    if (!resolve(cx, obj, js_IdToValue(id)))
			return JS_FALSE;
		    scope = (JSScope *)obj->map;
		    sym = scope->ops->lookup(cx, scope, id, hash);
		}
	    }
	}
	if (sym) {
	    *propp = sym_property(sym);
	    return JS_TRUE;
	}
	prevscope = scope;
    } while ((obj = OBJ_GET_PROTO(obj)) != NULL);
    *propp = NULL;
    return JS_TRUE;
}
예제 #10
0
static JSBool
obj_watch_handler(JSContext *cx, JSObject *obj, jsval id, jsval old, jsval *nvp,
		  void *closure)
{
    JSObject *funobj;
    jsval argv[3];

    PR_ASSERT(JS_IS_LOCKED(cx));
    funobj = closure;
    argv[0] = id;
    argv[1] = old;
    argv[2] = *nvp;
    return js_Call(cx, obj, OBJECT_TO_JSVAL(funobj), 3, argv, nvp);
}
예제 #11
0
JSAtom *
js_AtomizeDouble(JSContext *cx, jsdouble d, uintN flags)
{
    jsdouble *dp;
    PRHashTable *table;
    PRHashNumber keyHash;
    jsval key;
    PRHashEntry *he, **hep;
    JSAtom *atom;

#if PR_ALIGN_OF_DOUBLE == 8
    dp = &d;
#else
    char alignbuf[16];

    dp = (jsdouble *)&alignbuf[8 - ((pruword)&alignbuf & 7)];
    *dp = d;
#endif

    PR_ASSERT(JS_IS_LOCKED(cx));
    table = cx->runtime->atomState.table;
    keyHash = HASH_DOUBLE(dp);
    key = DOUBLE_TO_JSVAL(dp);
    hep = PR_HashTableRawLookup(table, keyHash, (void *)key);
    if ((he = *hep) == NULL) {
	if (!js_NewDoubleValue(cx, d, &key))
	    return NULL;
	he = PR_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL);
	if (!he) {
	    JS_ReportOutOfMemory(cx);
	    return NULL;
	}
    }

    atom = (JSAtom *)he;
#ifdef DEBUG_DUPLICATE_ATOMS
    hep = PR_HashTableRawLookup(table, keyHash, (void *)key);
    he = *hep;
    PR_ASSERT(atom == (JSAtom *)he);
#endif

    if (flags & ATOM_NOHOLD)
	return atom;
    return js_HoldAtom(cx, atom);
}
예제 #12
0
js_alloc_symbol(void *priv, const void *key)
{
    JSContext *cx;
    JSSymbol *sym;
    JSAtom *atom;

    cx = priv;
    PR_ASSERT(JS_IS_LOCKED(cx));
    sym = JS_malloc(cx, sizeof(JSSymbol));
    if (!sym)
        return NULL;
    sym->entry.key = key;
    if (!JSVAL_IS_INT((jsval)key)) {
        atom = (JSAtom *)key;
        js_HoldAtom(cx, atom);
    }
    return &sym->entry;
}
예제 #13
0
JSBool
js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp)
{
    JSObjectMap *map;
    uint32 nslots;
    size_t nbytes;
    jsval *newslots;

    PR_ASSERT(JS_IS_LOCKED(cx));
    map = obj->map;
    PR_ASSERT(((JSScope *)map)->object == obj);

    nslots = map->nslots;
    if (map->freeslot >= nslots) {
	nslots = PR_MAX(map->freeslot, nslots);
	if (nslots < JS_INITIAL_NSLOTS)
	    nslots = JS_INITIAL_NSLOTS;
	else
	    nslots += (nslots + 1) / 2;

	nbytes = (size_t)nslots * sizeof(jsval);
#if defined(XP_PC) && defined _MSC_VER && _MSC_VER <= 800
	if (nbytes > 60000U) {
	    JS_ReportOutOfMemory(cx);
	    return JS_FALSE;
	}
#endif

	if (obj->slots)
	    newslots = JS_realloc(cx, obj->slots, nbytes);
	else
	    newslots = JS_malloc(cx, nbytes);
	if (!newslots)
	    return JS_FALSE;
	obj->slots = newslots;
	map->nslots = nslots;
    }

#ifdef TOO_MUCH_GC
    obj->slots[map->freeslot] = JSVAL_VOID;
#endif
    *slotp = map->freeslot++;
    return JS_TRUE;
}
예제 #14
0
js_hash_scope_add(JSContext *cx, JSScope *scope, jsval id, JSProperty *prop)
{
    PRHashTable *table = scope->data;
    const void *key;
    PRHashNumber keyHash;
    PRHashEntry **hep;
    JSSymbol *sym, **sp;

    PR_ASSERT(JS_IS_LOCKED(cx));
    table->allocPriv = cx;
    key = (const void *)id;
    keyHash = js_hash_id(key);
    hep = PR_HashTableRawLookup(table, keyHash, key);
    sym = (JSSymbol *) *hep;
    SCOPE_ADD(
        sym = (JSSymbol *) PR_HashTableRawAdd(table, hep, keyHash, key, NULL);
        if (!sym)
        return NULL;
    );
예제 #15
0
JSAtom *
js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
{
    PRHashTable *table;
    PRHashNumber keyHash;
    jsval key;
    PRHashEntry *he, **hep;
    JSAtom *atom;

    PR_ASSERT(JS_IS_LOCKED(cx));
    table = cx->runtime->atomState.table;
    keyHash = js_HashString(str);
    key = STRING_TO_JSVAL(str);
    hep = PR_HashTableRawLookup(table, keyHash, (void *)key);
    if ((he = *hep) == NULL) {
	if (flags & ATOM_TMPSTR) {
	    if (flags & ATOM_NOCOPY)
		str = js_NewString(cx, str->chars, str->length, 0);
	    else
		str = js_NewStringCopyN(cx, str->chars, str->length, 0);
	    if (!str)
		return NULL;
	    key = STRING_TO_JSVAL(str);
	}
	he = PR_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL);
	if (!he) {
	    JS_ReportOutOfMemory(cx);
	    return NULL;
	}
    }

    atom = (JSAtom *)he;
#ifdef DEBUG_DUPLICATE_ATOMS
    hep = PR_HashTableRawLookup(table, keyHash, (void *)key);
    he = *hep;
    PR_ASSERT(atom == (JSAtom *)he);
#endif

    if (flags & ATOM_NOHOLD)
	return atom;
    return js_HoldAtom(cx, atom);
}
예제 #16
0
JSAtom *
js_HoldAtom(JSContext *cx, JSAtom *atom)
{
#ifdef DEBUG_DUPLICATE_ATOMS
    jsval key;
    PRHashNumber keyHash;
    PRHashEntry *he, **hep;

    key = ATOM_KEY(atom);
    keyHash = js_hash_atom_key((void *)key);
    hep = PR_HashTableRawLookup(cx->runtime->atomState.table, keyHash,
				(void*)key);
    he = *hep;
    PR_ASSERT(atom == (JSAtom *)he);
#endif
    PR_ASSERT(JS_IS_LOCKED(cx));
    atom->nrefs++;
    PR_ASSERT(atom->nrefs > 0);
    return atom;
}
예제 #17
0
JSBool
js_DeleteProperty(JSContext *cx, JSObject *obj, jsval id, jsval *rval)
{
#if JS_HAS_PROP_DELETE
    JSProperty *prop;

    PR_ASSERT(JS_IS_LOCKED(cx));

    if (!js_LookupProperty(cx, obj, id, NULL, &prop))
	return JS_FALSE;
    if (!prop)
	return JS_TRUE;
    return js_DeleteProperty2(cx, obj, prop, id, rval);
#else
    jsval null = JSVAL_NULL;

    *rval = JSVAL_VOID;
    return (js_SetProperty(cx, obj, id, &null) != NULL);
#endif
}