Skip to content

Commit

Permalink
JavaScript: capture function objects in Self-Invoking Anonymous Funct…
Browse files Browse the repository at this point in the history
…ion Statements

Signed-off-by: Masatake YAMATO <[email protected]>
  • Loading branch information
masatake committed Jul 8, 2022
1 parent 2052bbf commit d0ed6dc
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--sort=no
10 changes: 10 additions & 0 deletions Units/parser-javascript.r/self-invoking-anon-func.d/expected.tags
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
anonymousFunction204aa80e0100 input.js /^(function(x) {$/;" f
a input.js /^ var a = function (o) { return o; };$/;" f function:anonymousFunction204aa80e0100
anonymousFunction204aa80e0200 input.js /^(function(y) {$/;" f
b input.js /^ const b = function (p) { return p; };$/;" f function:anonymousFunction204aa80e0200
anonymousFunction204aa80e0300 input.js /^!function(z) {$/;" f
c input.js /^ const c = function (r) { return r; };$/;" f function:anonymousFunction204aa80e0300
anonymousFunction204aa80e0400 input.js /^console.log("a" + (function (A) {$/;" f
anonymousFunction204aa80e0500 input.js /^}((function (B) {$/;" f
anonymousFunction204aa80e0600 input.js /^}(!function(C) {$/;" f
f input.js /^ var f = function (t) {$/;" f function:anonymousFunction204aa80e0600
26 changes: 26 additions & 0 deletions Units/parser-javascript.r/self-invoking-anon-func.d/input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
(function(x) {
var a = function (o) { return o; };
return x + a (1);
})(1);

(function(y) {
const b = function (p) { return p; };
return y - b (1);
}(1));

!function(z) {
const c = function (r) { return r; };
return z * c (1);
}(1);

console.log("a" + (function (A) {
return A;
}((function (B) {
return B;
}(!function(C) {
var f = function (t) {
return !t;
}
return f(C);
}(true)
)))));
83 changes: 82 additions & 1 deletion parsers/jscript.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ typedef enum eTokenType {
* Used only in readTokenFull or lower functions. */
TOKEN_ATMARK,
TOKEN_BINARY_OPERATOR,
TOKEN_ARROW
TOKEN_ARROW,
TOKEN_BANG,
} tokenType;

typedef struct sTokenInfo {
Expand Down Expand Up @@ -1066,6 +1067,9 @@ static void readTokenFullRaw (tokenInfo *const token, bool include_newlines, vSt
case '*':
token->type = TOKEN_STAR;
break;
case '!':
token->type = TOKEN_BANG;
break;
case '%':
case '?':
case '>':
Expand Down Expand Up @@ -2924,6 +2928,83 @@ static bool parseLine (tokenInfo *const token, bool is_inside_class)
break;
}
}
else if (isType (token, TOKEN_BANG))
{
/*
* Try to handle "Self-Invoking Anonymous Function Statements" like:
*
* !function(z) { # case A.
* return z * 1;
* }(1);
*
* case A is nothing special; just consuming the token for ! is enough.
*/
readToken (token);
is_terminated = parseLine (token, is_inside_class);
}
else if (isType (token, TOKEN_OPEN_PAREN))
{
/*
* Try to handle "Self-Invoking Anonymous Function Statements" like:
*
* (function(x) { # case B.
* return x + 1;
* })(1);
*
* (function(y) { # case C.
* return y - 1;
* }(1));
*
*/
readToken (token);
is_terminated = parseLine (token, is_inside_class);

/*
* In case B, next ')' should be consumed here.
* In case C, the last ')' after an argument list should be consumed here.
* In case B and C, this function returns true.
*/
if (is_terminated)
{
tokenType last_token_type = token->type;

readToken (token);
if (isType (token, TOKEN_CLOSE_PAREN))
{
/* case B. */
is_terminated = true;
}
else if (last_token_type == TOKEN_CLOSE_CURLY && isType (token, TOKEN_OPEN_PAREN))
{
/*
* maybe case C.
* Parse the argument list if there is.
*/
is_terminated = parseStatement (token, is_inside_class);
if (is_terminated)
{
readToken (token);
if (!isType (token, TOKEN_CLOSE_PAREN) && !isType (token, TOKEN_EOF))
{
/*
* In case B, ')' terminates the statement.
* If the token is not ')', the statement is
* not a "Self-Invoking Anonymous Function Statement".
*/
Assert (NextToken == NULL);
NextToken = newToken ();
copyToken (NextToken, token, false);
}
}
}
else if (!isType (token, TOKEN_EOF))
{
Assert (NextToken == NULL);
NextToken = newToken ();
copyToken (NextToken, token, false);
}
}
}
else
{
/*
Expand Down

0 comments on commit d0ed6dc

Please sign in to comment.