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

📄 jsfun.c

📁 一个基于alice开发的机器人
💻 C
📖 第 1 页 / 共 5 页
字号:
    }

    if (!js_XDRScript(xdr, &fun->script, NULL))
        return JS_FALSE;

    if (xdr->mode == JSXDR_DECODE) {
        *objp = fun->object;
        if (atomstr) {
            fun->atom = js_AtomizeString(cx, atomstr, 0);
            if (!fun->atom)
                return JS_FALSE;

            if (!OBJ_DEFINE_PROPERTY(cx, cx->globalObject,
                                     (jsid)fun->atom, OBJECT_TO_JSVAL(*objp),
                                     NULL, NULL, JSPROP_ENUMERATE,
                                     NULL)) {
                return JS_FALSE;
            }
        }

        js_CallNewScriptHook(cx, fun->script, fun);
    }

    return JS_TRUE;
}

#else  /* !JS_HAS_XDR */

#define fun_xdrObject NULL

#endif /* !JS_HAS_XDR */

#if JS_HAS_INSTANCEOF

/*
 * [[HasInstance]] internal method for Function objects: fetch the .prototype
 * property of its 'this' parameter, and walks the prototype chain of v (only
 * if v is an object) returning true if .prototype is found.
 */
static JSBool
fun_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
{
    jsval pval, cval;
    JSString *str;
    JSObject *proto, *obj2;
    JSFunction *cfun, *ofun;

    if (!OBJ_GET_PROPERTY(cx, obj,
                          (jsid)cx->runtime->atomState.classPrototypeAtom,
                          &pval)) {
        return JS_FALSE;
    }

    if (JSVAL_IS_PRIMITIVE(pval)) {
        /*
         * Throw a runtime error if instanceof is called on a function that
         * has a non-object as its .prototype value.
         */
        str = js_DecompileValueGenerator(cx, -1, OBJECT_TO_JSVAL(obj), NULL);
        if (str) {
            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                 JSMSG_BAD_PROTOTYPE, JS_GetStringBytes(str));
        }
        return JS_FALSE;
    }

    proto = JSVAL_TO_OBJECT(pval);
    if (!js_IsDelegate(cx, proto, v, bp))
        return JS_FALSE;

    if (!*bp && !JSVAL_IS_PRIMITIVE(v)) {
        /*
         * Extension for "brutal sharing" of standard class constructors: if
         * a script is compiled using a single, shared set of constructors, in
         * particular Function and RegExp, but executed many times using other
         * sets of standard constructors, then (/re/ instanceof RegExp), e.g.,
         * will be false.
         *
         * We extend instanceof in this case to look for a matching native or
         * script underlying the function object found in the 'constructor'
         * property of the object in question (which is JSVAL_TO_OBJECT(v)),
         * or found in the 'constructor' property of one of its prototypes.
         *
         * See also jsexn.c, where the *Error constructors are defined, each
         * with its own native function, to satisfy (e instanceof Error) even
         * when exceptions cross standard-class sharing boundaries.  Note that
         * Error.prototype may not lie on e's __proto__ chain in that case.
         */
        obj2 = JSVAL_TO_OBJECT(v);
        do {
            if (!OBJ_GET_PROPERTY(cx, obj2,
                                  (jsid)cx->runtime->atomState.constructorAtom,
                                  &cval)) {
                return JS_FALSE;
            }

            if (JSVAL_IS_FUNCTION(cx, cval)) {
                cfun = (JSFunction *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(cval));
                ofun = (JSFunction *) JS_GetPrivate(cx, obj);
                if (cfun->native == ofun->native &&
                    cfun->script == ofun->script) {
                    *bp = JS_TRUE;
                    break;
                }
            }
        } while ((obj2 = OBJ_GET_PROTO(cx, obj2)) != NULL);
    }

    return JS_TRUE;
}

#else  /* !JS_HAS_INSTANCEOF */

#define fun_hasInstance NULL

#endif /* !JS_HAS_INSTANCEOF */

static uint32
fun_mark(JSContext *cx, JSObject *obj, void *arg)
{
    JSFunction *fun;

    fun = (JSFunction *) JS_GetPrivate(cx, obj);
    if (fun) {
        if (fun->atom)
            GC_MARK_ATOM(cx, fun->atom, arg);
        if (fun->script)
            js_MarkScript(cx, fun->script, arg);
    }
    return 0;
}

/*
 * Reserve two slots in all function objects for XPConnect.  Note that this
 * does not bloat every instance, only those on which reserved slots are set,
 * and those on which ad-hoc properties are defined.
 */
JSClass js_FunctionClass = {
    js_Function_str,
    JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(2),
    JS_PropertyStub,  JS_PropertyStub,
    fun_getProperty,  JS_PropertyStub,
    JS_EnumerateStub, (JSResolveOp)fun_resolve,
    fun_convert,      fun_finalize,
    NULL,             NULL,
    NULL,             NULL,
    fun_xdrObject,    fun_hasInstance,
    fun_mark,         0
};

JSBool
js_fun_toString(JSContext *cx, JSObject *obj, uint32 indent,
                uintN argc, jsval *argv, jsval *rval)
{
    jsval fval;
    JSFunction *fun;
    JSString *str;

    if (!argv) {
        JS_ASSERT(JS_ObjectIsFunction(cx, obj));
    } else {
        fval = argv[-1];
        if (!JSVAL_IS_FUNCTION(cx, fval)) {
            /*
             * If we don't have a function to start off with, try converting
             * the object to a function.  If that doesn't work, complain.
             */
            if (JSVAL_IS_OBJECT(fval)) {
                obj = JSVAL_TO_OBJECT(fval);
                if (!OBJ_GET_CLASS(cx, obj)->convert(cx, obj, JSTYPE_FUNCTION,
                                                     &fval)) {
                    return JS_FALSE;
                }
            }
            if (!JSVAL_IS_FUNCTION(cx, fval)) {
                JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                     JSMSG_INCOMPATIBLE_PROTO,
                                     js_Function_str, js_toString_str,
                                     JS_GetTypeName(cx,
                                                    JS_TypeOfValue(cx, fval)));
                return JS_FALSE;
            }
        }

        obj = JSVAL_TO_OBJECT(fval);
    }

    fun = (JSFunction *) JS_GetPrivate(cx, obj);
    if (!fun)
        return JS_TRUE;
    if (argc && !js_ValueToECMAUint32(cx, argv[0], &indent))
        return JS_FALSE;
    str = JS_DecompileFunction(cx, fun, (uintN)indent);
    if (!str)
        return JS_FALSE;
    *rval = STRING_TO_JSVAL(str);
    return JS_TRUE;
}

static JSBool
fun_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    return js_fun_toString(cx, obj, 0, argc, argv, rval);
}

#if JS_HAS_TOSOURCE
static JSBool
fun_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    return js_fun_toString(cx, obj, JS_DONT_PRETTY_PRINT, argc, argv, rval);
}
#endif

static const char js_call_str[] = "call";

#if JS_HAS_CALL_FUNCTION
static JSBool
fun_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    jsval fval, *sp, *oldsp;
    void *mark;
    uintN i;
    JSStackFrame *fp;
    JSBool ok;

    if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &argv[-1]))
        return JS_FALSE;
    fval = argv[-1];

    if (!JSVAL_IS_FUNCTION(cx, fval)) {
        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                             JSMSG_INCOMPATIBLE_PROTO,
                             js_Function_str, js_call_str,
                             JS_GetStringBytes(JS_ValueToString(cx, fval)));
        return JS_FALSE;
    }

    if (argc == 0) {
        /* Call fun with its parent as the 'this' parameter if no args. */
        obj = OBJ_GET_PARENT(cx, obj);
    } else {
        /* Otherwise convert the first arg to 'this' and skip over it. */
        if (!js_ValueToObject(cx, argv[0], &obj))
            return JS_FALSE;
        argc--;
        argv++;
    }

    /* Allocate stack space for fval, obj, and the args. */
    sp = js_AllocStack(cx, 2 + argc, &mark);
    if (!sp)
        return JS_FALSE;

    /* Push fval, obj, and the args. */
    *sp++ = fval;
    *sp++ = OBJECT_TO_JSVAL(obj);
    for (i = 0; i < argc; i++)
        *sp++ = argv[i];

    /* Lift current frame to include the args and do the call. */
    fp = cx->fp;
    oldsp = fp->sp;
    fp->sp = sp;
    ok = js_Invoke(cx, argc, JSINVOKE_INTERNAL | JSINVOKE_SKIP_CALLER);

    /* Store rval and pop stack back to our frame's sp. */
    *rval = fp->sp[-1];
    fp->sp = oldsp;
    js_FreeStack(cx, mark);
    return ok;
}
#endif /* JS_HAS_CALL_FUNCTION */

#if JS_HAS_APPLY_FUNCTION
static JSBool
fun_apply(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    jsval fval, *sp, *oldsp;
    JSObject *aobj;
    jsuint length;
    void *mark;
    uintN i;
    JSBool ok;
    JSStackFrame *fp;

    if (argc == 0) {
        /* Will get globalObject as 'this' and no other agurments. */
        return fun_call(cx, obj, argc, argv, rval);
    }

    if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &argv[-1]))
        return JS_FALSE;
    fval = argv[-1];

    if (!JSVAL_IS_FUNCTION(cx, fval)) {
        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                             JSMSG_INCOMPATIBLE_PROTO,
                             js_Function_str, "apply",
                             JS_GetStringBytes(JS_ValueToString(cx, fval)));
        return JS_FALSE;
    }

    /* Quell GCC overwarnings. */
    aobj = NULL;
    length = 0;

    if (argc >= 2) {
        /* If the 2nd arg is null or void, call the function with 0 args. */
        if (JSVAL_IS_NULL(argv[1]) || JSVAL_IS_VOID(argv[1])) {
            argc = 0;
        } else {
            /* The second arg must be an array (or arguments object). */
            if (JSVAL_IS_PRIMITIVE(argv[1]) ||
                (aobj = JSVAL_TO_OBJECT(argv[1]),
                OBJ_GET_CLASS(cx, aobj) != &js_ArgumentsClass &&
                OBJ_GET_CLASS(cx, aobj) != &js_ArrayClass))
            {
                JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                     JSMSG_BAD_APPLY_ARGS);
                return JS_FALSE;
            }
            if (!js_GetLengthProperty(cx, aobj, &length))
                return JS_FALSE;
        }
    }

    /* Convert the first arg to 'this' and skip over it. */
    if (!js_ValueToObject(cx, argv[0], &obj))
        return JS_FALSE;

    /* Allocate stack space for fval, obj, and the args. */
    argc = (uintN)JS_MIN(length, ARGC_LIMIT - 1);
    sp = js_AllocStack(cx, 2 + argc, &mark);
    if (!sp)
        return JS_FALSE;

    /* Push fval, obj, and aobj's elements as args. */
    *sp++ = fval;
    *sp++ = OBJECT_TO_JSVAL(obj);
    for (i = 0; i < argc; i++) {
        ok = JS_GetElement(cx, aobj, (jsint)i, sp);
        if (!ok)
            goto out;
        sp++;
    }

    /* Lift current frame to include the args and do the call. */
    fp = cx->fp;
    oldsp = fp->sp;
    fp->sp = sp;
    ok = js_Invoke(cx, argc, JSINVOKE_INTERNAL | JSINVOKE_SKIP_CALLER);

    /* Store rval and pop stack back to our frame's sp. */
    *rval = fp->sp[-1];
    fp->sp = oldsp;
out:
    js_FreeStack(cx, mark);
    return ok;
}
#endif /* JS_HAS_APPLY_FUNCTION */

static JSFunctionSpec function_methods[] = {
#if JS_HAS_TOSOURCE
    {js_toSource_str,   fun_toSource,   0,0,0},
#endif
    {js_toString_str,   fun_toString,   1,0,0},
#if JS_HAS_APPLY_FUNCTION
    {"apply",           fun_apply,      2,0,0},
#endif
#if JS_HAS_CALL_FUNCTION
    {js_call_str,       fun_call,       1,0,0},
#endif
    {0,0,0,0,0}
};

JSBool
js_IsIdentifier(JSString *str)
{
    size_t n;
    jschar *s, c;

    n = JSSTRING_LENGTH(str);
    if (n == 0)
        return JS_FALSE;
    s = JSSTRING_CHARS(str);
    c = *s;
    if (!JS_ISIDENT_START(c))
        return JS_FALSE;
    for (n--; n != 0; n--) {
        c = *++s;
        if (!JS_ISIDENT(c))
            return JS_FALSE;
    }
    return JS_TRUE;
}

static JSBool
Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    JSStackFrame *fp, *caller;
    JSFunction *fun;
    JSObject *parent;
    uintN i, n, lineno, dupflag;
    JSAtom *atom;
    const char *filename;
    JSObject *obj2;
    JSScopeProperty *sprop;
    JSString *str, *arg;

⌨️ 快捷键说明

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