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

📄 jsfun.c

📁 Swfdec still is development software, but has also followed a rigid no-crashes-allowed policy. I b
💻 C
📖 第 1 页 / 共 5 页
字号:
    if (fun)        return JS_TRUE;#if JS_HAS_CALL_OBJECT    /*     * NB: (new Function) is not lexically closed by its caller, it's just an     * anonymous function in the top-level scope that its constructor inhabits.     * Thus 'var x = 42; f = new Function("return x"); print(f())' prints 42,     * and so would a call to f from another top-level's script or function.     *     * In older versions, before call objects, a new Function was adopted by     * its running context's globalObject, which might be different from the     * top-level reachable from scopeChain (in HTML frames, e.g.).     */    parent = OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(argv[-2]));#else    /* Set up for dynamic parenting (see js_Invoke in jsinterp.c). */    parent = NULL;#endif    fun = js_NewFunction(cx, obj, NULL, 0, JSFUN_LAMBDA, parent,                         JSVERSION_IS_ECMA(cx->version)                         ? cx->runtime->atomState.anonymousAtom                         : NULL);    if (!fun)        return JS_FALSE;    /*     * Function is static and not called directly by other functions in this     * file, therefore it is callable only as a native function by js_Invoke.     * Find the scripted caller, possibly skipping other native frames such as     * are built for Function.prototype.call or .apply activations that invoke     * Function indirectly from a script.     */    JS_ASSERT(!fp->script && fp->fun && fp->fun->native == Function);    caller = JS_GetScriptedCaller(cx, fp);    if (caller) {        filename = caller->script->filename;        lineno = js_PCToLineNumber(cx, caller->script, caller->pc);        principals = JS_EvalFramePrincipals(cx, fp, caller);    } else {        filename = NULL;        lineno = 0;        principals = NULL;    }    n = argc ? argc - 1 : 0;    if (n > 0) {        /*         * Collect the function-argument arguments into one string, separated         * by commas, then make a tokenstream from that string, and scan it to         * get the arguments.  We need to throw the full scanner at the         * problem, because the argument string can legitimately contain         * comments and linefeeds.  XXX It might be better to concatenate         * everything up into a function definition and pass it to the         * compiler, but doing it this way is less of a delta from the old         * code.  See ECMA 15.3.2.1.         */        args_length = 0;        for (i = 0; i < n; i++) {            /* Collect the lengths for all the function-argument arguments. */            arg = js_ValueToString(cx, argv[i]);            if (!arg)                return JS_FALSE;            argv[i] = STRING_TO_JSVAL(arg);            args_length += JSSTRING_LENGTH(arg);        }        /* Add 1 for each joining comma. */        args_length += n - 1;        /*         * Allocate a string to hold the concatenated arguments, including room         * for a terminating 0.  Mark cx->tempPool for later release, to free         * collected_args and its tokenstream in one swoop.         */        mark = JS_ARENA_MARK(&cx->tempPool);        JS_ARENA_ALLOCATE_CAST(cp, jschar *, &cx->tempPool,                               (args_length+1) * sizeof(jschar));        if (!cp)            return JS_FALSE;        collected_args = cp;        /*         * Concatenate the arguments into the new string, separated by commas.         */        for (i = 0; i < n; i++) {            arg = JSVAL_TO_STRING(argv[i]);            arg_length = JSSTRING_LENGTH(arg);            (void) js_strncpy(cp, JSSTRING_CHARS(arg), arg_length);            cp += arg_length;            /* Add separating comma or terminating 0. */            *cp++ = (i + 1 < n) ? ',' : 0;        }        /*         * Make a tokenstream (allocated from cx->tempPool) that reads from         * the given string.         */        ts = js_NewTokenStream(cx, collected_args, args_length, filename,                               lineno, principals);        if (!ts) {            JS_ARENA_RELEASE(&cx->tempPool, mark);            return JS_FALSE;        }        /* The argument string may be empty or contain no tokens. */        tt = js_GetToken(cx, ts);        if (tt != TOK_EOF) {            for (;;) {                /*                 * Check that it's a name.  This also implicitly guards against                 * TOK_ERROR, which was already reported.                 */                if (tt != TOK_NAME)                    goto bad_formal;                /*                 * Get the atom corresponding to the name from the tokenstream;                 * we're assured at this point that it's a valid identifier.                 */                atom = CURRENT_TOKEN(ts).t_atom;                if (!js_LookupProperty(cx, obj, (jsid)atom, &obj2,                                       (JSProperty **)&sprop)) {                    goto bad_formal;                }                dupflag = 0;                if (sprop) {                    ok = JS_TRUE;                    if (obj2 == obj) {                        const char *name = js_AtomToPrintableString(cx, atom);                        /*                         * A duplicate parameter name. We force a duplicate                         * node on the SCOPE_LAST_PROP(scope) list with the                         * same id, distinguished by the SPROP_IS_DUPLICATE                         * flag, and not mapped by an entry in scope.                         */                        JS_ASSERT(sprop->getter == js_GetArgument);                        ok = name &&                             js_ReportCompileErrorNumber(cx, ts, NULL,                                                         JSREPORT_WARNING |                                                         JSREPORT_STRICT,                                                         JSMSG_DUPLICATE_FORMAL,                                                         name);                        dupflag = SPROP_IS_DUPLICATE;                    }                    OBJ_DROP_PROPERTY(cx, obj2, (JSProperty *)sprop);                    if (!ok)                        goto bad_formal;                    sprop = NULL;                }                if (!js_AddNativeProperty(cx, fun->object, (jsid)atom,                                          js_GetArgument, js_SetArgument,                                          SPROP_INVALID_SLOT,                                          JSPROP_ENUMERATE | JSPROP_PERMANENT |                                          JSPROP_SHARED,                                          SPROP_HAS_SHORTID | dupflag,                                          fun->nargs)) {                    goto bad_formal;                }                fun->nargs++;                /*                 * Get the next token.  Stop on end of stream.  Otherwise                 * insist on a comma, get another name, and iterate.                 */                tt = js_GetToken(cx, ts);                if (tt == TOK_EOF)                    break;                if (tt != TOK_COMMA)                    goto bad_formal;                tt = js_GetToken(cx, ts);            }        }        /* Clean up. */        ok = js_CloseTokenStream(cx, ts);        JS_ARENA_RELEASE(&cx->tempPool, mark);        if (!ok)            return JS_FALSE;    }    if (argc) {        str = js_ValueToString(cx, argv[argc-1]);    } else {        /* Can't use cx->runtime->emptyString because we're called too early. */        str = js_NewStringCopyZ(cx, js_empty_ucstr, 0);    }    if (!str)        return JS_FALSE;    if (argv) {        /* Use the last arg (or this if argc == 0) as a local GC root. */        argv[(intN)(argc-1)] = STRING_TO_JSVAL(str);    }    mark = JS_ARENA_MARK(&cx->tempPool);    ts = js_NewTokenStream(cx, JSSTRING_CHARS(str), JSSTRING_LENGTH(str),                           filename, lineno, principals);    if (!ts) {        ok = JS_FALSE;    } else {        ok = js_CompileFunctionBody(cx, ts, fun) &&             js_CloseTokenStream(cx, ts);    }    JS_ARENA_RELEASE(&cx->tempPool, mark);    return ok;bad_formal:    /*     * Report "malformed formal parameter" iff no illegal char or similar     * scanner error was already reported.     */    if (!(ts->flags & TSF_ERROR))        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_FORMAL);    /*     * Clean up the arguments string and tokenstream if we failed to parse     * the arguments.     */    (void)js_CloseTokenStream(cx, ts);    JS_ARENA_RELEASE(&cx->tempPool, mark);    return JS_FALSE;}JSObject *js_InitFunctionClass(JSContext *cx, JSObject *obj){    JSObject *proto;    JSAtom *atom;    JSFunction *fun;    proto = JS_InitClass(cx, obj, NULL, &js_FunctionClass, Function, 1,                         function_props, function_methods, NULL, NULL);    if (!proto)        return NULL;    atom = js_Atomize(cx, js_FunctionClass.name, strlen(js_FunctionClass.name),                      0);    if (!atom)        goto bad;    fun = js_NewFunction(cx, proto, NULL, 0, 0, obj, NULL);    if (!fun)        goto bad;    fun->script = js_NewScript(cx, 0, 0, 0);    if (!fun->script)        goto bad;    return proto;bad:    cx->newborn[GCX_OBJECT] = NULL;    return NULL;}#if JS_HAS_CALL_OBJECTJSObject *js_InitCallClass(JSContext *cx, JSObject *obj){    return JS_InitClass(cx, obj, NULL, &js_CallClass, NULL, 0,                        call_props, NULL, NULL, NULL);}#endifJSFunction *js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,               uintN flags, JSObject *parent, JSAtom *atom){    JSFunction *fun;    /* Allocate a function struct. */    fun = (JSFunction *) JS_malloc(cx, sizeof *fun);    if (!fun)        return NULL;    /* If funobj is null, allocate an object for it. */    if (funobj) {        OBJ_SET_PARENT(cx, funobj, parent);    } else {        funobj = js_NewObject(cx, &js_FunctionClass, NULL, parent);        if (!funobj) {            JS_free(cx, fun);            return NULL;        }    }    /* Initialize all function members. */    fun->nrefs = 0;    fun->object = NULL;    fun->native = native;    fun->script = NULL;    fun->swf = NULL;    fun->nargs = nargs;    fun->extra = 0;    fun->nvars = 0;    fun->flags = flags & JSFUN_FLAGS_MASK;    fun->spare = 0;    fun->atom = atom;    fun->clasp = NULL;    /* Link fun to funobj and vice versa. */    if (!js_LinkFunctionObject(cx, fun, funobj)) {        cx->newborn[GCX_OBJECT] = NULL;        JS_free(cx, fun);        return NULL;    }    return fun;}JSObject *js_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent){    JSObject *newfunobj;    JSFunction *fun;    JS_ASSERT(OBJ_GET_CLASS(cx, funobj) == &js_FunctionClass);    newfunobj = js_NewObject(cx, &js_FunctionClass, funobj, parent);    if (!newfunobj)        return NULL;    fun = (JSFunction *) JS_GetPrivate(cx, funobj);    if (!js_LinkFunctionObject(cx, fun, newfunobj)) {        cx->newborn[GCX_OBJECT] = NULL;        return NULL;    }    return newfunobj;}JSBooljs_LinkFunctionObject(JSContext *cx, JSFunction *fun, JSObject *funobj){    if (!fun->object)        fun->object = funobj;    if (!JS_SetPrivate(cx, funobj, fun))        return JS_FALSE;    JS_ATOMIC_INCREMENT(&fun->nrefs);    return JS_TRUE;}JSFunction *js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative native,                  uintN nargs, uintN attrs){    JSFunction *fun;    fun = js_NewFunction(cx, NULL, native, nargs, attrs, obj, atom);    if (!fun)        return NULL;    if (!OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, OBJECT_TO_JSVAL(fun->object),                             NULL, NULL, attrs & ~JSFUN_FLAGS_MASK, NULL)) {        return NULL;    }    return fun;}#if (JSV2F_CONSTRUCT & JSV2F_SEARCH_STACK)# error "JSINVOKE_CONSTRUCT and JSV2F_SEARCH_STACK are not disjoint!"#endifJSFunction *js_ValueToFunction(JSContext *cx, jsval *vp, uintN flags){    jsval v;    JSObject *obj;    v = *vp;    obj = NULL;    if (JSVAL_IS_OBJECT(v)) {        obj = JSVAL_TO_OBJECT(v);        if (obj && OBJ_GET_CLASS(cx, obj) != &js_FunctionClass) {            if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &v))                return NULL;            obj = JSVAL_IS_FUNCTION(cx, v) ? JSVAL_TO_OBJECT(v) : NULL;        }    }    if (!obj) {        js_ReportIsNotFunction(cx, vp, flags);        return NULL;    }    return (JSFunction *) JS_GetPrivate(cx, obj);}voidjs_ReportIsNotFunction(JSContext *cx, jsval *vp, uintN flags){    JSType type;    JSString *fallback;    JSString *str;    /*     * We provide the typename as the fallback to handle the case when     * valueOf is not a function, which prevents ValueToString from being     * called as the default case inside js_DecompileValueGenerator (and     * so recursing back to here).     */    type = JS_TypeOfValue(cx, *vp);    fallback = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]);    str = js_DecompileValueGenerator(cx,                                     (flags & JSV2F_SEARCH_STACK)                                     ? JSDVG_SEARCH_STACK                                     : cx->fp                                     ? vp - cx->fp->sp                                     : JSDVG_IGNORE_STACK,                                     *vp,                                     fallback);    if (str) {        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,                             (uintN)((flags & JSV2F_CONSTRUCT)                                     ? JSMSG_NOT_CONSTRUCTOR                                     : JSMSG_NOT_FUNCTION),                             JS_GetStringBytes(str));    }}

⌨️ 快捷键说明

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