if (sprop && obj2 == obj) {
Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    JSFunction *fun;    JSObject *parent;    uintN i, n, lineno;    JSAtom *atom;    const char *filename;    JSObject *obj2;    JSScopeProperty *sprop;    JSString *str, *arg;    JSStackFrame *fp;    JSTokenStream *ts;    JSPrincipals *principals;    jschar *collected_args, *cp;    size_t args_length;    JSTokenType tt;    if (cx->fp && !cx->fp->constructing) {	obj = js_NewObject(cx, &js_FunctionClass, NULL, NULL);	if (!obj)	    return JS_FALSE;	*rval = OBJECT_TO_JSVAL(obj);    }    fun = JS_GetPrivate(cx, obj);    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 Call in jsinterp.c). */    parent = NULL;#endif    fun = js_NewFunction(cx, obj, NULL, 0, 0, parent,			 (JSVERSION_IS_ECMA(cx->version))			 ? cx->runtime->atomState.anonymousAtom                         : NULL);    if (!fun)	return JS_FALSE;    if ((fp = cx->fp) != NULL && (fp = fp->down) != NULL && fp->script) {	filename = fp->script->filename;	lineno = js_PCToLineNumber(fp->script, fp->pc);        principals = fp->script->principals;    } 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 = JSVAL_TO_STRING(argv[i]);            args_length += arg->length;        }        /* Add 1 for each joining comma. */        args_length += n - 1;        /* Allocate a string to hold the concatenated arguments, including room         * for a terminating 0.         */        cp = collected_args = (jschar *) JS_malloc(cx, (args_length + 1) *                                                   sizeof(jschar));        /* Concatenate the arguments into the new string, separated by commas. */        for (i = 0; i < n; i++) {            arg = JSVAL_TO_STRING(argv[i]);            (void)js_strncpy(cp, arg->chars, arg->length);            cp += arg->length;            /* Add separating comma or terminating 0. */            *(cp++) = (i + 1 < n) ? ',' : 0;        }        /* Make a tokenstream that reads from the given string. */        ts = js_NewTokenStream(cx, collected_args, args_length, filename, lineno,                               principals);        if (!ts) {            JS_free(cx, collected_args);            return JS_FALSE;        }                tt = js_GetToken(cx, ts);        /* The argument string may be empty or contain no tokens. */        if (tt != TOK_EOF) {            while (1) {                /* Check that it's a name.  This also implicitly guards against                 * TOK_ERROR.                 */                if (tt != TOK_NAME) {                    JS_ReportError(cx, "missing formal parameter");                    goto badargs;                }                /* Get the atom corresponding to the name from the tokenstream;                 * we're assured at this point that it's a valid identifier.                 */                atom = ts->token.t_atom;                if (!js_LookupProperty(cx, obj, (jsid)atom, &obj2,                                       (JSProperty **)&sprop)) {                    goto badargs;                }#ifdef CHECK_ARGUMENT_HIDING                if (sprop && obj2 == obj) {                    PR_ASSERT(sprop->getter == js_GetArgument);                    OBJ_DROP_PROPERTY(cx, obj2, (JSProperty *)sprop);                    JS_ReportError(cx, "duplicate formal argument %s",                                   ATOM_BYTES(atom));                    goto badargs;                }#endif                if (sprop)                    OBJ_DROP_PROPERTY(cx, obj2, (JSProperty *)sprop);                if (!js_DefineProperty(cx, obj, (jsid)atom, JSVAL_VOID,                                       js_GetArgument, js_SetArgument,                                       JSPROP_ENUMERATE | JSPROP_PERMANENT,                                       (JSProperty **)&sprop)) {                    goto badargs;                }                PR_ASSERT(sprop);                sprop->id = INT_TO_JSVAL(fun->nargs++);                OBJ_DROP_PROPERTY(cx, obj, (JSProperty *)sprop);                        /* Done with the NAME; get the next token. */                tt = js_GetToken(cx, ts);                /* Stop if we've reached the end of the string. */                if (tt == TOK_EOF)                    break;                /* If a comma is seen, get the next token.  Otherwise, let the                 * loop catch the error.                 */                if (tt == TOK_COMMA)                    tt = js_GetToken(cx, ts);            }        }                /* Clean up. */        JS_free(cx, collected_args);        if (!js_CloseTokenStream(cx, ts))            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[argc-1] = STRING_TO_JSVAL(str);    }    if ((fp = cx->fp) != NULL && (fp = fp->down) != NULL && fp->script) {	filename = fp->script->filename;	lineno = js_PCToLineNumber(fp->script, fp->pc);        principals = fp->script->principals;    } else {	filename = NULL;	lineno = 0;        principals = NULL;    }    ts = js_NewTokenStream(cx, str->chars, str->length, filename, lineno,                           principals);    if (!ts)	return JS_FALSE;    return js_ParseFunctionBody(cx, ts, fun) &&	   js_CloseTokenStream(cx, ts);badargs:    /* Clean up the arguments string and tokenstream if we failed to parse     * the arguments.     */    JS_free(cx, collected_args);    (void)js_CloseTokenStream(cx, ts);    return JS_FALSE;}