js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR, JSMSG_DUPLICATE_FORMAL, ATOM_BYTES(atom)); goto bad_formal;
if (!js_ReportCompileErrorNumber(cx, ts, JSREPORT_WARNING | JSREPORT_STRICT, JSMSG_DUPLICATE_FORMAL, ATOM_BYTES(atom))) { goto bad_formal; }
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;    void *mark;    JSTokenStream *ts;    JSPrincipals *principals;    jschar *collected_args, *cp;    size_t args_length;    JSTokenType tt;    jsid oldArgId;    JSBool ok;    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.  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(cp, &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]);	    (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 (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) {	    while (1) {		/*		 * 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;		}		if (sprop && obj2 == obj) {                    if (JS_HAS_STRICT_OPTION(cx)) {                        JS_ASSERT(SPROP_GETTER(sprop, obj) == js_GetArgument);                        OBJ_DROP_PROPERTY(cx, obj2, (JSProperty *)sprop);                        js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,                                                    JSMSG_DUPLICATE_FORMAL,                                                    ATOM_BYTES(atom));                        goto bad_formal;                    }		    /*		     * A duplicate parameter name. We create a dummy symbol		     * entry with property id of the parameter number and set		     * the id to the name of the parameter.  See jsopcode.c:		     * the decompiler knows to treat this case specially.		     */		    oldArgId = (jsid) sprop->id;		    OBJ_DROP_PROPERTY(cx, obj2, (JSProperty *)sprop);		    sprop = NULL;		    if (!js_DefineProperty(cx, obj, oldArgId, JSVAL_VOID,					   js_GetArgument, js_SetArgument,					   JSPROP_ENUMERATE | JSPROP_PERMANENT,					   (JSProperty **)&sprop)) {			goto bad_formal;		    }		    sprop->id = (jsid) atom;		}		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 bad_formal;		}		JS_ASSERT(sprop);		sprop->id = INT_TO_JSVAL(fun->nargs++);		OBJ_DROP_PROPERTY(cx, obj, (JSProperty *)sprop);		/*		 * 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);    }    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;    }    mark = JS_ARENA_MARK(&cx->tempPool);    ts = js_NewTokenStream(cx, str->chars, str->length, filename, lineno,			   principals);    if (!ts) {	ok = JS_FALSE;    } else {	ok = js_ParseFunctionBody(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;}