You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

208 lines
4.7 KiB

/*
* E5 Section 15.3.2: function constructor argument list is not
* necessarily just identifier names, a call argument may contain
* multiple argument declarations.
*
* The arguments joined with "," should parse as a FormalParameterList_opt.
* Apparently this means that the source can contain newlines and comments
* too!
*/
/*===
6
6
6
6
6
6
===*/
var f1, f2, f3, f4, f5, f6;
try {
print(eval('f1 = new Function("a", "b", "c", "return a+b+c"); f1(1,2,3);'));
} catch (e) {
print(e.name);
}
try {
print(eval('f2 = new Function("a, b, c", "return a+b+c"); f2(1,2,3);'));
} catch (e) {
print(e.name);
}
try {
print(eval('f3 = new Function("a, b", "c", "return a+b+c"); f3(1,2,3);'));
} catch (e) {
print(e.name);
}
try {
print(eval('f4 = new Function("a /*first*/", "b /*second*/, c /*third*/", "return a+b+c"); f4(1,2,3);'));
} catch (e) {
print(e.name);
}
try {
/* It's unclear in the specification whether this should be a SyntaxError or not.
* If one naively constructs a parse string as:
*
* function (a, b, c //last) { return a+b+c }
*
* Then this would be a syntax error. On the other hand, the specification does not
* say that this should be done; rather, the argument list, joined by commas, should
* be parsed as a FormalParameterList_opt and the body should be parsed as a
* FunctionBody, separately. So we interpret this to mean that this should actually
* work correctly, as comments are allowed anywhere in source code. The formal
* argument list to be parsed is:
*
* a,b, c // last
*
* This fails in V8 and Rhino, though. For example, Rhino will complain:
*
* SyntaxError: missing ) after formal parameters
*
* V8 (Node) will complain:
*
* [SyntaxError: Unexpected token return]
*
*/
print(eval('f5 = new Function("a", "b, c // last", "return a+b+c"); f5(1,2,3);'));
} catch (e) {
print(e.name);
}
try {
/* Here the format argument list to be parsed would be:
*
* a
* ,b
* ,c // last [newline]
*
* Again, this should parse as a FormalParameterList_opt but fails to do so in
* Rhino and V8. Rhino will complain:
*
* SyntaxError: unterminated string literal
*
* whereas V8 will complain:
*
* [SyntaxError: Unexpected token ILLEGAL]
*/
eval('f6 = new Function("a\n", "b\n,c // last\n", "return a+b+c"); f6(1,2,3);');
} catch (e) {
print(e.name);
}
/*===
function () {if (1) {print('foo')}}
foo
SyntaxError
===*/
/* It would be tempting to implement the Function constuctor as follows:
*
* 1. Coerce the argument names and join with commas -> formals
* 2. Coerce the function body -> body
* 3. Let T = 'function(' + formals + ') { + body + '}'
*
* However, this would not be correct. E5 Section 15.3.2.1 step 7
* requires that 'formals' must parse as a FormalParameterList_opt
* by itself.
*
* The test case below ensures that this is indeed the case. The
* following function:
*
* function () {if (1) {print('foo')}}
* ==========--------===-------------=
*
* is split into parts in a sneaky way.
*/
var fake_arg = ") {if (1";
var fake_body = "print('foo')}";
var fake_val;
try {
// this should work (parens used to ensure function expression parses)
fake_val = 'function (' + fake_arg + ') {' + fake_body + '}';
print(fake_val);
eval('(' + fake_val + ') ()');
} catch (e) {
print(e.name);
}
try {
// this should not (but does, e.g. on Rhino)
new Function(fake_arg, fake_body)();
} catch (e) {
print(e.name);
}
/*===
OBJ1
OBJ2
OBJ3
7
===*/
/* The coercion order of arguments is specified to match function argument
* order, i.e. ToString() coerce first the formal arguments and finally
* the body.
*/
var obj1 = {
toString: function() { print('OBJ1'); return 'x'; }
};
var obj2 = {
toString: function() { print('OBJ2'); return 'y'; }
};
var obj3 = {
toString: function() { print('OBJ3'); return 'print(x+y)'; }
};
try {
new Function(obj1, obj2, obj3)(3,4);
} catch (e) {
print(e.name);
}
/*===
undefined
foo
foo 1
foo 1 2
===*/
/* Misc additional tests for implementation-dependent reasons. */
try {
// no arguments or body -> body evaluates to an empty string, so
// should behave like "function() {}", i.e. return undefined
print(new Function()());
} catch (e) {
print(e.name);
}
try {
// empty args
new Function("print('foo')")();
} catch (e) {
print(e.name);
}
try {
// 1 arg
new Function("x", "print('foo', x)")(1);
} catch (e) {
print(e.name);
}
try {
// 2 args
new Function("x", "y", "print('foo', x, y)")(1, 2);
} catch (e) {
print(e.name);
}