[njs] Inclusive "new" operators and "new" operator calls without
Igor Sysoev
igor at sysoev.ru
Mon Oct 3 10:33:37 UTC 2016
details: http://hg.nginx.org/njs/rev/8c2cea409034
branches:
changeset: 187:8c2cea409034
user: Igor Sysoev <igor at sysoev.ru>
date: Fri Sep 30 22:07:07 2016 +0300
description:
Inclusive "new" operators and "new" operator calls without
parenthesis are supported.
diffstat:
njs/njs_parser_expression.c | 135 +++++++++++++++++++++++++++++++++++--------
njs/test/njs_unit_test.c | 101 ++++++++++++++++++++++++++++++++
2 files changed, 211 insertions(+), 25 deletions(-)
diffs (378 lines):
diff -r b3e83fa52345 -r 8c2cea409034 njs/njs_parser_expression.c
--- a/njs/njs_parser_expression.c Fri Sep 30 14:11:27 2016 +0300
+++ b/njs/njs_parser_expression.c Fri Sep 30 22:07:07 2016 +0300
@@ -70,6 +70,8 @@ static njs_token_t njs_parser_post_inc_d
njs_parser_t *parser, njs_token_t token);
static njs_token_t njs_parser_call_expression(njs_vm_t *vm,
njs_parser_t *parser, njs_token_t token);
+static njs_token_t njs_parser_new_expression(njs_vm_t *vm,
+ njs_parser_t *parser, njs_token_t token);
static njs_token_t njs_parser_property_expression(njs_vm_t *vm,
njs_parser_t *parser, njs_token_t token);
static njs_token_t njs_parser_property_brackets(njs_vm_t *vm,
@@ -894,27 +896,20 @@ static njs_token_t
njs_parser_call_expression(njs_vm_t *vm, njs_parser_t *parser,
njs_token_t token)
{
- nxt_bool_t ctor;
njs_parser_node_t *func, *node;
- ctor = 0;
-
if (token == NJS_TOKEN_NEW) {
- token = njs_parser_token(parser);
- if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
- return token;
- }
+ token = njs_parser_new_expression(vm, parser, token);
- ctor = 1;
+ } else {
+ token = njs_parser_terminal(vm, parser, token);
}
- token = njs_parser_terminal(vm, parser, token);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
for ( ;; ) {
-
token = njs_parser_property_expression(vm, parser, token);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
@@ -923,8 +918,6 @@ njs_parser_call_expression(njs_vm_t *vm,
node = parser->node;
if (token != NJS_TOKEN_OPEN_PARENTHESIS) {
- /* TODO: var o = new Object; */
- node->ctor = ctor;
return token;
}
@@ -937,19 +930,6 @@ njs_parser_call_expression(njs_vm_t *vm,
+ sizeof(njs_vmcode_function_call_t);
break;
- case NJS_TOKEN_FUNCTION_EXPRESSION:
- func = njs_parser_node_alloc(vm);
- if (nxt_slow_path(func == NULL)) {
- return NJS_TOKEN_ERROR;
- }
-
- func->token = NJS_TOKEN_FUNCTION_CALL;
- func->left = node;
- func->index = node->index;
- parser->code_size += sizeof(njs_vmcode_function_frame_t)
- + sizeof(njs_vmcode_function_call_t);
- break;
-
case NJS_TOKEN_PROPERTY:
func = njs_parser_node_alloc(vm);
if (nxt_slow_path(func == NULL)) {
@@ -964,6 +944,9 @@ njs_parser_call_expression(njs_vm_t *vm,
default:
/*
+ * NJS_TOKEN_METHOD_CALL,
+ * NJS_TOKEN_FUNCTION_CALL,
+ * NJS_TOKEN_FUNCTION_EXPRESSION,
* NJS_TOKEN_OPEN_PARENTHESIS,
* NJS_TOKEN_OBJECT_CONSTRUCTOR,
* NJS_TOKEN_ARRAY_CONSTRUCTOR,
@@ -986,6 +969,13 @@ njs_parser_call_expression(njs_vm_t *vm,
break;
}
+ func->ctor = 0;
+
+ if (token != NJS_TOKEN_OPEN_PARENTHESIS) {
+ parser->node = func;
+ return token;
+ }
+
token = njs_parser_arguments(vm, parser, func);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
@@ -1002,6 +992,101 @@ njs_parser_call_expression(njs_vm_t *vm,
static njs_token_t
+njs_parser_new_expression(njs_vm_t *vm, njs_parser_t *parser,
+ njs_token_t token)
+{
+ njs_parser_node_t *func, *node;
+
+ token = njs_parser_token(parser);
+ if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+ return token;
+ }
+
+ if (token == NJS_TOKEN_NEW) {
+ token = njs_parser_new_expression(vm, parser, token);
+
+ } else {
+ token = njs_parser_terminal(vm, parser, token);
+ if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+ return token;
+ }
+
+ token = njs_parser_property_expression(vm, parser, token);
+ }
+
+ if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+ return token;
+ }
+
+ node = parser->node;
+
+ switch (node->token) {
+
+ case NJS_TOKEN_NAME:
+ func = node;
+ func->token = NJS_TOKEN_FUNCTION_CALL;
+ parser->code_size += sizeof(njs_vmcode_function_frame_t)
+ + sizeof(njs_vmcode_function_call_t);
+ break;
+
+ case NJS_TOKEN_PROPERTY:
+ func = njs_parser_node_alloc(vm);
+ if (nxt_slow_path(func == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ func->token = NJS_TOKEN_METHOD_CALL;
+ func->left = node;
+ parser->code_size += sizeof(njs_vmcode_method_frame_t)
+ + sizeof(njs_vmcode_function_call_t);
+ break;
+
+ default:
+ /*
+ * NJS_TOKEN_METHOD_CALL,
+ * NJS_TOKEN_FUNCTION_CALL,
+ * NJS_TOKEN_FUNCTION_EXPRESSION,
+ * NJS_TOKEN_OPEN_PARENTHESIS,
+ * NJS_TOKEN_OBJECT_CONSTRUCTOR,
+ * NJS_TOKEN_ARRAY_CONSTRUCTOR,
+ * NJS_TOKEN_BOOLEAN_CONSTRUCTOR,
+ * NJS_TOKEN_NUMBER_CONSTRUCTOR,
+ * NJS_TOKEN_STRING_CONSTRUCTOR,
+ * NJS_TOKEN_FUNCTION_CONSTRUCTOR,
+ * NJS_TOKEN_REGEXP_CONSTRUCTOR,
+ * NJS_TOKEN_EVAL.
+ */
+ func = njs_parser_node_alloc(vm);
+ if (nxt_slow_path(func == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ func->token = NJS_TOKEN_FUNCTION_CALL;
+ func->left = node;
+ parser->code_size += sizeof(njs_vmcode_function_frame_t)
+ + sizeof(njs_vmcode_function_call_t);
+ break;
+ }
+
+ func->ctor = 1;
+
+ if (token != NJS_TOKEN_OPEN_PARENTHESIS) {
+ parser->node = func;
+ return token;
+ }
+
+ token = njs_parser_arguments(vm, parser, func);
+ if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+ return token;
+ }
+
+ parser->node = func;
+
+ return njs_parser_token(parser);
+}
+
+
+static njs_token_t
njs_parser_property_expression(njs_vm_t *vm, njs_parser_t *parser,
njs_token_t token)
{
diff -r b3e83fa52345 -r 8c2cea409034 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Fri Sep 30 14:11:27 2016 +0300
+++ b/njs/test/njs_unit_test.c Fri Sep 30 22:07:07 2016 +0300
@@ -3631,6 +3631,9 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("(function(x) { return x + 1 }(2))"),
nxt_string("3") },
+ { nxt_string("a = function() { return 1 }(); a"),
+ nxt_string("1") },
+
{ nxt_string("a = (function() { return 1 })(); a"),
nxt_string("1") },
@@ -3777,6 +3780,12 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("function f() {}; f = f + 1; f"),
nxt_string("[object Function]1") },
+ { nxt_string("function a() { return 1 }"
+ "function b() { return a }"
+ "function c() { return b }"
+ "c()()()"),
+ nxt_string("1") },
+
#if 0
{ nxt_string("function f() {}; f += 1; f"),
nxt_string("[object Function]1") },
@@ -3884,6 +3893,56 @@ static njs_unit_test_t njs_test[] =
"o.constructor === F"),
nxt_string("true") },
+ { nxt_string("function F() { return Number }"
+ "var o = new (F())(5);"
+ "typeof o +' '+ o"),
+ nxt_string("object 5") },
+
+ { nxt_string("function F() { return Number }"
+ "var o = new (F());"
+ "typeof o +' '+ o"),
+ nxt_string("object 0") },
+
+ { nxt_string("var o = new function F() { return Number }()(5);"
+ "typeof o +' '+ o"),
+ nxt_string("number 5") },
+
+ { nxt_string("var o = new (function F() { return Number }())(5);"
+ "typeof o +' '+ o"),
+ nxt_string("object 5") },
+
+ { nxt_string("var o = new (new function F() { return Number }())(5);"
+ "typeof o +' '+ o"),
+ nxt_string("object 5") },
+
+ { nxt_string("var o = new new function F() { return Number }()(5);"
+ "typeof o +' '+ o"),
+ nxt_string("object 5") },
+
+ { nxt_string("var b; function F(x) { return {a:x} }"
+ "function G(y) { b = y; return F }"
+ "var o = new G(3)(5);"
+ "b + ' ' + o.a"),
+ nxt_string("3 5") },
+
+ { nxt_string("var b; function F(x) { return {a:x} }"
+ "function G(y) { b = y; return F }"
+ "var o = new (new G(3))(5);"
+ "b + ' ' + o.a"),
+ nxt_string("3 5") },
+
+ { nxt_string("var b; function F(x) { return {a:x} }"
+ "function G(y) { b = y; return F }"
+ "var o = new new G(3)(5);"
+ "b + ' ' + o.a"),
+ nxt_string("3 5") },
+
+ { nxt_string("var b; function F(x) { return {a:x} }"
+ "var g = { G: function (y) { b = y; return F } };"
+ "var o = new new g.G(3)(5);"
+ "b + ' ' + o.a"),
+ nxt_string("3 5") },
+
{ nxt_string("function a() { return function(x) { return x + 1 } }"
"b = a(); b(2)"),
nxt_string("3") },
@@ -4282,6 +4341,12 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("Boolean()"),
nxt_string("false") },
+ { nxt_string("new Boolean()"),
+ nxt_string("false") },
+
+ { nxt_string("new Boolean"),
+ nxt_string("false") },
+
{ nxt_string("Boolean(0)"),
nxt_string("false") },
@@ -4306,6 +4371,9 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("typeof new Boolean(1)"),
nxt_string("object") },
+ { nxt_string("typeof new Boolean"),
+ nxt_string("object") },
+
{ nxt_string("Boolean.name"),
nxt_string("Boolean") },
@@ -4345,6 +4413,12 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("Number()"),
nxt_string("0") },
+ { nxt_string("new Number()"),
+ nxt_string("0") },
+
+ { nxt_string("new Number"),
+ nxt_string("0") },
+
{ nxt_string("Number(123)"),
nxt_string("123") },
@@ -4365,6 +4439,9 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("typeof new Number(1)"),
nxt_string("object") },
+ { nxt_string("typeof new Number"),
+ nxt_string("object") },
+
{ nxt_string("Number.name"),
nxt_string("Number") },
@@ -4401,12 +4478,24 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("String()"),
nxt_string("") },
+ { nxt_string("new String()"),
+ nxt_string("") },
+
+ { nxt_string("new String"),
+ nxt_string("") },
+
{ nxt_string("String(123)"),
nxt_string("123") },
{ nxt_string("new String(123)"),
nxt_string("123") },
+ { nxt_string("new String(123).length"),
+ nxt_string("3") },
+
+ { nxt_string("new String(123).toString()"),
+ nxt_string("123") },
+
{ nxt_string("String([1,2,3])"),
nxt_string("1,2,3") },
@@ -4427,6 +4516,9 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("typeof new String('abc')"),
nxt_string("object") },
+ { nxt_string("typeof new String"),
+ nxt_string("object") },
+
{ nxt_string("String.name"),
nxt_string("String") },
@@ -4926,6 +5018,15 @@ static njs_unit_test_t njs_test[] =
"Date.prototype.toJSON.call(o, 1)"),
nxt_string("OK") },
+ { nxt_string("var d = new Date; d.__proto__"),
+ nxt_string("Invalid Date") },
+
+ { nxt_string("var d = new Date(); d.__proto__"),
+ nxt_string("Invalid Date") },
+
+ { nxt_string("var d = new Date(); d.__proto__ === Date.prototype"),
+ nxt_string("true") },
+
{ nxt_string("Date.name"),
nxt_string("Date") },
More information about the nginx-devel
mailing list