mirror of https://github.com/svaarala/duktape.git
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.
214 lines
4.8 KiB
214 lines
4.8 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!
|
|
*/
|
|
|
|
/*---
|
|
{
|
|
"knownissue": "corner cases for 'new Function()' when arguments and code are given as strings"
|
|
}
|
|
---*/
|
|
|
|
/*===
|
|
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);
|
|
}
|
|
|
|
|