2020-10-21 21:16:45 +00:00
|
|
|
|
/*
|
|
|
|
|
These tests deliberately produce syntax errors to check what line the parser thinks we're on.
|
LibJS: Tweak generated source in 'new Function()' to match ES 2015 spec
ES 5(.1) described parsing of the function body string as:
https://www.ecma-international.org/ecma-262/5.1/#sec-15.3.2.1
7. If P is not parsable as a FormalParameterList[opt] then throw a SyntaxError exception.
8. If body is not parsable as FunctionBody then throw a SyntaxError exception.
We implemented it as building the source string of a complete function
and feeding that to the parser, with the same outcome. ES 2015+ does
exactly that, but with newlines at certain positions:
https://tc39.es/ecma262/#sec-createdynamicfunction
16. Let bodyString be the string-concatenation of 0x000A (LINE FEED), ? ToString(bodyArg), and 0x000A (LINE FEED).
17. Let prefix be the prefix associated with kind in Table 49.
18. Let sourceString be the string-concatenation of prefix, " anonymous(", P, 0x000A (LINE FEED), ") {", bodyString, and "}".
This patch updates the generated source string to match these
requirements. This will make certain edge cases work, e.g.
'new Function("-->")', where the user supplied input must be placed on
its own line to be valid syntax.
2020-10-29 18:11:35 +00:00
|
|
|
|
Note that line numbers are higher than you might expect as the parsed code is:
|
|
|
|
|
|
|
|
|
|
function anonymous(
|
|
|
|
|
) {
|
|
|
|
|
<code>
|
|
|
|
|
}
|
2020-10-21 21:16:45 +00:00
|
|
|
|
|
|
|
|
|
⚠ PLEASE MAKE SURE TO NOT LET YOUR EDITOR REMOVE THE LS/PS LINE TERMINATORS!
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
test("LINE FEED is a line terminator", () => {
|
|
|
|
|
expect(() => {
|
|
|
|
|
Function("\n\n@");
|
2022-01-15 16:26:06 +00:00
|
|
|
|
}).toThrowWithMessage(
|
|
|
|
|
SyntaxError,
|
|
|
|
|
"Unexpected token Invalid. Expected CurlyClose (line: 4, column: 1)"
|
|
|
|
|
);
|
2020-10-21 21:16:45 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("CARRIAGE RETURN is a line terminator", () => {
|
|
|
|
|
expect(() => {
|
|
|
|
|
Function("\r\r@");
|
2022-01-15 16:26:06 +00:00
|
|
|
|
}).toThrowWithMessage(
|
|
|
|
|
SyntaxError,
|
|
|
|
|
"Unexpected token Invalid. Expected CurlyClose (line: 4, column: 1)"
|
|
|
|
|
);
|
2020-10-21 21:16:45 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("LINE SEPARATOR is a line terminator", () => {
|
|
|
|
|
expect(() => {
|
2020-10-25 18:36:10 +00:00
|
|
|
|
Function("
@");
|
2022-01-15 16:26:06 +00:00
|
|
|
|
}).toThrowWithMessage(
|
|
|
|
|
SyntaxError,
|
|
|
|
|
"Unexpected token Invalid. Expected CurlyClose (line: 4, column: 1)"
|
|
|
|
|
);
|
2020-10-21 21:16:45 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("PARAGRAPH SEPARATOR is a line terminator", () => {
|
|
|
|
|
expect(() => {
|
2020-10-25 18:36:10 +00:00
|
|
|
|
Function("
@");
|
2022-01-15 16:26:06 +00:00
|
|
|
|
}).toThrowWithMessage(
|
|
|
|
|
SyntaxError,
|
|
|
|
|
"Unexpected token Invalid. Expected CurlyClose (line: 4, column: 1)"
|
|
|
|
|
);
|
2020-10-21 21:16:45 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("CR LF is counted as only one line terminator", () => {
|
|
|
|
|
expect(() => {
|
|
|
|
|
Function("\r\n\r\n@");
|
2022-01-15 16:26:06 +00:00
|
|
|
|
}).toThrowWithMessage(
|
|
|
|
|
SyntaxError,
|
|
|
|
|
"Unexpected token Invalid. Expected CurlyClose (line: 4, column: 1)"
|
|
|
|
|
);
|
2020-10-21 21:16:45 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("LF/CR are not allowed in string literal", () => {
|
|
|
|
|
expect(() => {
|
|
|
|
|
Function(`"
|
|
|
|
|
"`);
|
|
|
|
|
}).toThrowWithMessage(SyntaxError, "Unexpected token UnterminatedStringLiteral");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("LS/PS are allowed in string literal", () => {
|
|
|
|
|
expect(`"
"`).toEval();
|
|
|
|
|
expect(`"
"`).toEval();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("line terminators can be mixed (but please don't)", () => {
|
|
|
|
|
expect(() => {
|
2020-10-25 18:36:10 +00:00
|
|
|
|
Function("\r
\r\n
\n\r@");
|
2022-01-15 16:26:06 +00:00
|
|
|
|
}).toThrowWithMessage(
|
|
|
|
|
SyntaxError,
|
|
|
|
|
"Unexpected token Invalid. Expected CurlyClose (line: 8, column: 1)"
|
|
|
|
|
);
|
2020-10-21 21:16:45 +00:00
|
|
|
|
});
|
2020-10-25 18:36:10 +00:00
|
|
|
|
|
|
|
|
|
test("all line terminators are valid for line continuations", () => {
|
|
|
|
|
expect(Function('return "a\\\nb"')()).toBe("ab");
|
|
|
|
|
expect(Function('return "a\\\rb"')()).toBe("ab");
|
2021-09-01 16:34:19 +00:00
|
|
|
|
expect(Function('return "a\\\r\nb"')()).toBe("ab");
|
2020-10-25 18:36:10 +00:00
|
|
|
|
expect(Function('return "a\\
b"')()).toBe("ab");
|
|
|
|
|
expect(Function('return "a\\
b"')()).toBe("ab");
|
|
|
|
|
});
|
2021-09-01 16:34:19 +00:00
|
|
|
|
|
|
|
|
|
test("template-literals raw and real value", () => {
|
|
|
|
|
let lastTemplate;
|
|
|
|
|
let lastRaw;
|
|
|
|
|
|
|
|
|
|
function tag(cs) {
|
|
|
|
|
lastTemplate = cs[0];
|
|
|
|
|
lastRaw = cs.raw[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function checkTemplate(string_value, expected_template, expected_raw) {
|
|
|
|
|
eval("tag`" + string_value + "`");
|
|
|
|
|
expect(lastTemplate).toBe(expected_template);
|
|
|
|
|
expect(lastRaw).toBe(expected_raw);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
checkTemplate("", "", "");
|
|
|
|
|
checkTemplate("\n", "\n", "\n");
|
|
|
|
|
checkTemplate("\r", "\n", "\n");
|
|
|
|
|
checkTemplate("\r\n", "\n", "\n");
|
|
|
|
|
checkTemplate("\n\r\n", "\n\n", "\n\n");
|
|
|
|
|
|
|
|
|
|
checkTemplate("a\\\nb", "ab", "a\\\nb");
|
|
|
|
|
checkTemplate("a\\\rb", "ab", "a\\\nb");
|
|
|
|
|
checkTemplate("a\\
b", "ab", "a\\
b");
|
|
|
|
|
checkTemplate("a\\
b", "ab", "a\\
b");
|
|
|
|
|
});
|