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

📄 jsobj.c

📁 java script test programing source code
💻 C
📖 第 1 页 / 共 5 页
字号:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=78: * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** *//* * JS object implementation. */#include "jsstddef.h"#include <stdlib.h>#include <string.h>#include "jstypes.h"#include "jsarena.h" /* Added by JSIFY */#include "jsbit.h"#include "jsutil.h" /* Added by JSIFY */#include "jshash.h" /* Added by JSIFY */#include "jsdhash.h"#include "jsprf.h"#include "jsapi.h"#include "jsarray.h"#include "jsatom.h"#include "jsbool.h"#include "jscntxt.h"#include "jsconfig.h"#include "jsfun.h"#include "jsgc.h"#include "jsinterp.h"#include "jslock.h"#include "jsnum.h"#include "jsobj.h"#include "jsscan.h"#include "jsscope.h"#include "jsscript.h"#include "jsstr.h"#include "jsopcode.h"#include "jsdbgapi.h"   /* whether or not JS_HAS_OBJ_WATCHPOINT */#if JS_HAS_GENERATORS#include "jsiter.h"#endif#if JS_HAS_XML_SUPPORT#include "jsxml.h"#endif#if JS_HAS_XDR#include "jsxdrapi.h"#endif#ifdef JS_THREADSAFE#define NATIVE_DROP_PROPERTY js_DropPropertyextern voidjs_DropProperty(JSContext *cx, JSObject *obj, JSProperty *prop);#else#define NATIVE_DROP_PROPERTY NULL#endifJS_FRIEND_DATA(JSObjectOps) js_ObjectOps = {    js_NewObjectMap,        js_DestroyObjectMap,    js_LookupProperty,      js_DefineProperty,    js_GetProperty,         js_SetProperty,    js_GetAttributes,       js_SetAttributes,    js_DeleteProperty,      js_DefaultValue,    js_Enumerate,           js_CheckAccess,    NULL,                   NATIVE_DROP_PROPERTY,    js_Call,                js_Construct,    NULL,                   js_HasInstance,    js_SetProtoOrParent,    js_SetProtoOrParent,    js_Mark,                js_Clear,    js_GetRequiredSlot,     js_SetRequiredSlot};JSClass js_ObjectClass = {    js_Object_str,    JSCLASS_HAS_CACHED_PROTO(JSProto_Object),    JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,    JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   JS_FinalizeStub,    JSCLASS_NO_OPTIONAL_MEMBERS};#if JS_HAS_OBJ_PROTO_PROPstatic JSBoolobj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp);static JSBoolobj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp);static JSBoolobj_getCount(JSContext *cx, JSObject *obj, jsval id, jsval *vp);static JSPropertySpec object_props[] = {    /* These two must come first; see object_props[slot].name usage below. */    {js_proto_str, JSSLOT_PROTO, JSPROP_PERMANENT|JSPROP_SHARED,                                                  obj_getSlot,  obj_setSlot},    {js_parent_str,JSSLOT_PARENT,JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED,                                                  obj_getSlot,  obj_setSlot},    {js_count_str, 0,            JSPROP_PERMANENT,obj_getCount, obj_getCount},    {0,0,0,0,0}};/* NB: JSSLOT_PROTO and JSSLOT_PARENT are already indexes into object_props. */#define JSSLOT_COUNT 2static JSBoolReportStrictSlot(JSContext *cx, uint32 slot){    if (slot == JSSLOT_PROTO)        return JS_TRUE;    return JS_ReportErrorFlagsAndNumber(cx,                                        JSREPORT_WARNING | JSREPORT_STRICT,                                        js_GetErrorMessage, NULL,                                        JSMSG_DEPRECATED_USAGE,                                        object_props[slot].name);}static JSBoolobj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp){    uint32 slot;    jsid propid;    JSAccessMode mode;    uintN attrs;    JSObject *pobj;    JSClass *clasp;    JSExtendedClass *xclasp;    slot = (uint32) JSVAL_TO_INT(id);    if (id == INT_TO_JSVAL(JSSLOT_PROTO)) {        propid = ATOM_TO_JSID(cx->runtime->atomState.protoAtom);        mode = JSACC_PROTO;    } else {        propid = ATOM_TO_JSID(cx->runtime->atomState.parentAtom);        mode = JSACC_PARENT;    }    /* Let OBJ_CHECK_ACCESS get the slot's value, based on the access mode. */    if (!OBJ_CHECK_ACCESS(cx, obj, propid, mode, vp, &attrs))        return JS_FALSE;    pobj = JSVAL_TO_OBJECT(*vp);    if (pobj) {        clasp = OBJ_GET_CLASS(cx, pobj);        if (clasp == &js_CallClass || clasp == &js_BlockClass) {            /* Censor activations and lexical scopes per ECMA-262. */            *vp = JSVAL_NULL;        } else if (clasp->flags & JSCLASS_IS_EXTENDED) {            xclasp = (JSExtendedClass *) clasp;            if (xclasp->outerObject) {                pobj = xclasp->outerObject(cx, pobj);                if (!pobj)                    return JS_FALSE;                *vp = OBJECT_TO_JSVAL(pobj);            }        }    }    return JS_TRUE;}static JSBoolobj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp){    JSObject *pobj;    uint32 slot;    jsid propid;    uintN attrs;    if (!JSVAL_IS_OBJECT(*vp))        return JS_TRUE;    pobj = JSVAL_TO_OBJECT(*vp);    if (pobj) {        /*         * Innerize pobj here to avoid sticking unwanted properties on the         * outer object. This ensures that any with statements only grant         * access to the inner object.         */        OBJ_TO_INNER_OBJECT(cx, pobj);        if (!pobj)            return JS_FALSE;    }    slot = (uint32) JSVAL_TO_INT(id);    if (JS_HAS_STRICT_OPTION(cx) && !ReportStrictSlot(cx, slot))        return JS_FALSE;    /* __parent__ is readonly and permanent, only __proto__ may be set. */    propid = ATOM_TO_JSID(cx->runtime->atomState.protoAtom);    if (!OBJ_CHECK_ACCESS(cx, obj, propid, JSACC_PROTO|JSACC_WRITE, vp, &attrs))        return JS_FALSE;    return js_SetProtoOrParent(cx, obj, slot, pobj);}static JSBoolobj_getCount(JSContext *cx, JSObject *obj, jsval id, jsval *vp){    jsval iter_state;    jsid num_properties;    JSBool ok;    if (JS_HAS_STRICT_OPTION(cx) && !ReportStrictSlot(cx, JSSLOT_COUNT))        return JS_FALSE;    /* Get the number of properties to enumerate. */    iter_state = JSVAL_NULL;    ok = OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, &num_properties);    if (!ok)        goto out;    if (!JSVAL_IS_INT(num_properties)) {        JS_ASSERT(0);        *vp = JSVAL_ZERO;        goto out;    }    *vp = num_properties;out:    if (iter_state != JSVAL_NULL)        ok = OBJ_ENUMERATE(cx, obj, JSENUMERATE_DESTROY, &iter_state, 0);    return ok;}#else  /* !JS_HAS_OBJ_PROTO_PROP */#define object_props NULL#endif /* !JS_HAS_OBJ_PROTO_PROP */JSBooljs_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj){    JSRuntime *rt;    JSObject *obj2, *oldproto;    JSScope *scope, *newscope;    /*     * Serialize all proto and parent setting in order to detect cycles.     * We nest locks in this function, and only here, in the following orders:     *     * (1)  rt->setSlotLock < pobj's scope lock;     *      rt->setSlotLock < pobj's proto-or-parent's scope lock;     *      rt->setSlotLock < pobj's grand-proto-or-parent's scope lock;     *      etc...     * (2)  rt->setSlotLock < obj's scope lock < pobj's scope lock.     *     * We avoid AB-BA deadlock by restricting obj from being on pobj's parent     * or proto chain (pobj may already be on obj's parent or proto chain; it     * could be moving up or down).  We finally order obj with respect to pobj     * at the bottom of this routine (just before releasing rt->setSlotLock),     * by making pobj be obj's prototype or parent.     *     * After we have set the slot and released rt->setSlotLock, another call     * to js_SetProtoOrParent could nest locks according to the first order     * list above, but it cannot deadlock with any other thread.  For there     * to be a deadlock, other parts of the engine would have to nest scope     * locks in the opposite order.  XXXbe ensure they don't!     */    rt = cx->runtime;#ifdef JS_THREADSAFE    JS_ACQUIRE_LOCK(rt->setSlotLock);    while (rt->setSlotBusy) {        jsrefcount saveDepth;        /* Take pains to avoid nesting rt->gcLock inside rt->setSlotLock! */        JS_RELEASE_LOCK(rt->setSlotLock);        saveDepth = JS_SuspendRequest(cx);        JS_ACQUIRE_LOCK(rt->setSlotLock);        if (rt->setSlotBusy)            JS_WAIT_CONDVAR(rt->setSlotDone, JS_NO_TIMEOUT);        JS_RELEASE_LOCK(rt->setSlotLock);        JS_ResumeRequest(cx, saveDepth);        JS_ACQUIRE_LOCK(rt->setSlotLock);    }    rt->setSlotBusy = JS_TRUE;    JS_RELEASE_LOCK(rt->setSlotLock);#define SET_SLOT_DONE(rt)                                                     \    JS_BEGIN_MACRO                                                            \        JS_ACQUIRE_LOCK((rt)->setSlotLock);                                   \        (rt)->setSlotBusy = JS_FALSE;                                         \        JS_NOTIFY_ALL_CONDVAR((rt)->setSlotDone);                             \        JS_RELEASE_LOCK((rt)->setSlotLock);                                   \    JS_END_MACRO#else#define SET_SLOT_DONE(rt)       /* nothing */#endif    obj2 = pobj;    while (obj2) {        if (obj2 == obj) {            SET_SLOT_DONE(rt);            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,                                 JSMSG_CYCLIC_VALUE,#if JS_HAS_OBJ_PROTO_PROP                                 object_props[slot].name#else                                 (slot == JSSLOT_PROTO) ? js_proto_str                                                        : js_parent_str#endif                                 );            return JS_FALSE;        }        obj2 = JSVAL_TO_OBJECT(OBJ_GET_SLOT(cx, obj2, slot));    }    if (slot == JSSLOT_PROTO && OBJ_IS_NATIVE(obj)) {        /* Check to see whether obj shares its prototype's scope. */        JS_LOCK_OBJ(cx, obj);        scope = OBJ_SCOPE(obj);        oldproto = JSVAL_TO_OBJECT(LOCKED_OBJ_GET_SLOT(obj, JSSLOT_PROTO));        if (oldproto && OBJ_SCOPE(oldproto) == scope) {            /* Either obj needs a new empty scope, or it should share pobj's. */            if (!pobj ||                !OBJ_IS_NATIVE(pobj) ||                OBJ_GET_CLASS(cx, pobj) != LOCKED_OBJ_GET_CLASS(oldproto)) {                /*                 * With no proto and no scope of its own, obj is truly empty.                 *                 * If pobj is not native, obj needs its own empty scope -- it                 * should not continue to share oldproto's scope once oldproto                 * is not on obj's prototype chain.  That would put properties                 * from oldproto's scope ahead of properties defined by pobj,                 * in lookup order.                 *                 * If pobj's class differs from oldproto's, we may need a new                 * scope to handle differences in private and reserved slots,                 * so we suboptimally but safely make one.                 */                scope = js_GetMutableScope(cx, obj);                if (!scope) {                    JS_UNLOCK_OBJ(cx, obj);                    SET_SLOT_DONE(rt);                    return JS_FALSE;                }            } else if (OBJ_SCOPE(pobj) != scope) {#ifdef JS_THREADSAFE                /*                 * We are about to nest scope locks.  Help jslock.c:ShareScope                 * keep scope->u.count balanced for the JS_UNLOCK_SCOPE, while                 * avoiding deadlock, by recording scope in rt->setSlotScope.                 */                if (scope->ownercx) {                    JS_ASSERT(scope->ownercx == cx);                    rt->setSlotScope = scope;                }#endif                /* We can't deadlock because we checked for cycles above (2). */                JS_LOCK_OBJ(cx, pobj);                newscope = (JSScope *) js_HoldObjectMap(cx, pobj->map);                obj->map = &newscope->map;                js_DropObjectMap(cx, &scope->map, obj);                JS_TRANSFER_SCOPE_LOCK(cx, scope, newscope);                scope = newscope;#ifdef JS_THREADSAFE                rt->setSlotScope = NULL;#endif            }        }        LOCKED_OBJ_SET_SLOT(obj, JSSLOT_PROTO, OBJECT_TO_JSVAL(pobj));        JS_UNLOCK_SCOPE(cx, scope);    } else {        OBJ_SET_SLOT(cx, obj, slot, OBJECT_TO_JSVAL(pobj));    }    SET_SLOT_DONE(rt);    return JS_TRUE;#undef SET_SLOT_DONE}JS_STATIC_DLL_CALLBACK(JSHashNumber)js_hash_object(const void *key){    return (JSHashNumber)JS_PTR_TO_UINT32(key) >> JSVAL_TAGBITS;

⌨️ 快捷键说明

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