Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff -r c08a5e45d75b njs/njs_function.c
- --- a/njs/njs_function.c Mon Mar 18 14:09:40 2019 +0800
- +++ b/njs/njs_function.c Mon Mar 18 16:02:44 2019 +0800
- @@ -35,7 +35,7 @@ njs_function_alloc(njs_vm_t *vm, njs_fun
- goto fail;
- }
- - function->ctor = 1;
- + function->ctor = lambda->arrow ? 0 : 1;
- function->args_offset = 1;
- function->u.lambda = lambda;
- @@ -290,8 +290,8 @@ njs_function_lambda_frame(njs_vm_t *vm,
- nxt_bool_t ctor)
- {
- size_t size;
- - nxt_uint_t n, max_args, closures;
- - njs_value_t *value, *bound;
- + nxt_uint_t i, n, max_args, closures;
- + njs_value_t *value;
- njs_frame_t *frame;
- njs_native_frame_t *native_frame;
- njs_function_lambda_t *lambda;
- @@ -321,18 +321,17 @@ njs_function_lambda_frame(njs_vm_t *vm,
- njs_frame_size(closures));
- native_frame->arguments = value;
- - bound = function->bound;
- -
- - if (bound == NULL) {
- + if (function->bound == NULL) {
- *value++ = *this;
- } else {
- n = function->args_offset;
- - do {
- - *value++ = *bound++;
- - n--;
- - } while (n != 0);
- + for (i = 0; i < n; i++) {
- + *value++ = function->bound[i];
- + }
- +
- + native_frame->nargs += (n - 1);
- }
- vm->scopes[NJS_SCOPE_CALLEE_ARGUMENTS] = value;
- diff -r c08a5e45d75b njs/njs_function.h
- --- a/njs/njs_function.h Mon Mar 18 14:09:40 2019 +0800
- +++ b/njs/njs_function.h Mon Mar 18 16:02:44 2019 +0800
- @@ -30,6 +30,7 @@ struct njs_function_lambda_s {
- /* Function internal block closures levels. */
- uint8_t block_closures; /* 4 bits */
- + uint8_t arrow; /* 1 bit */
- uint8_t rest_parameters; /* 1 bit */
- /* Initial values of local scope. */
- diff -r c08a5e45d75b njs/njs_lexer.c
- --- a/njs/njs_lexer.c Mon Mar 18 14:09:40 2019 +0800
- +++ b/njs/njs_lexer.c Mon Mar 18 16:02:44 2019 +0800
- @@ -278,6 +278,7 @@ static const njs_lexer_multi_t njs_grea
- static const njs_lexer_multi_t njs_assignment_token[] = {
- { '=', NJS_TOKEN_EQUAL, 1, njs_strict_equal_token },
- + { '>', NJS_TOKEN_ARROW, 0, NULL },
- };
- diff -r c08a5e45d75b njs/njs_lexer.h
- --- a/njs/njs_lexer.h Mon Mar 18 14:09:40 2019 +0800
- +++ b/njs/njs_lexer.h Mon Mar 18 16:02:44 2019 +0800
- @@ -36,6 +36,7 @@ typedef enum {
- NJS_TOKEN_CONDITIONAL,
- NJS_TOKEN_ASSIGNMENT,
- + NJS_TOKEN_ARROW,
- NJS_TOKEN_ADDITION_ASSIGNMENT,
- NJS_TOKEN_SUBSTRACTION_ASSIGNMENT,
- NJS_TOKEN_MULTIPLICATION_ASSIGNMENT,
- diff -r c08a5e45d75b njs/njs_parser.c
- --- a/njs/njs_parser.c Mon Mar 18 14:09:40 2019 +0800
- +++ b/njs/njs_parser.c Mon Mar 18 16:02:44 2019 +0800
- @@ -1960,6 +1960,167 @@ njs_parser_property_token(njs_vm_t *vm,
- }
- +static nxt_int_t
- +njs_parser_match_arrow_expression(njs_vm_t *vm, njs_parser_t *parser,
- + njs_token_t token)
- +{
- + size_t offset;
- + nxt_bool_t rest_parameters;
- +
- + offset = 0;
- +
- + if (token == NJS_TOKEN_NAME) {
- + goto arrow;
- + }
- +
- + token = njs_parser_peek_token(vm, parser, &offset);
- + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
- + return NXT_DECLINED;
- + }
- +
- + rest_parameters = 0;
- +
- + while (token != NJS_TOKEN_CLOSE_PARENTHESIS) {
- +
- + if (rest_parameters) {
- + return NXT_DECLINED;
- + }
- +
- + if (nxt_slow_path(token == NJS_TOKEN_ELLIPSIS)) {
- + rest_parameters = 1;
- +
- + token = njs_parser_peek_token(vm, parser, &offset);
- + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
- + return NXT_DECLINED;
- + }
- + }
- +
- + if (nxt_slow_path(token != NJS_TOKEN_NAME)) {
- + return NXT_DECLINED;
- + }
- +
- + token = njs_parser_peek_token(vm, parser, &offset);
- + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
- + return token;
- + }
- +
- + if (token == NJS_TOKEN_COMMA) {
- + token = njs_parser_peek_token(vm, parser, &offset);
- + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
- + return NXT_DECLINED;
- + }
- + }
- + }
- +
- +arrow:
- +
- + token = njs_parser_peek_token(vm, parser, &offset);
- + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
- + return NXT_DECLINED;
- + }
- +
- + if (parser->lexer->prev_token == NJS_TOKEN_LINE_END) {
- + return NXT_DECLINED;
- + }
- +
- + if (nxt_slow_path(token != NJS_TOKEN_ARROW)) {
- + return NXT_DECLINED;
- + }
- +
- + return NXT_OK;
- +}
- +
- +
- +static njs_token_t
- +njs_parser_arrow_expression(njs_vm_t *vm, njs_parser_t *parser,
- + njs_token_t token)
- +{
- + njs_ret_t ret;
- + njs_index_t index;
- + njs_parser_node_t *node, *body, *parent;
- + njs_function_lambda_t *lambda;
- +
- + node = njs_parser_node_new(vm, parser, NJS_TOKEN_FUNCTION_EXPRESSION);
- + if (nxt_slow_path(node == NULL)) {
- + return NJS_TOKEN_ERROR;
- + }
- +
- + node->token_line = njs_parser_token_line(parser);
- + parser->node = node;
- +
- + lambda = nxt_mp_zalloc(vm->mem_pool, sizeof(njs_function_lambda_t));
- + if (nxt_slow_path(lambda == NULL)) {
- + return NJS_TOKEN_ERROR;
- + }
- +
- + lambda->arrow = 1;
- +
- + node->u.value.data.u.lambda = lambda;
- +
- + ret = njs_parser_scope_begin(vm, parser, NJS_SCOPE_FUNCTION);
- + if (nxt_slow_path(ret != NXT_OK)) {
- + return NJS_TOKEN_ERROR;
- + }
- +
- + index = NJS_SCOPE_ARGUMENTS;
- +
- + /* A "this" reservation. */
- + index += sizeof(njs_value_t);
- +
- + if (token == NJS_TOKEN_OPEN_PARENTHESIS) {
- + token = njs_parser_lambda_arguments(vm, parser, lambda, index, token);
- + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
- + return token;
- + }
- +
- + } else {
- + token = njs_parser_lambda_argument(vm, parser, index);
- + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
- + return token;
- + }
- +
- + lambda->nargs = 1;
- + }
- +
- + if (parser->lexer->prev_token == NJS_TOKEN_LINE_END) {
- + return NJS_TOKEN_ILLEGAL;
- + }
- +
- + token = njs_parser_match(vm, parser, token, NJS_TOKEN_ARROW);
- + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
- + return token;
- + }
- +
- + if (token == NJS_TOKEN_OPEN_BRACE) {
- + token = njs_parser_lambda_body(vm, parser, token);
- + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
- + return token;
- + }
- +
- + } else {
- + parent = parser->node;
- +
- + token = njs_parser_expression(vm, parser, token);
- + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
- + return token;
- + }
- +
- + body = njs_parser_return_set(vm, parser, parser->node);
- + if (nxt_slow_path(body == NULL)) {
- + return NJS_TOKEN_ERROR;
- + }
- +
- + parent->right = body;
- +
- + parser->node = parent;
- + }
- +
- + njs_parser_scope_end(vm, parser);
- +
- + return token;
- +}
- +
- +
- njs_token_t
- njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token)
- {
- @@ -1967,6 +2128,12 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa
- njs_ret_t ret;
- njs_parser_node_t *node;
- + if (token == NJS_TOKEN_OPEN_PARENTHESIS || token == NJS_TOKEN_NAME) {
- + if (njs_parser_match_arrow_expression(vm, parser, token) == NXT_OK) {
- + return njs_parser_arrow_expression(vm, parser, token);
- + }
- + }
- +
- if (token == NJS_TOKEN_OPEN_PARENTHESIS) {
- token = njs_parser_token(vm, parser);
- diff -r c08a5e45d75b njs/test/njs_unit_test.c
- --- a/njs/test/njs_unit_test.c Mon Mar 18 14:09:40 2019 +0800
- +++ b/njs/test/njs_unit_test.c Mon Mar 18 16:02:44 2019 +0800
- @@ -6503,6 +6503,86 @@ static njs_unit_test_t njs_test[] =
- "myFoo(1,2);" ),
- nxt_string("") },
- + /* arrow functions. */
- +
- + { nxt_string("()"),
- + nxt_string("SyntaxError: Unexpected token \")\" in 1") },
- +
- + { nxt_string("() => "),
- + nxt_string("SyntaxError: Unexpected end of input in 1") },
- +
- + { nxt_string("() => {"),
- + nxt_string("SyntaxError: Unexpected end of input in 1") },
- +
- + { nxt_string("a\n => 1"),
- + nxt_string("SyntaxError: Unexpected token \"=>\" in 2") },
- +
- + { nxt_string("new (()=>1)"),
- + nxt_string("TypeError: function is not a constructor")},
- +
- + { nxt_string("(\n) => {}"),
- + nxt_string("[object Function]") },
- +
- + { nxt_string("a => 1"),
- + nxt_string("[object Function]") },
- +
- + { nxt_string("var f = f => {return 1;}; f()"),
- + nxt_string("1") },
- +
- + { nxt_string("var f = (f) => {return 1;}; f()"),
- + nxt_string("1") },
- +
- + { nxt_string("var f = (f, a, b) => {return 1;}; f()"),
- + nxt_string("1") },
- +
- + { nxt_string("var f = () => {return 1;}; f()"),
- + nxt_string("1") },
- +
- + { nxt_string("(f => {return 1;})()"),
- + nxt_string("1") },
- +
- + { nxt_string("((f) => {return 1;})()"),
- + nxt_string("1") },
- +
- + { nxt_string("(((f) => {return 1;}))()"),
- + nxt_string("1") },
- +
- + { nxt_string("var f = f => 1; f()"),
- + nxt_string("1") },
- +
- + { nxt_string("() => 1"),
- + nxt_string("[object Function]") },
- +
- + { nxt_string("var f = ()=>{}; f()"),
- + nxt_string("undefined") },
- +
- + { nxt_string("var f = ()=>({}); f()"),
- + nxt_string("[object Object]") },
- +
- + { nxt_string("var materials = ['Hydrogen', 'Helium', 'Lithium', 'Beryllium'];"
- + "materials.map(material => { return material.length; });"),
- + nxt_string("8,6,7,9") },
- +
- + { nxt_string("var materials = ['Hydrogen', 'Helium', 'Lithium', 'Beryllium'];"
- + "materials.map(material => material.length);"),
- + nxt_string("8,6,7,9") },
- +
- + { nxt_string("var materials = ['Hydrogen', 'Helium', 'Lithium', 'Beryllium'];"
- + "materials.map(material => { material.length });"),
- + nxt_string(",,,") },
- +
- + { nxt_string("function f(a, b, c) {a = 1; return () => { return arguments[1]; };};"
- + "f(1, 2, 3)('a', 'b');"),
- + nxt_string("2") },
- +
- + { nxt_string("var f = (...c) => { return (function() { return arguments.length; }).bind(null, c); };"
- + "var x = f(1,'a',false, {}); x()"),
- + nxt_string("1") },
- +
- + { nxt_string("var f = (...c) => { return (function() { return arguments.length; }).bind(null, c); };"
- + "var x = f(1,'a',false, {}); x(1,2,3)"),
- + nxt_string("4") },
- +
- /* Scopes. */
- { nxt_string("function f(x) { a = x } var a; f(5); a"),
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement