📄 jsobj.c
字号:
jsval v; if (!JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING | JSREPORT_STRICT, js_GetErrorMessage, NULL, JSMSG_DEPRECATED_USAGE, js_WithClass.name)) { return JS_FALSE; } if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) { obj = js_NewObject(cx, &js_WithClass, NULL, NULL); if (!obj) return JS_FALSE; *rval = OBJECT_TO_JSVAL(obj); } parent = cx->fp->scopeChain; if (argc > 0) { if (!js_ValueToObject(cx, argv[0], &proto)) return JS_FALSE; v = OBJECT_TO_JSVAL(proto); if (!obj_setSlot(cx, obj, INT_TO_JSVAL(JSSLOT_PROTO), &v)) return JS_FALSE; if (argc > 1) { if (!js_ValueToObject(cx, argv[1], &parent)) return JS_FALSE; } } v = OBJECT_TO_JSVAL(parent); return obj_setSlot(cx, obj, INT_TO_JSVAL(JSSLOT_PARENT), &v);}#endifJSObject *js_InitObjectClass(JSContext *cx, JSObject *obj){ JSObject *proto; jsval eval;#if JS_HAS_SHARP_VARS JS_ASSERT(sizeof(jsatomid) * JS_BITS_PER_BYTE >= ATOM_INDEX_LIMIT_LOG2 + 1);#endif proto = JS_InitClass(cx, obj, NULL, &js_ObjectClass, Object, 1, object_props, object_methods, NULL, NULL); if (!proto) return NULL;#if JS_HAS_OBJ_PROTO_PROP if (!JS_InitClass(cx, obj, NULL, &js_WithClass, With, 0, NULL, NULL, NULL, NULL)) { return NULL; }#endif /* ECMA (15.1.2.1) says 'eval' is also a property of the global object. */ if (!OBJ_GET_PROPERTY(cx, proto, (jsid)cx->runtime->atomState.evalAtom, &eval)) { return NULL; } if (!OBJ_DEFINE_PROPERTY(cx, obj, (jsid)cx->runtime->atomState.evalAtom, eval, NULL, NULL, 0, NULL)) { return NULL; } return proto;}voidjs_InitObjectMap(JSObjectMap *map, jsrefcount nrefs, JSObjectOps *ops, const JSClass *clasp){ map->nrefs = nrefs; map->ops = ops; map->nslots = JS_INITIAL_NSLOTS; map->freeslot = JSSLOT_FREE(clasp);}JSObjectMap *js_NewObjectMap(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, const JSClass *clasp, JSObject *obj){ return (JSObjectMap *) js_NewScope(cx, nrefs, ops, clasp, obj);}voidjs_DestroyObjectMap(JSContext *cx, JSObjectMap *map){ js_DestroyScope(cx, (JSScope *)map);}JSObjectMap *js_HoldObjectMap(JSContext *cx, JSObjectMap *map){ JS_ASSERT(map->nrefs >= 0); JS_ATOMIC_INCREMENT(&map->nrefs); return map;}JSObjectMap *js_DropObjectMap(JSContext *cx, JSObjectMap *map, JSObject *obj){ JS_ASSERT(map->nrefs > 0); JS_ATOMIC_DECREMENT(&map->nrefs); if (map->nrefs == 0) { map->ops->destroyObjectMap(cx, map); return NULL; } if (MAP_IS_NATIVE(map) && ((JSScope *)map)->object == obj) ((JSScope *)map)->object = NULL; return map;}static JSBoolGetClassPrototype(JSContext *cx, JSObject *scope, const char *name, JSObject **protop);JSObject *js_NewObject(JSContext *cx, const JSClass *clasp, JSObject *proto, JSObject *parent){ JSObject *obj, *ctor; JSObjectOps *ops; JSObjectMap *map; jsval cval; uint32 nslots, i; jsval *newslots; /* Allocate an object from the GC heap and zero it. */ obj = (JSObject *) js_AllocGCThing(cx, GCX_OBJECT); if (!obj) return NULL; /* Bootstrap the ur-object, and make it the default prototype object. */ if (!proto) { if (!GetClassPrototype(cx, parent, clasp->name, &proto)) goto bad; if (!proto && !GetClassPrototype(cx, parent, js_Object_str, &proto)) goto bad; } /* Always call the class's getObjectOps hook if it has one. */ ops = clasp->getObjectOps ? clasp->getObjectOps(cx, clasp) : &js_ObjectOps; /* * Share proto's map only if it has the same JSObjectOps, and only if * proto's class has the same private and reserved slots, as obj's map * and class have. */ if (proto && (map = proto->map)->ops == ops && ((clasp->flags ^ OBJ_GET_CLASS(cx, proto)->flags) & (JSCLASS_HAS_PRIVATE | (JSCLASS_RESERVED_SLOTS_MASK << JSCLASS_RESERVED_SLOTS_SHIFT))) == 0) { /* Default parent to the parent of the prototype's constructor. */ if (!parent) { if (!OBJ_GET_PROPERTY(cx, proto, (jsid)cx->runtime->atomState.constructorAtom, &cval)) { goto bad; } if (JSVAL_IS_OBJECT(cval) && (ctor = JSVAL_TO_OBJECT(cval)) != NULL) parent = OBJ_GET_PARENT(cx, ctor); } /* Share the given prototype's map. */ obj->map = js_HoldObjectMap(cx, map); /* Ensure that obj starts with the minimum slots for clasp. */ nslots = JS_INITIAL_NSLOTS; } else { /* Leave parent alone. Allocate a new map for obj. */ map = ops->newObjectMap(cx, 1, ops, clasp, obj); if (!map) goto bad; obj->map = map; /* Let ops->newObjectMap set nslots so as to reserve slots. */ nslots = map->nslots; } /* Allocate a slots vector, with a -1'st element telling its length. */ newslots = (jsval *) JS_malloc(cx, (nslots + 1) * sizeof(jsval)); if (!newslots) { js_DropObjectMap(cx, obj->map, obj); obj->map = NULL; goto bad; } newslots[0] = nslots; newslots++; /* Set the proto, parent, and class properties. */ newslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto); newslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(parent); newslots[JSSLOT_CLASS] = PRIVATE_TO_JSVAL(clasp); /* Clear above JSSLOT_CLASS so the GC doesn't load uninitialized memory. */ for (i = JSSLOT_CLASS + 1; i < nslots; i++) newslots[i] = JSVAL_VOID; /* Store newslots after initializing all of 'em, just in case. */ obj->slots = newslots; if (cx->runtime->objectHook) cx->runtime->objectHook(cx, obj, JS_TRUE, cx->runtime->objectHookData); return obj;bad: cx->newborn[GCX_OBJECT] = NULL; return NULL;}static JSBoolFindConstructor(JSContext *cx, JSObject *scope, const char *name, jsval *vp){ JSAtom *atom; JSObject *obj; JSObject *pobj; JSScopeProperty *sprop; atom = js_Atomize(cx, name, strlen(name), 0); if (!atom) return JS_FALSE; if (scope || (cx->fp && (scope = cx->fp->scopeChain) != NULL)) { /* Find the topmost object in the scope chain. */ do { obj = scope; scope = OBJ_GET_PARENT(cx, obj); } while (scope); } else { obj = cx->globalObject; if (!obj) { *vp = JSVAL_VOID; return JS_TRUE; } } JS_ASSERT(OBJ_IS_NATIVE(obj)); if (!js_LookupPropertyWithFlags(cx, obj, (jsid)atom, JSRESOLVE_CLASSNAME, &pobj, (JSProperty **)&sprop#if defined JS_THREADSAFE && defined DEBUG , __FILE__, __LINE__#endif )) { return JS_FALSE; } if (!sprop) { *vp = JSVAL_VOID; return JS_TRUE; } JS_ASSERT(OBJ_IS_NATIVE(pobj)); JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj))); *vp = OBJ_GET_SLOT(cx, pobj, sprop->slot); OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop); return JS_TRUE;}JSObject *js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent, uintN argc, jsval *argv){ jsval cval, rval; JSObject *obj, *ctor; if (!FindConstructor(cx, parent, clasp->name, &cval)) return NULL; if (JSVAL_IS_PRIMITIVE(cval)) { js_ReportIsNotFunction(cx, &cval, JSV2F_CONSTRUCT | JSV2F_SEARCH_STACK); return NULL; } /* * If proto or parent are NULL, set them to Constructor.prototype and/or * Constructor.__parent__, just like JSOP_NEW does. */ ctor = JSVAL_TO_OBJECT(cval); if (!parent) parent = OBJ_GET_PARENT(cx, ctor); if (!proto) { if (!OBJ_GET_PROPERTY(cx, ctor, (jsid)cx->runtime->atomState.classPrototypeAtom, &rval)) { return NULL; } if (JSVAL_IS_OBJECT(rval)) proto = JSVAL_TO_OBJECT(rval); } obj = js_NewObject(cx, clasp, proto, parent); if (!obj) return NULL; if (!js_InternalConstruct(cx, obj, cval, argc, argv, &rval)) goto bad; return JSVAL_IS_OBJECT(rval) ? JSVAL_TO_OBJECT(rval) : obj;bad: cx->newborn[GCX_OBJECT] = NULL; return NULL;}voidjs_FinalizeObject(JSContext *cx, JSObject *obj){ JSObjectMap *map; /* Cope with stillborn objects that have no map. */ map = obj->map; if (!map) return; JS_ASSERT(obj->slots); if (cx->runtime->objectHook) cx->runtime->objectHook(cx, obj, JS_FALSE, cx->runtime->objectHookData); /* Remove all watchpoints with weak links to obj. */ JS_ClearWatchPointsForObject(cx, obj); /* * Finalize obj first, in case it needs map and slots. Optimized to use * LOCKED_OBJ_GET_CLASS instead of OBJ_GET_CLASS, so we avoid "promoting" * obj's scope from lock-free to lock-full (see jslock.c:ClaimScope) when * we're called from the GC. Only the GC should call js_FinalizeObject, * and no other threads run JS (and possibly racing to update obj->slots) * while the GC is running. */ LOCKED_OBJ_GET_CLASS(obj)->finalize(cx, obj); /* Drop map and free slots. */ js_DropObjectMap(cx, map, obj); obj->map = NULL; JS_free(cx, obj->slots - 1); obj->slots = NULL;}/* XXXbe if one adds props, deletes earlier props, adds more, the last added won't recycle the deleted props' slots. */JSBooljs_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp){ JSObjectMap *map; uint32 nslots, i; size_t nbytes; jsval *newslots; map = obj->map; JS_ASSERT(!MAP_IS_NATIVE(map) || ((JSScope *)map)->object == obj); nslots = map->nslots; if (map->freeslot >= nslots) { nslots = map->freeslot; JS_ASSERT(nslots >= JS_INITIAL_NSLOTS); nslots += (nslots + 1) / 2; nbytes = (nslots + 1) * sizeof(jsval);#if defined _MSC_VER && _MSC_VER <= 800 if (nbytes > 60000U) { JS_ReportOutOfMemory(cx); return JS_FALSE; }#endif newslots = (jsval *) JS_realloc(cx, obj->slots - 1, nbytes); if (!newslots) return JS_FALSE; for (i = 1 + newslots[0]; i <= nslots; i++) newslots[i] = JSVAL_VOID; newslots[0] = map->nslots = nslots; obj->slots = newslots + 1; }#ifdef TOO_MUCH_GC obj->slots[map->freeslot] = JSVAL_VOID;#endif *slotp = map->freeslot++; return JS_TRUE;}voidjs_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot){ JSObjectMap *map; uint32 nslots; size_t nbytes; jsval *newslots; OBJ_CHECK_SLOT(obj, slot); obj->slots[slot] = JSVAL_VOID; map = obj->map; JS_ASSERT(!MAP_IS_NATIVE(map) || ((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; if (nslots < JS_INITIAL_NSLOTS) nslots = JS_INITIAL_NSLOTS; nbytes = (nslots + 1) * sizeof(jsval); newslots = (jsval *) JS_realloc(cx, obj->slots - 1, nbytes); if (!newslots) return; newslots[0] = map->nslots = nslots; obj->slots = newslots + 1; }}#if JS_BUG_EMPTY_INDEX_ZERO#define CHECK_FOR_EMPTY_INDEX(id) \ JS_BEGIN_MACRO \ if (JSSTRING_LENGTH(_str) == 0) \ id = JSVAL_ZERO; \ JS_END_MACRO#else#define CHECK_FOR_EMPTY_INDEX(id) /* nothing */#endif/* JSVAL_INT_MAX as a string */#define JSVAL_INT_MAX_STRING "1073741823"#define CHECK_FOR_FUNNY_INDEX(id) \ JS_BEGIN_MACRO \ if (!JSVAL_IS_INT(id)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -