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

📄 jsfun.c

📁 一个基于alice开发的机器人
💻 C
📖 第 1 页 / 共 5 页
字号:
                value = vp[slot];
                spflags = SPROP_HAS_SHORTID;
                shortid = (intN) slot;
            } else {
                value = JSVAL_VOID;
                spflags = 0;
                shortid = 0;
            }
            if (!js_DefineNativeProperty(cx, obj, propid, value,
                                         getter, setter, attrs,
                                         spflags, shortid, NULL)) {
                return JS_FALSE;
            }
            *objp = obj;
        }
    }
    return JS_TRUE;
}

static JSBool
call_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
{
    JSStackFrame *fp;

    if (type == JSTYPE_FUNCTION) {
        fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
        if (fp) {
            JS_ASSERT(fp->fun);
            *vp = fp->argv ? fp->argv[-2] : OBJECT_TO_JSVAL(fp->fun->object);
        }
    }
    return JS_TRUE;
}

JSClass js_CallClass = {
    js_Call_str,
    JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE,
    JS_PropertyStub,  JS_PropertyStub,
    call_getProperty, call_setProperty,
    call_enumerate,   (JSResolveOp)call_resolve,
    call_convert,     JS_FinalizeStub,
    JSCLASS_NO_OPTIONAL_MEMBERS
};

#endif /* JS_HAS_CALL_OBJECT */

/* SHARED because fun_getProperty always computes a new value. */
#define FUNCTION_PROP_ATTRS (JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED)

static JSPropertySpec function_props[] = {
    {js_arguments_str, CALL_ARGUMENTS, FUNCTION_PROP_ATTRS,0,0},
    {js_arity_str,     FUN_ARITY,      FUNCTION_PROP_ATTRS,0,0},
    {js_length_str,    ARGS_LENGTH,    FUNCTION_PROP_ATTRS,0,0},
    {js_name_str,      FUN_NAME,       FUNCTION_PROP_ATTRS,0,0},
    {js_caller_str,    FUN_CALLER,     FUNCTION_PROP_ATTRS,0,0},
    {0,0,0,0,0}
};

static JSBool
fun_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
    jsint slot;
    JSFunction *fun;
    JSStackFrame *fp;
#if defined _MSC_VER &&_MSC_VER <= 800
    /* MSVC1.5 coredumps */
    jsval bogus = *vp;
#endif

    if (!JSVAL_IS_INT(id))
        return JS_TRUE;
    slot = JSVAL_TO_INT(id);

    /* No valid function object should lack private data, but check anyway. */
    fun = (JSFunction *)JS_GetInstancePrivate(cx, obj, &js_FunctionClass, NULL);
    if (!fun)
        return JS_TRUE;

    /* Find fun's top-most activation record. */
    for (fp = cx->fp; fp && (fp->fun != fun || (fp->flags & JSFRAME_SPECIAL));
         fp = fp->down) {
        continue;
    }

    switch (slot) {
      case CALL_ARGUMENTS:
#if JS_HAS_ARGS_OBJECT
        /* Warn if strict about f.arguments or equivalent unqualified uses. */
        if (!JS_ReportErrorFlagsAndNumber(cx,
                                          JSREPORT_WARNING | JSREPORT_STRICT,
                                          js_GetErrorMessage, NULL,
                                          JSMSG_DEPRECATED_USAGE,
                                          js_arguments_str)) {
            return JS_FALSE;
        }
        if (fp) {
            if (!js_GetArgsValue(cx, fp, vp))
                return JS_FALSE;
        } else {
            *vp = JSVAL_NULL;
        }
        break;
#else  /* !JS_HAS_ARGS_OBJECT */
        *vp = OBJECT_TO_JSVAL(fp ? obj : NULL);
        break;
#endif /* !JS_HAS_ARGS_OBJECT */

      case ARGS_LENGTH:
        if (!JSVERSION_IS_ECMA(cx->version))
            *vp = INT_TO_JSVAL((jsint)(fp && fp->fun ? fp->argc : fun->nargs));
        else
      case FUN_ARITY:
            *vp = INT_TO_JSVAL((jsint)fun->nargs);
        break;

      case FUN_NAME:
        *vp = fun->atom
              ? ATOM_KEY(fun->atom)
              : STRING_TO_JSVAL(cx->runtime->emptyString);
        break;

      case FUN_CALLER:
        while (fp && (fp->flags & JSFRAME_SKIP_CALLER) && fp->down)
            fp = fp->down;
        if (fp && fp->down && fp->down->fun && fp->down->argv)
            *vp = fp->down->argv[-2];
        else
            *vp = JSVAL_NULL;
        if (!JSVAL_IS_PRIMITIVE(*vp) && cx->runtime->checkObjectAccess) {
            id = ATOM_KEY(cx->runtime->atomState.callerAtom);
            if (!cx->runtime->checkObjectAccess(cx, obj, id, JSACC_READ, vp))
                return JS_FALSE;
        }
        break;

      default:
        /* XXX fun[0] and fun.arguments[0] are equivalent. */
        if (fp && fp->fun && (uintN)slot < fp->fun->nargs)
#if defined _MSC_VER &&_MSC_VER <= 800
          /* MSVC1.5 coredumps */
          if (bogus == *vp)
#endif
            *vp = fp->argv[slot];
        break;
    }

    return JS_TRUE;
}

static JSBool
fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
            JSObject **objp)
{
    JSFunction *fun;
    JSString *str;
    JSAtom *prototypeAtom;

    if (!JSVAL_IS_STRING(id))
        return JS_TRUE;

    /* No valid function object should lack private data, but check anyway. */
    fun = (JSFunction *)JS_GetInstancePrivate(cx, obj, &js_FunctionClass, NULL);
    if (!fun || !fun->object)
        return JS_TRUE;

    /* No need to reflect fun.prototype in 'fun.prototype = ...'. */
    if (flags & JSRESOLVE_ASSIGNING)
        return JS_TRUE;

    /*
     * Ok, check whether id is 'prototype' and bootstrap the function object's
     * prototype property.
     */
    str = JSVAL_TO_STRING(id);
    prototypeAtom = cx->runtime->atomState.classPrototypeAtom;
    if (str == ATOM_TO_STRING(prototypeAtom)) {
        JSObject *proto, *parentProto;
        jsval pval;

        proto = parentProto = NULL;
        if (fun->object != obj && fun->object) {
            /*
             * Clone of a function: make its prototype property value have the
             * same class as the clone-parent's prototype.
             */
            if (!OBJ_GET_PROPERTY(cx, fun->object, (jsid)prototypeAtom, &pval))
                return JS_FALSE;
            if (JSVAL_IS_OBJECT(pval))
                parentProto = JSVAL_TO_OBJECT(pval);
        }

        /*
         * Beware of the wacky case of a user function named Object -- trying
         * to find a prototype for that will recur back here ad perniciem.
         */
        if (!parentProto && fun->atom == cx->runtime->atomState.ObjectAtom)
            return JS_TRUE;

        /*
         * If resolving "prototype" in a clone, clone the parent's prototype.
         * Pass the constructor's (obj's) parent as the prototype parent, to
         * avoid defaulting to parentProto.constructor.__parent__.
         */
        proto = js_NewObject(cx, &js_ObjectClass, parentProto,
                             OBJ_GET_PARENT(cx, obj));
        if (!proto)
            return JS_FALSE;

        /*
         * ECMA says that constructor.prototype is DontEnum | DontDelete for
         * user-defined functions, but DontEnum | ReadOnly | DontDelete for
         * native "system" constructors such as Object or Function.  So lazily
         * set the former here in fun_resolve, but eagerly define the latter
         * in JS_InitClass, with the right attributes.
         */
        if (!js_SetClassPrototype(cx, obj, proto, JSPROP_PERMANENT)) {
            cx->newborn[GCX_OBJECT] = NULL;
            return JS_FALSE;
        }
        *objp = obj;
    }

    return JS_TRUE;
}

static JSBool
fun_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
{
    switch (type) {
      case JSTYPE_FUNCTION:
        *vp = OBJECT_TO_JSVAL(obj);
        return JS_TRUE;
      default:
        return js_TryValueOf(cx, obj, type, vp);
    }
}

static void
fun_finalize(JSContext *cx, JSObject *obj)
{
    JSFunction *fun;

    /* No valid function object should lack private data, but check anyway. */
    fun = (JSFunction *) JS_GetPrivate(cx, obj);
    if (!fun)
        return;
    if (fun->object == obj)
        fun->object = NULL;
    JS_ATOMIC_DECREMENT(&fun->nrefs);
    if (fun->nrefs)
        return;
    if (fun->script)
        js_DestroyScript(cx, fun->script);
    JS_free(cx, fun);
}

#if JS_HAS_XDR

#include "jsxdrapi.h"

enum {
    JSXDR_FUNARG = 1,
    JSXDR_FUNVAR = 2,
    JSXDR_FUNCONST = 3
};

/* XXX store parent and proto, if defined */
static JSBool
fun_xdrObject(JSXDRState *xdr, JSObject **objp)
{
    JSContext *cx;
    JSFunction *fun;
    JSString *atomstr;
    char *propname;
    JSScopeProperty *sprop;
    uint32 userid;              /* NB: holds a signed int-tagged jsval */
    JSAtom *atom;
    uintN i, n, dupflag;
    uint32 type;
#ifdef DEBUG
    uintN nvars = 0, nargs = 0;
#endif

    cx = xdr->cx;
    if (xdr->mode == JSXDR_ENCODE) {
        /*
         * No valid function object should lack private data, but fail soft
         * (return true, no error report) in case one does due to API pilot
         * or internal error.
         */
        fun = (JSFunction *) JS_GetPrivate(cx, *objp);
        if (!fun)
            return JS_TRUE;
        atomstr = fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
    } else {
        fun = js_NewFunction(cx, NULL, NULL, 0, 0, NULL, NULL);
        if (!fun)
            return JS_FALSE;
        atomstr = NULL;
    }

    if (!JS_XDRStringOrNull(xdr, &atomstr) ||
        !JS_XDRUint16(xdr, &fun->nargs) ||
        !JS_XDRUint16(xdr, &fun->extra) ||
        !JS_XDRUint16(xdr, &fun->nvars) ||
        !JS_XDRUint8(xdr, &fun->flags)) {
        return JS_FALSE;
    }

    /* do arguments and local vars */
    if (fun->object) {
        n = fun->nargs + fun->nvars;
        if (xdr->mode == JSXDR_ENCODE) {
            JSScope *scope;
            JSScopeProperty **spvec, *auto_spvec[8];
            void *mark;

            if (n <= sizeof auto_spvec / sizeof auto_spvec[0]) {
                spvec = auto_spvec;
                mark = NULL;
            } else {
                mark = JS_ARENA_MARK(&cx->tempPool);
                JS_ARENA_ALLOCATE_CAST(spvec, JSScopeProperty **, &cx->tempPool,
                                       n * sizeof(JSScopeProperty *));
                if (!spvec) {
                    JS_ReportOutOfMemory(cx);
                    return JS_FALSE;
                }
            }
            scope = OBJ_SCOPE(fun->object);
            for (sprop = SCOPE_LAST_PROP(scope); sprop;
                 sprop = sprop->parent) {
                if (sprop->getter == js_GetArgument) {
                    JS_ASSERT(nargs++ <= fun->nargs);
                    spvec[sprop->shortid] = sprop;
                } else if (sprop->getter == js_GetLocalVariable) {
                    JS_ASSERT(nvars++ <= fun->nvars);
                    spvec[fun->nargs + sprop->shortid] = sprop;
                }
            }
            for (i = 0; i < n; i++) {
                sprop = spvec[i];
                JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);
                type = (i < fun->nargs)
                       ? JSXDR_FUNARG
                       : (sprop->attrs & JSPROP_READONLY)
                       ? JSXDR_FUNCONST
                       : JSXDR_FUNVAR;
                userid = INT_TO_JSVAL(sprop->shortid);
                /* XXX lossy conversion, need new XDR version for ECMAv3 */
                propname = JS_GetStringBytes(ATOM_TO_STRING((JSAtom *)sprop->id));
                if (!propname ||
                    !JS_XDRUint32(xdr, &type) ||
                    !JS_XDRUint32(xdr, &userid) ||
                    !JS_XDRCString(xdr, &propname)) {
                    if (mark)
                        JS_ARENA_RELEASE(&cx->tempPool, mark);
                    return JS_FALSE;
                }
            }
            if (mark)
                JS_ARENA_RELEASE(&cx->tempPool, mark);
        } else {
            JSPropertyOp getter, setter;

            for (i = n; i != 0; i--) {
                uintN attrs = JSPROP_ENUMERATE | JSPROP_PERMANENT;

                if (!JS_XDRUint32(xdr, &type) ||
                    !JS_XDRUint32(xdr, &userid) ||
                    !JS_XDRCString(xdr, &propname)) {
                    return JS_FALSE;
                }
                JS_ASSERT(type == JSXDR_FUNARG || type == JSXDR_FUNVAR ||
                          type == JSXDR_FUNCONST);
                if (type == JSXDR_FUNARG) {
                    getter = js_GetArgument;
                    setter = js_SetArgument;
                    JS_ASSERT(nargs++ <= fun->nargs);
                } else if (type == JSXDR_FUNVAR || type == JSXDR_FUNCONST) {
                    getter = js_GetLocalVariable;
                    setter = js_SetLocalVariable;
                    if (type == JSXDR_FUNCONST)
                        attrs |= JSPROP_READONLY;
                    JS_ASSERT(nvars++ <= fun->nvars);
                } else {
                    getter = NULL;
                    setter = NULL;
                }
                atom = js_Atomize(cx, propname, strlen(propname), 0);
                JS_free(cx, propname);
                if (!atom)
                    return JS_FALSE;

                /* Flag duplicate argument if atom is bound in fun->object. */
                dupflag = SCOPE_GET_PROPERTY(OBJ_SCOPE(fun->object), (jsid)atom)
                          ? SPROP_IS_DUPLICATE
                          : 0;

                if (!js_AddNativeProperty(cx, fun->object, (jsid)atom,
                                          getter, setter, SPROP_INVALID_SLOT,
                                          attrs | JSPROP_SHARED,
                                          SPROP_HAS_SHORTID | dupflag,
                                          JSVAL_TO_INT(userid))) {
                    return JS_FALSE;
                }
            }
        }

⌨️ 快捷键说明

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