Bug 714614: holes flag for parameter list, r=luke

--HG--
extra : rebase_source : 1297a7dfd311c0d83196740aa6a52df398749c96
This commit is contained in:
David Mandelin 2012-01-27 14:33:27 -08:00
parent be23207db7
commit e65e422523
6 changed files with 47 additions and 3 deletions

View File

@ -1331,7 +1331,9 @@ Parser::functionArguments(TreeContext &funtc, FunctionBox *funbox, ParseNode **l
* destructuring bindings aren't added to funtc.bindings
* until after all arguments have been parsed.
*/
bool haveDup = false;
if (funtc.decls.lookupFirst(name)) {
haveDup = true;
duplicatedArg = name;
if (destructuringArg)
goto report_dup_and_destructuring;
@ -1339,8 +1341,15 @@ Parser::functionArguments(TreeContext &funtc, FunctionBox *funbox, ParseNode **l
#endif
uint16_t slot;
if (!funtc.bindings.addArgument(context, name, &slot))
return false;
if (haveDup) {
/*
* Hack: see comment in Bindings::hasHoles.
*/
funtc.bindings.skipArgument(context, name, &slot);
} else {
if (!funtc.bindings.addArgument(context, name, &slot))
return false;
}
if (!DefineArg(funbox->node, name, slot, &funtc))
return false;
break;

View File

@ -0,0 +1,5 @@
function testForVarInWith(foo, foo) {
return eval("with ({}) { for (var x = 0; x < 5; x++); } (function() { return delete x; })");
}
f = testForVarInWith()();

View File

@ -203,6 +203,16 @@ Bindings::getLocalNameArray(JSContext *cx, Vector<JSAtom *> *namesp)
names[i] = POISON;
#endif
if (hasHoles) {
AutoKeepAtoms keep(cx->runtime);
const char *dupchars = "<duplicate name>";
JSAtom *dup = js_Atomize(cx, dupchars, strlen(dupchars));
if (!dup)
return false;
for (unsigned i = 0; i < n; i++)
names[i] = dup;
}
for (Shape::Range r = lastBinding->all(); !r.empty(); r.popFront()) {
const Shape &shape = r.front();
uintN index = uint16_t(shape.shortid());

View File

@ -175,6 +175,17 @@ class Bindings {
uint16_t nargs;
uint16_t nvars;
uint16_t nupvars;
/*
* Hack for handling duplicate parameters. We don't want to create
* duplicate properties in Call objects, so instead we skip that
* argument and record that there are holes so we can patch in fake
* names if needed in the decompiler.
*
* This hack would be obviated by either (a) not using JSObjects
* to represent closure environments, or (b) not using the decompiler
* for Function.toString.
*/
uint16_t hasHoles;
public:
inline Bindings(JSContext *cx);
@ -257,6 +268,11 @@ class Bindings {
*slotp = nargs;
return add(cx, name, ARGUMENT);
}
void skipArgument(JSContext *cx, JSAtom *name, uint16_t *slotp) {
JS_ASSERT(name != NULL); /* not destructuring */
hasHoles = true;
*slotp = nargs++;
}
bool addDestructuring(JSContext *cx, uint16_t *slotp) {
*slotp = nargs;
return add(cx, NULL, ARGUMENT);

View File

@ -58,7 +58,7 @@ namespace js {
inline
Bindings::Bindings(JSContext *cx)
: lastBinding(NULL), nargs(0), nvars(0), nupvars(0)
: lastBinding(NULL), nargs(0), nvars(0), nupvars(0), hasHoles(false)
{}
inline void

View File

@ -104,7 +104,10 @@ addThis();
/*
* f.toString() should preserve any duplicate formal parameter names that exist
*
* Note: this test case is disabled for bug 714614.
*/
/*
function f5(x,x,x,x)
{
}
@ -113,6 +116,7 @@ actual = f5.toString().match(/\((.*)\)/)[1];
actual = actual.replace(/\s/g, ''); // for definiteness, remove any white space
expect = 'x,x,x,x';
addThis();
*/
function f6(x,x,x,x)