Advertisement
Guest User

Untitled

a guest
Apr 1st, 2019
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 34.38 KB | None | 0 0
  1. # HG changeset patch
  2. # User hongzhidao <hongzhidao@gmail.com>
  3. # Date 1553532159 -28800
  4. # Node ID 89bfc95f182f12238b7884a39326bdae77f6ddc9
  5. # Parent e3ee3a2d9994f77dc420edf89d6cf2af5b64743e
  6. Improved lambda arguments object.
  7.  
  8. diff -r e3ee3a2d9994 -r 89bfc95f182f njs/njs_function.c
  9. --- a/njs/njs_function.c Mon Mar 25 17:51:19 2019 +0300
  10. +++ b/njs/njs_function.c Tue Mar 26 00:42:39 2019 +0800
  11. @@ -477,13 +477,6 @@ njs_function_lambda_call(njs_vm_t *vm, n
  12. vm->scopes[NJS_SCOPE_CLOSURE + n] = &closure->u.values;
  13. }
  14.  
  15. - if (lambda->arguments_object) {
  16. - ret = njs_function_arguments_object_init(vm, &frame->native);
  17. - if (nxt_slow_path(ret != NXT_OK)) {
  18. - return NXT_ERROR;
  19. - }
  20. - }
  21. -
  22. if (lambda->rest_parameters) {
  23. ret = njs_function_rest_parameters_init(vm, &frame->native);
  24. if (nxt_slow_path(ret != NXT_OK)) {
  25. diff -r e3ee3a2d9994 -r 89bfc95f182f njs/njs_function.h
  26. --- a/njs/njs_function.h Mon Mar 25 17:51:19 2019 +0300
  27. +++ b/njs/njs_function.h Tue Mar 26 00:42:39 2019 +0800
  28. @@ -30,7 +30,6 @@ struct njs_function_lambda_s {
  29. /* Function internal block closures levels. */
  30. uint8_t block_closures; /* 4 bits */
  31.  
  32. - uint8_t arguments_object; /* 1 bit */
  33. uint8_t rest_parameters; /* 1 bit */
  34.  
  35. /* Initial values of local scope. */
  36. diff -r e3ee3a2d9994 -r 89bfc95f182f njs/njs_generator.c
  37. --- a/njs/njs_generator.c Mon Mar 25 17:51:19 2019 +0300
  38. +++ b/njs/njs_generator.c Tue Mar 26 00:42:39 2019 +0800
  39. @@ -61,8 +61,6 @@ static nxt_int_t njs_generate_name(njs_v
  40. njs_parser_node_t *node);
  41. static nxt_int_t njs_generate_builtin_object(njs_vm_t *vm,
  42. njs_generator_t *generator, njs_parser_node_t *node);
  43. -static nxt_int_t njs_generate_arguments_object(njs_vm_t *vm,
  44. - njs_generator_t *generator, njs_parser_node_t *node);
  45. static nxt_int_t njs_generate_variable(njs_vm_t *vm, njs_generator_t *generator,
  46. njs_parser_node_t *node);
  47. static nxt_int_t njs_generate_var_statement(njs_vm_t *vm,
  48. @@ -140,7 +138,7 @@ static nxt_int_t njs_generate_function_d
  49. static nxt_int_t njs_generate_function_scope(njs_vm_t *vm,
  50. njs_function_lambda_t *lambda, njs_parser_node_t *node,
  51. const nxt_str_t *name);
  52. -static nxt_int_t njs_generate_argument_closures(njs_vm_t *vm,
  53. +static nxt_int_t njs_generate_lambda_variables(njs_vm_t *vm,
  54. njs_generator_t *generator, njs_parser_node_t *node);
  55. static nxt_int_t njs_generate_return_statement(njs_vm_t *vm,
  56. njs_generator_t *generator, njs_parser_node_t *node);
  57. @@ -429,6 +427,7 @@ njs_generator(njs_vm_t *vm, njs_generato
  58. return NXT_OK;
  59.  
  60. case NJS_TOKEN_NAME:
  61. + case NJS_TOKEN_ARGUMENTS:
  62. return njs_generate_name(vm, generator, node);
  63.  
  64. case NJS_TOKEN_GLOBAL_THIS:
  65. @@ -451,9 +450,6 @@ njs_generator(njs_vm_t *vm, njs_generato
  66. case NJS_TOKEN_CLEAR_TIMEOUT:
  67. return njs_generate_builtin_object(vm, generator, node);
  68.  
  69. - case NJS_TOKEN_ARGUMENTS:
  70. - return njs_generate_arguments_object(vm, generator, node);
  71. -
  72. case NJS_TOKEN_FUNCTION:
  73. return njs_generate_function_declaration(vm, generator, node);
  74.  
  75. @@ -586,25 +582,6 @@ njs_generate_builtin_object(njs_vm_t *vm
  76.  
  77.  
  78. static nxt_int_t
  79. -njs_generate_arguments_object(njs_vm_t *vm, njs_generator_t *generator,
  80. - njs_parser_node_t *node)
  81. -{
  82. - njs_vmcode_arguments_t *gen;
  83. -
  84. - node->index = njs_generate_object_dest_index(vm, generator, node);
  85. - if (nxt_slow_path(node->index == NJS_INDEX_ERROR)) {
  86. - return NXT_ERROR;
  87. - }
  88. -
  89. - njs_generate_code(generator, njs_vmcode_arguments_t, gen,
  90. - njs_vmcode_arguments, 1, 1);
  91. - gen->retval = node->index;
  92. -
  93. - return NXT_OK;
  94. -}
  95. -
  96. -
  97. -static nxt_int_t
  98. njs_generate_variable(njs_vm_t *vm, njs_generator_t *generator,
  99. njs_parser_node_t *node)
  100. {
  101. @@ -2329,7 +2306,6 @@ njs_generate_function_scope(njs_vm_t *vm
  102. lambda->closure_size = size;
  103.  
  104. lambda->nesting = node->scope->nesting;
  105. - lambda->arguments_object = node->scope->arguments_object;
  106.  
  107. lambda->start = generator.code_start;
  108. lambda->local_size = generator.scope_size;
  109. @@ -2362,7 +2338,7 @@ njs_generate_scope(njs_vm_t *vm, njs_gen
  110. generator->code_start = p;
  111. generator->code_end = p;
  112.  
  113. - ret = njs_generate_argument_closures(vm, generator, scope->top);
  114. + ret = njs_generate_lambda_variables(vm, generator, scope->top);
  115. if (nxt_slow_path(ret != NXT_OK)) {
  116. return NXT_ERROR;
  117. }
  118. @@ -2420,35 +2396,36 @@ njs_generate_scope(njs_vm_t *vm, njs_gen
  119.  
  120.  
  121. static nxt_int_t
  122. -njs_generate_argument_closures(njs_vm_t *vm, njs_generator_t *generator,
  123. +njs_generate_lambda_variables(njs_vm_t *vm, njs_generator_t *generator,
  124. njs_parser_node_t *node)
  125. {
  126. - nxt_uint_t n;
  127. - njs_index_t index;
  128. - njs_variable_t *var;
  129. - njs_vmcode_move_t *move;
  130. - nxt_lvlhsh_each_t lhe;
  131. -
  132. - n = node->scope->argument_closures;
  133. -
  134. - if (n == 0) {
  135. - return NXT_OK;
  136. - }
  137. + njs_index_t index;
  138. + njs_variable_t *var;
  139. + njs_vmcode_move_t *move;
  140. + nxt_lvlhsh_each_t lhe;
  141. + njs_vmcode_arguments_t *arguments;
  142.  
  143. nxt_lvlhsh_each_init(&lhe, &njs_variables_hash_proto);
  144.  
  145. - do {
  146. + for ( ;; ) {
  147. var = nxt_lvlhsh_each(&node->scope->variables, &lhe);
  148.  
  149. + if (var == NULL) {
  150. + break;
  151. + }
  152. +
  153. if (var->argument != 0) {
  154. index = njs_scope_index((var->argument - 1), NJS_SCOPE_ARGUMENTS);
  155.  
  156. njs_generate_code_move(generator, move, var->index, index);
  157. -
  158. - n--;
  159. }
  160.  
  161. - } while (n != 0);
  162. + if (var->arguments_object) {
  163. + njs_generate_code(generator, njs_vmcode_arguments_t, arguments,
  164. + njs_vmcode_arguments, 1, 0);
  165. + arguments->dst = var->index;
  166. + }
  167. + }
  168.  
  169. return NXT_OK;
  170. }
  171. diff -r e3ee3a2d9994 -r 89bfc95f182f njs/njs_parser.c
  172. --- a/njs/njs_parser.c Mon Mar 25 17:51:19 2019 +0300
  173. +++ b/njs/njs_parser.c Tue Mar 26 00:42:39 2019 +0800
  174. @@ -536,6 +536,7 @@ njs_parser_variable_add(njs_vm_t *vm, nj
  175. njs_parser_key_hash(parser), type);
  176. }
  177.  
  178. +
  179. nxt_inline njs_ret_t
  180. njs_parser_variable_reference(njs_vm_t *vm, njs_parser_t *parser,
  181. njs_parser_node_t *node, njs_reference_type_t type)
  182. @@ -546,6 +547,36 @@ njs_parser_variable_reference(njs_vm_t *
  183. }
  184.  
  185.  
  186. +nxt_inline njs_parser_node_t *
  187. +njs_parser_variable_node(njs_vm_t *vm, njs_parser_t *parser, nxt_str_t *name,
  188. + uint32_t hash, njs_variable_type_t type, uint8_t arguments_object)
  189. +{
  190. + nxt_int_t ret;
  191. + njs_variable_t *var;
  192. + njs_parser_node_t *node;
  193. +
  194. + var = njs_variable_add(vm, parser->scope, name, hash, type);
  195. + if (nxt_slow_path(var == NULL)) {
  196. + return NULL;
  197. + }
  198. +
  199. + var->arguments_object = arguments_object;
  200. +
  201. + node = njs_parser_node_new(vm, parser, NJS_TOKEN_NAME);
  202. + if (nxt_slow_path(node == NULL)) {
  203. + return NULL;
  204. + }
  205. +
  206. + ret = njs_variable_reference(vm, parser->scope, node, name, hash,
  207. + NJS_DECLARATION);
  208. + if (nxt_slow_path(ret != NXT_OK)) {
  209. + return NULL;
  210. + }
  211. +
  212. + return node;
  213. +}
  214. +
  215. +
  216. static njs_token_t
  217. njs_parser_labelled_statement(njs_vm_t *vm, njs_parser_t *parser)
  218. {
  219. @@ -761,8 +792,11 @@ static njs_token_t
  220. njs_parser_function_lambda(njs_vm_t *vm, njs_parser_t *parser,
  221. njs_function_lambda_t *lambda, njs_token_t token)
  222. {
  223. - njs_ret_t ret;
  224. - njs_index_t index;
  225. + njs_ret_t ret;
  226. + nxt_str_t name;
  227. + uint32_t hash;
  228. + njs_index_t index;
  229. + njs_parser_node_t *node;
  230.  
  231. ret = njs_parser_scope_begin(vm, parser, NJS_SCOPE_FUNCTION);
  232. if (nxt_slow_path(ret != NXT_OK)) {
  233. @@ -779,6 +813,15 @@ njs_parser_function_lambda(njs_vm_t *vm,
  234. return token;
  235. }
  236.  
  237. + name = nxt_string_value("arguments");
  238. + hash = nxt_djb_hash(name.start, name.length);
  239. +
  240. + node = njs_parser_variable_node(vm, parser, &name, hash,
  241. + NJS_VARIABLE_VAR, 1);
  242. + if (nxt_slow_path(node == NULL)) {
  243. + return NJS_TOKEN_ERROR;
  244. + }
  245. +
  246. token = njs_parser_lambda_body(vm, parser, token);
  247. if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  248. return token;
  249. @@ -1025,9 +1068,7 @@ njs_parser_return_statement(njs_vm_t *vm
  250. static njs_token_t
  251. njs_parser_var_statement(njs_vm_t *vm, njs_parser_t *parser)
  252. {
  253. - njs_ret_t ret;
  254. njs_token_t token;
  255. - njs_variable_t *var;
  256. njs_parser_node_t *left, *stmt, *name, *assign, *expr;
  257.  
  258. parser->node = NULL;
  259. @@ -1049,21 +1090,14 @@ njs_parser_var_statement(njs_vm_t *vm, n
  260. return NJS_TOKEN_ILLEGAL;
  261. }
  262.  
  263. - var = njs_parser_variable_add(vm, parser, NJS_VARIABLE_VAR);
  264. - if (nxt_slow_path(var == NULL)) {
  265. - return NJS_TOKEN_ERROR;
  266. - }
  267. -
  268. - name = njs_parser_node_new(vm, parser, NJS_TOKEN_NAME);
  269. + name = njs_parser_variable_node(vm, parser,
  270. + njs_parser_text(parser),
  271. + njs_parser_key_hash(parser),
  272. + NJS_VARIABLE_VAR, 0);
  273. if (nxt_slow_path(name == NULL)) {
  274. return NJS_TOKEN_ERROR;
  275. }
  276.  
  277. - ret = njs_parser_variable_reference(vm, parser, name, NJS_DECLARATION);
  278. - if (nxt_slow_path(ret != NXT_OK)) {
  279. - return NJS_TOKEN_ERROR;
  280. - }
  281. -
  282. token = njs_parser_token(vm, parser);
  283. if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  284. return token;
  285. @@ -1477,9 +1511,7 @@ njs_parser_for_statement(njs_vm_t *vm, n
  286. static njs_token_t
  287. njs_parser_for_var_statement(njs_vm_t *vm, njs_parser_t *parser)
  288. {
  289. - njs_ret_t ret;
  290. njs_token_t token;
  291. - njs_variable_t *var;
  292. njs_parser_node_t *left, *stmt, *name, *assign, *expr;
  293.  
  294. parser->node = NULL;
  295. @@ -1501,21 +1533,14 @@ njs_parser_for_var_statement(njs_vm_t *v
  296. return NJS_TOKEN_ILLEGAL;
  297. }
  298.  
  299. - var = njs_parser_variable_add(vm, parser, NJS_VARIABLE_VAR);
  300. - if (nxt_slow_path(var == NULL)) {
  301. - return NJS_TOKEN_ERROR;
  302. - }
  303. -
  304. - name = njs_parser_node_new(vm, parser, NJS_TOKEN_NAME);
  305. + name = njs_parser_variable_node(vm, parser,
  306. + njs_parser_text(parser),
  307. + njs_parser_key_hash(parser),
  308. + NJS_VARIABLE_VAR, 0);
  309. if (nxt_slow_path(name == NULL)) {
  310. return NJS_TOKEN_ERROR;
  311. }
  312.  
  313. - ret = njs_parser_variable_reference(vm, parser, name, NJS_DECLARATION);
  314. - if (nxt_slow_path(ret != NXT_OK)) {
  315. - return NJS_TOKEN_ERROR;
  316. - }
  317. -
  318. token = njs_parser_token(vm, parser);
  319. if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  320. return token;
  321. @@ -1714,7 +1739,6 @@ njs_parser_try_statement(njs_vm_t *vm, n
  322. {
  323. njs_ret_t ret;
  324. njs_token_t token;
  325. - njs_variable_t *var;
  326. njs_parser_node_t *node, *try, *catch;
  327.  
  328. token = njs_parser_try_block(vm, parser);
  329. @@ -1760,21 +1784,14 @@ njs_parser_try_statement(njs_vm_t *vm, n
  330. return NJS_TOKEN_ERROR;
  331. }
  332.  
  333. - var = njs_parser_variable_add(vm, parser, NJS_VARIABLE_CATCH);
  334. - if (nxt_slow_path(var == NULL)) {
  335. - return NJS_TOKEN_ERROR;
  336. - }
  337. -
  338. - node = njs_parser_node_new(vm, parser, NJS_TOKEN_NAME);
  339. + node = njs_parser_variable_node(vm, parser,
  340. + njs_parser_text(parser),
  341. + njs_parser_key_hash(parser),
  342. + NJS_VARIABLE_CATCH, 0);
  343. if (nxt_slow_path(node == NULL)) {
  344. return NJS_TOKEN_ERROR;
  345. }
  346.  
  347. - ret = njs_parser_variable_reference(vm, parser, node, NJS_DECLARATION);
  348. - if (nxt_slow_path(ret != NXT_OK)) {
  349. - return NJS_TOKEN_ERROR;
  350. - }
  351. -
  352. catch->left = node;
  353.  
  354. token = njs_parser_token(vm, parser);
  355. @@ -1899,7 +1916,6 @@ njs_parser_import_statement(njs_vm_t *vm
  356. {
  357. njs_ret_t ret;
  358. njs_token_t token;
  359. - njs_variable_t *var;
  360. njs_parser_node_t *name, *import;
  361.  
  362. if (parser->scope->type != NJS_SCOPE_GLOBAL
  363. @@ -1921,21 +1937,14 @@ njs_parser_import_statement(njs_vm_t *vm
  364. return NJS_TOKEN_ILLEGAL;
  365. }
  366.  
  367. - var = njs_parser_variable_add(vm, parser, NJS_VARIABLE_VAR);
  368. - if (nxt_slow_path(var == NULL)) {
  369. - return NJS_TOKEN_ERROR;
  370. - }
  371. -
  372. - name = njs_parser_node_new(vm, parser, NJS_TOKEN_NAME);
  373. + name = njs_parser_variable_node(vm, parser,
  374. + njs_parser_text(parser),
  375. + njs_parser_key_hash(parser),
  376. + NJS_VARIABLE_VAR, 0);
  377. if (nxt_slow_path(name == NULL)) {
  378. return NJS_TOKEN_ERROR;
  379. }
  380.  
  381. - ret = njs_parser_variable_reference(vm, parser, name, NJS_DECLARATION);
  382. - if (nxt_slow_path(ret != NXT_OK)) {
  383. - return NJS_TOKEN_ERROR;
  384. - }
  385. -
  386. token = njs_parser_token(vm, parser);
  387. if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  388. return token;
  389. @@ -2463,20 +2472,6 @@ njs_parser_reference(njs_vm_t *vm, njs_p
  390.  
  391. break;
  392.  
  393. - case NJS_TOKEN_ARGUMENTS:
  394. - nxt_thread_log_debug("JS: arguments");
  395. -
  396. - if (parser->scope->type <= NJS_SCOPE_GLOBAL) {
  397. - njs_parser_syntax_error(vm, parser, "\"%V\" object "
  398. - "in global scope", name);
  399. -
  400. - return NULL;
  401. - }
  402. -
  403. - parser->scope->arguments_object = 1;
  404. -
  405. - break;
  406. -
  407. case NJS_TOKEN_OBJECT_CONSTRUCTOR:
  408. node->index = NJS_INDEX_OBJECT;
  409. break;
  410. @@ -2566,6 +2561,26 @@ njs_parser_reference(njs_vm_t *vm, njs_p
  411.  
  412. break;
  413.  
  414. + case NJS_TOKEN_ARGUMENTS:
  415. + nxt_thread_log_debug("JS: arguments");
  416. +
  417. + if (parser->scope->type <= NJS_SCOPE_GLOBAL) {
  418. + njs_parser_syntax_error(vm, parser, "\"%V\" object "
  419. + "in global scope", name);
  420. +
  421. + return NULL;
  422. + }
  423. +
  424. + node->token_line = token_line;
  425. +
  426. + ret = njs_variable_reference(vm, parser->scope, node, name, hash,
  427. + NJS_REFERENCE);
  428. + if (nxt_slow_path(ret != NXT_OK)) {
  429. + return NULL;
  430. + }
  431. +
  432. + break;
  433. +
  434. case NJS_TOKEN_NAME:
  435. nxt_thread_log_debug("JS: %V", name);
  436.  
  437. diff -r e3ee3a2d9994 -r 89bfc95f182f njs/njs_parser.h
  438. --- a/njs/njs_parser.h Mon Mar 25 17:51:19 2019 +0300
  439. +++ b/njs/njs_parser.h Tue Mar 26 00:42:39 2019 +0800
  440. @@ -31,7 +31,6 @@ struct njs_parser_scope_s {
  441. njs_scope_t type:8;
  442. uint8_t nesting; /* 4 bits */
  443. uint8_t argument_closures;
  444. - uint8_t arguments_object;
  445. uint8_t module;
  446. };
  447.  
  448. diff -r e3ee3a2d9994 -r 89bfc95f182f njs/njs_variable.h
  449. --- a/njs/njs_variable.h Mon Mar 25 17:51:19 2019 +0300
  450. +++ b/njs/njs_variable.h Tue Mar 26 00:42:39 2019 +0800
  451. @@ -23,6 +23,7 @@ typedef struct {
  452.  
  453. njs_variable_type_t type:8; /* 3 bits */
  454. uint8_t argument;
  455. + uint8_t arguments_object;
  456.  
  457. njs_index_t index;
  458. njs_value_t value;
  459. diff -r e3ee3a2d9994 -r 89bfc95f182f njs/njs_vm.c
  460. --- a/njs/njs_vm.c Mon Mar 25 17:51:19 2019 +0300
  461. +++ b/njs/njs_vm.c Tue Mar 26 00:42:39 2019 +0800
  462. @@ -10,7 +10,6 @@
  463. #include <stdio.h>
  464.  
  465.  
  466. -
  467. struct njs_property_next_s {
  468. int32_t index;
  469. nxt_lvlhsh_each_t lhe;
  470. @@ -420,8 +419,10 @@ njs_vmcode_function(njs_vm_t *vm, njs_va
  471. njs_ret_t
  472. njs_vmcode_arguments(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2)
  473. {
  474. - njs_ret_t ret;
  475. - njs_frame_t *frame;
  476. + nxt_int_t ret;
  477. + njs_frame_t *frame;
  478. + njs_value_t *value;
  479. + njs_vmcode_arguments_t *code;
  480.  
  481. frame = (njs_frame_t *) vm->active_frame;
  482.  
  483. @@ -432,9 +433,12 @@ njs_vmcode_arguments(njs_vm_t *vm, njs_v
  484. }
  485. }
  486.  
  487. - vm->retval.data.u.object = frame->native.arguments_object;
  488. - vm->retval.type = NJS_OBJECT;
  489. - vm->retval.data.truth = 1;
  490. + code = (njs_vmcode_arguments_t *) vm->current;
  491. +
  492. + value = njs_vmcode_operand(vm, code->dst);
  493. + value->data.u.object = frame->native.arguments_object;
  494. + value->type = NJS_OBJECT;
  495. + value->data.truth = 1;
  496.  
  497. return sizeof(njs_vmcode_arguments_t);
  498. }
  499. diff -r e3ee3a2d9994 -r 89bfc95f182f njs/njs_vm.h
  500. --- a/njs/njs_vm.h Mon Mar 25 17:51:19 2019 +0300
  501. +++ b/njs/njs_vm.h Tue Mar 26 00:42:39 2019 +0800
  502. @@ -639,7 +639,7 @@ typedef struct {
  503.  
  504. typedef struct {
  505. njs_vmcode_t code;
  506. - njs_index_t retval;
  507. + njs_index_t dst;
  508. } njs_vmcode_arguments_t;
  509.  
  510.  
  511. # HG changeset patch
  512. # User hongzhidao <hongzhidao@gmail.com>
  513. # Date 1553533166 -28800
  514. # Node ID 938cb05807692b9f3d50c210124b48ea832feeed
  515. # Parent 89bfc95f182f12238b7884a39326bdae77f6ddc9
  516. Improved lambda this object.
  517.  
  518. diff -r 89bfc95f182f -r 938cb0580769 njs/njs_generator.c
  519. --- a/njs/njs_generator.c Tue Mar 26 00:42:39 2019 +0800
  520. +++ b/njs/njs_generator.c Tue Mar 26 00:59:26 2019 +0800
  521. @@ -405,7 +405,6 @@ njs_generator(njs_vm_t *vm, njs_generato
  522. case NJS_TOKEN_REGEXP:
  523. return njs_generate_regexp(vm, generator, node);
  524.  
  525. - case NJS_TOKEN_THIS:
  526. case NJS_TOKEN_OBJECT_CONSTRUCTOR:
  527. case NJS_TOKEN_ARRAY_CONSTRUCTOR:
  528. case NJS_TOKEN_NUMBER_CONSTRUCTOR:
  529. @@ -427,6 +426,7 @@ njs_generator(njs_vm_t *vm, njs_generato
  530. return NXT_OK;
  531.  
  532. case NJS_TOKEN_NAME:
  533. + case NJS_TOKEN_THIS:
  534. case NJS_TOKEN_ARGUMENTS:
  535. return njs_generate_name(vm, generator, node);
  536.  
  537. @@ -2403,6 +2403,7 @@ njs_generate_lambda_variables(njs_vm_t *
  538. njs_variable_t *var;
  539. njs_vmcode_move_t *move;
  540. nxt_lvlhsh_each_t lhe;
  541. + njs_vmcode_this_t *this;
  542. njs_vmcode_arguments_t *arguments;
  543.  
  544. nxt_lvlhsh_each_init(&lhe, &njs_variables_hash_proto);
  545. @@ -2420,6 +2421,12 @@ njs_generate_lambda_variables(njs_vm_t *
  546. njs_generate_code_move(generator, move, var->index, index);
  547. }
  548.  
  549. + if (var->this_object) {
  550. + njs_generate_code(generator, njs_vmcode_this_t, this,
  551. + njs_vmcode_this, 1, 0);
  552. + this->dst = var->index;
  553. + }
  554. +
  555. if (var->arguments_object) {
  556. njs_generate_code(generator, njs_vmcode_arguments_t, arguments,
  557. njs_vmcode_arguments, 1, 0);
  558. diff -r 89bfc95f182f -r 938cb0580769 njs/njs_parser.c
  559. --- a/njs/njs_parser.c Tue Mar 26 00:42:39 2019 +0800
  560. +++ b/njs/njs_parser.c Tue Mar 26 00:59:26 2019 +0800
  561. @@ -549,7 +549,8 @@ njs_parser_variable_reference(njs_vm_t *
  562.  
  563. nxt_inline njs_parser_node_t *
  564. njs_parser_variable_node(njs_vm_t *vm, njs_parser_t *parser, nxt_str_t *name,
  565. - uint32_t hash, njs_variable_type_t type, uint8_t arguments_object)
  566. + uint32_t hash, njs_variable_type_t type, uint8_t arguments_object,
  567. + uint8_t this_object)
  568. {
  569. nxt_int_t ret;
  570. njs_variable_t *var;
  571. @@ -560,6 +561,7 @@ njs_parser_variable_node(njs_vm_t *vm, n
  572. return NULL;
  573. }
  574.  
  575. + var->this_object = this_object;
  576. var->arguments_object = arguments_object;
  577.  
  578. node = njs_parser_node_new(vm, parser, NJS_TOKEN_NAME);
  579. @@ -813,11 +815,20 @@ njs_parser_function_lambda(njs_vm_t *vm,
  580. return token;
  581. }
  582.  
  583. + name = nxt_string_value("this");
  584. + hash = nxt_djb_hash(name.start, name.length);
  585. +
  586. + node = njs_parser_variable_node(vm, parser, &name, hash,
  587. + NJS_VARIABLE_VAR, 0, 1);
  588. + if (nxt_slow_path(node == NULL)) {
  589. + return NJS_TOKEN_ERROR;
  590. + }
  591. +
  592. name = nxt_string_value("arguments");
  593. hash = nxt_djb_hash(name.start, name.length);
  594.  
  595. node = njs_parser_variable_node(vm, parser, &name, hash,
  596. - NJS_VARIABLE_VAR, 1);
  597. + NJS_VARIABLE_VAR, 1, 0);
  598. if (nxt_slow_path(node == NULL)) {
  599. return NJS_TOKEN_ERROR;
  600. }
  601. @@ -1093,7 +1104,7 @@ njs_parser_var_statement(njs_vm_t *vm, n
  602. name = njs_parser_variable_node(vm, parser,
  603. njs_parser_text(parser),
  604. njs_parser_key_hash(parser),
  605. - NJS_VARIABLE_VAR, 0);
  606. + NJS_VARIABLE_VAR, 0, 0);
  607. if (nxt_slow_path(name == NULL)) {
  608. return NJS_TOKEN_ERROR;
  609. }
  610. @@ -1536,7 +1547,7 @@ njs_parser_for_var_statement(njs_vm_t *v
  611. name = njs_parser_variable_node(vm, parser,
  612. njs_parser_text(parser),
  613. njs_parser_key_hash(parser),
  614. - NJS_VARIABLE_VAR, 0);
  615. + NJS_VARIABLE_VAR, 0, 0);
  616. if (nxt_slow_path(name == NULL)) {
  617. return NJS_TOKEN_ERROR;
  618. }
  619. @@ -1787,7 +1798,7 @@ njs_parser_try_statement(njs_vm_t *vm, n
  620. node = njs_parser_variable_node(vm, parser,
  621. njs_parser_text(parser),
  622. njs_parser_key_hash(parser),
  623. - NJS_VARIABLE_CATCH, 0);
  624. + NJS_VARIABLE_CATCH, 0, 0);
  625. if (nxt_slow_path(node == NULL)) {
  626. return NJS_TOKEN_ERROR;
  627. }
  628. @@ -1940,7 +1951,7 @@ njs_parser_import_statement(njs_vm_t *vm
  629. name = njs_parser_variable_node(vm, parser,
  630. njs_parser_text(parser),
  631. njs_parser_key_hash(parser),
  632. - NJS_VARIABLE_VAR, 0);
  633. + NJS_VARIABLE_VAR, 0, 0);
  634. if (nxt_slow_path(name == NULL)) {
  635. return NJS_TOKEN_ERROR;
  636. }
  637. @@ -2445,21 +2456,29 @@ njs_parser_reference(njs_vm_t *vm, njs_p
  638.  
  639. scope = parser->scope;
  640.  
  641. + node->token = NJS_TOKEN_GLOBAL_THIS;
  642. +
  643. while (scope->type != NJS_SCOPE_GLOBAL) {
  644. if (scope->type == NJS_SCOPE_FUNCTION) {
  645. - node->index = NJS_INDEX_THIS;
  646. + node->token = NJS_TOKEN_THIS;
  647. break;
  648. }
  649.  
  650. scope = scope->parent;
  651. }
  652.  
  653. - if (node->index == NJS_INDEX_THIS) {
  654. + if (node->token == NJS_TOKEN_THIS) {
  655. + node->token_line = token_line;
  656. +
  657. + ret = njs_variable_reference(vm, parser->scope, node, name, hash,
  658. + NJS_REFERENCE);
  659. + if (nxt_slow_path(ret != NXT_OK)) {
  660. + return NULL;
  661. + }
  662. +
  663. break;
  664. }
  665.  
  666. - node->token = NJS_TOKEN_GLOBAL_THIS;
  667. -
  668. /* Fall through. */
  669.  
  670. case NJS_TOKEN_NJS:
  671. diff -r 89bfc95f182f -r 938cb0580769 njs/njs_variable.h
  672. --- a/njs/njs_variable.h Tue Mar 26 00:42:39 2019 +0800
  673. +++ b/njs/njs_variable.h Tue Mar 26 00:59:26 2019 +0800
  674. @@ -23,6 +23,7 @@ typedef struct {
  675.  
  676. njs_variable_type_t type:8; /* 3 bits */
  677. uint8_t argument;
  678. + uint8_t this_object;
  679. uint8_t arguments_object;
  680.  
  681. njs_index_t index;
  682. diff -r 89bfc95f182f -r 938cb0580769 njs/njs_vm.c
  683. --- a/njs/njs_vm.c Tue Mar 26 00:42:39 2019 +0800
  684. +++ b/njs/njs_vm.c Tue Mar 26 00:59:26 2019 +0800
  685. @@ -417,6 +417,23 @@ njs_vmcode_function(njs_vm_t *vm, njs_va
  686.  
  687.  
  688. njs_ret_t
  689. +njs_vmcode_this(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2)
  690. +{
  691. + njs_frame_t *frame;
  692. + njs_value_t *value;
  693. + njs_vmcode_this_t *code;
  694. +
  695. + frame = (njs_frame_t *) vm->active_frame;
  696. + code = (njs_vmcode_this_t *) vm->current;
  697. +
  698. + value = njs_vmcode_operand(vm, code->dst);
  699. + *value = frame->native.arguments[0];
  700. +
  701. + return sizeof(njs_vmcode_this_t);
  702. +}
  703. +
  704. +
  705. +njs_ret_t
  706. njs_vmcode_arguments(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2)
  707. {
  708. nxt_int_t ret;
  709. diff -r 89bfc95f182f -r 938cb0580769 njs/njs_vm.h
  710. --- a/njs/njs_vm.h Tue Mar 26 00:42:39 2019 +0800
  711. +++ b/njs/njs_vm.h Tue Mar 26 00:59:26 2019 +0800
  712. @@ -640,6 +640,12 @@ typedef struct {
  713. typedef struct {
  714. njs_vmcode_t code;
  715. njs_index_t dst;
  716. +} njs_vmcode_this_t;
  717. +
  718. +
  719. +typedef struct {
  720. + njs_vmcode_t code;
  721. + njs_index_t dst;
  722. } njs_vmcode_arguments_t;
  723.  
  724.  
  725. @@ -1136,6 +1142,8 @@ njs_ret_t njs_vmcode_array(njs_vm_t *vm,
  726. njs_value_t *inlvd2);
  727. njs_ret_t njs_vmcode_function(njs_vm_t *vm, njs_value_t *inlvd1,
  728. njs_value_t *invld2);
  729. +njs_ret_t njs_vmcode_this(njs_vm_t *vm, njs_value_t *inlvd1,
  730. + njs_value_t *invld2);
  731. njs_ret_t njs_vmcode_arguments(njs_vm_t *vm, njs_value_t *inlvd1,
  732. njs_value_t *invld2);
  733. njs_ret_t njs_vmcode_regexp(njs_vm_t *vm, njs_value_t *inlvd1,
  734. # HG changeset patch
  735. # User hongzhidao <hongzhidao@gmail.com>
  736. # Date 1553534189 -28800
  737. # Node ID 280cc88eb639fec2c56d0b54af7442529da58b37
  738. # Parent 938cb05807692b9f3d50c210124b48ea832feeed
  739. Added arrow function support.
  740.  
  741. diff -r 938cb0580769 -r 280cc88eb639 njs/njs_function.h
  742. --- a/njs/njs_function.h Tue Mar 26 00:59:26 2019 +0800
  743. +++ b/njs/njs_function.h Tue Mar 26 01:16:29 2019 +0800
  744. @@ -30,6 +30,7 @@ struct njs_function_lambda_s {
  745. /* Function internal block closures levels. */
  746. uint8_t block_closures; /* 4 bits */
  747.  
  748. + uint8_t arrow; /* 1 bit */
  749. uint8_t rest_parameters; /* 1 bit */
  750.  
  751. /* Initial values of local scope. */
  752. diff -r 938cb0580769 -r 280cc88eb639 njs/njs_lexer.c
  753. --- a/njs/njs_lexer.c Tue Mar 26 00:59:26 2019 +0800
  754. +++ b/njs/njs_lexer.c Tue Mar 26 01:16:29 2019 +0800
  755. @@ -278,6 +278,7 @@ static const njs_lexer_multi_t njs_grea
  756.  
  757. static const njs_lexer_multi_t njs_assignment_token[] = {
  758. { '=', NJS_TOKEN_EQUAL, 1, njs_strict_equal_token },
  759. + { '>', NJS_TOKEN_ARROW, 0, NULL },
  760. };
  761.  
  762.  
  763. diff -r 938cb0580769 -r 280cc88eb639 njs/njs_lexer.h
  764. --- a/njs/njs_lexer.h Tue Mar 26 00:59:26 2019 +0800
  765. +++ b/njs/njs_lexer.h Tue Mar 26 01:16:29 2019 +0800
  766. @@ -36,6 +36,7 @@ typedef enum {
  767. NJS_TOKEN_CONDITIONAL,
  768.  
  769. NJS_TOKEN_ASSIGNMENT,
  770. + NJS_TOKEN_ARROW,
  771. NJS_TOKEN_ADDITION_ASSIGNMENT,
  772. NJS_TOKEN_SUBSTRACTION_ASSIGNMENT,
  773. NJS_TOKEN_MULTIPLICATION_ASSIGNMENT,
  774. diff -r 938cb0580769 -r 280cc88eb639 njs/njs_parser.c
  775. --- a/njs/njs_parser.c Tue Mar 26 00:59:26 2019 +0800
  776. +++ b/njs/njs_parser.c Tue Mar 26 01:16:29 2019 +0800
  777. @@ -2252,6 +2252,166 @@ njs_parser_property_token(njs_vm_t *vm,
  778. }
  779.  
  780.  
  781. +static nxt_int_t
  782. +njs_parser_match_arrow_expression(njs_vm_t *vm, njs_parser_t *parser,
  783. + njs_token_t token)
  784. +{
  785. + size_t offset;
  786. + nxt_bool_t rest_parameters;
  787. +
  788. + offset = 0;
  789. +
  790. + if (token == NJS_TOKEN_NAME) {
  791. + goto arrow;
  792. + }
  793. +
  794. + token = njs_parser_peek_token(vm, parser, &offset);
  795. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  796. + return NXT_DECLINED;
  797. + }
  798. +
  799. + rest_parameters = 0;
  800. +
  801. + while (token != NJS_TOKEN_CLOSE_PARENTHESIS) {
  802. +
  803. + if (rest_parameters) {
  804. + return NXT_DECLINED;
  805. + }
  806. +
  807. + if (nxt_slow_path(token == NJS_TOKEN_ELLIPSIS)) {
  808. + rest_parameters = 1;
  809. +
  810. + token = njs_parser_peek_token(vm, parser, &offset);
  811. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  812. + return NXT_DECLINED;
  813. + }
  814. + }
  815. +
  816. + if (nxt_slow_path(token != NJS_TOKEN_NAME)) {
  817. + return NXT_DECLINED;
  818. + }
  819. +
  820. + token = njs_parser_peek_token(vm, parser, &offset);
  821. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  822. + return token;
  823. + }
  824. +
  825. + if (token == NJS_TOKEN_COMMA) {
  826. + token = njs_parser_peek_token(vm, parser, &offset);
  827. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  828. + return NXT_DECLINED;
  829. + }
  830. + }
  831. + }
  832. +
  833. +arrow:
  834. +
  835. + token = njs_parser_peek_token(vm, parser, &offset);
  836. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  837. + return NXT_DECLINED;
  838. + }
  839. +
  840. + if (parser->lexer->prev_token == NJS_TOKEN_LINE_END) {
  841. + return NXT_DECLINED;
  842. + }
  843. +
  844. + if (nxt_slow_path(token != NJS_TOKEN_ARROW)) {
  845. + return NXT_DECLINED;
  846. + }
  847. +
  848. + return NXT_OK;
  849. +}
  850. +
  851. +
  852. +static njs_token_t
  853. +njs_parser_arrow_expression(njs_vm_t *vm, njs_parser_t *parser,
  854. + njs_token_t token)
  855. +{
  856. + njs_ret_t ret;
  857. + njs_index_t index;
  858. + njs_parser_node_t *node, *body, *parent;
  859. + njs_function_lambda_t *lambda;
  860. +
  861. + node = njs_parser_node_new(vm, parser, NJS_TOKEN_FUNCTION_EXPRESSION);
  862. + if (nxt_slow_path(node == NULL)) {
  863. + return NJS_TOKEN_ERROR;
  864. + }
  865. +
  866. + node->token_line = njs_parser_token_line(parser);
  867. + parser->node = node;
  868. +
  869. + lambda = nxt_mp_zalloc(vm->mem_pool, sizeof(njs_function_lambda_t));
  870. + if (nxt_slow_path(lambda == NULL)) {
  871. + return NJS_TOKEN_ERROR;
  872. + }
  873. +
  874. + lambda->arrow = 1;
  875. +
  876. + node->u.value.data.u.lambda = lambda;
  877. +
  878. + ret = njs_parser_scope_begin(vm, parser, NJS_SCOPE_FUNCTION);
  879. + if (nxt_slow_path(ret != NXT_OK)) {
  880. + return NJS_TOKEN_ERROR;
  881. + }
  882. +
  883. + index = NJS_SCOPE_ARGUMENTS;
  884. +
  885. + /* A "this" reservation. */
  886. + index += sizeof(njs_value_t);
  887. +
  888. + if (token == NJS_TOKEN_OPEN_PARENTHESIS) {
  889. + token = njs_parser_lambda_arguments(vm, parser, lambda, index, token);
  890. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  891. + return token;
  892. + }
  893. +
  894. + } else {
  895. + token = njs_parser_lambda_argument(vm, parser, index);
  896. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  897. + return token;
  898. + }
  899. +
  900. + lambda->nargs = 1;
  901. + }
  902. +
  903. + if (parser->lexer->prev_token == NJS_TOKEN_LINE_END) {
  904. + return NJS_TOKEN_ILLEGAL;
  905. + }
  906. +
  907. + token = njs_parser_match(vm, parser, token, NJS_TOKEN_ARROW);
  908. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  909. + return token;
  910. + }
  911. +
  912. + if (token == NJS_TOKEN_OPEN_BRACE) {
  913. + token = njs_parser_lambda_body(vm, parser, token);
  914. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  915. + return token;
  916. + }
  917. +
  918. + } else {
  919. + parent = parser->node;
  920. +
  921. + token = njs_parser_expression(vm, parser, token);
  922. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  923. + return token;
  924. + }
  925. +
  926. + body = njs_parser_return_set(vm, parser, parser->node);
  927. + if (nxt_slow_path(body == NULL)) {
  928. + return NJS_TOKEN_ERROR;
  929. + }
  930. +
  931. + parent->right = body;
  932. + parser->node = parent;
  933. + }
  934. +
  935. + njs_parser_scope_end(vm, parser);
  936. +
  937. + return token;
  938. +}
  939. +
  940. +
  941. njs_token_t
  942. njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token)
  943. {
  944. @@ -2259,6 +2419,12 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa
  945. njs_ret_t ret;
  946. njs_parser_node_t *node;
  947.  
  948. + if (token == NJS_TOKEN_OPEN_PARENTHESIS || token == NJS_TOKEN_NAME) {
  949. + if (njs_parser_match_arrow_expression(vm, parser, token) == NXT_OK) {
  950. + return njs_parser_arrow_expression(vm, parser, token);
  951. + }
  952. + }
  953. +
  954. if (token == NJS_TOKEN_OPEN_PARENTHESIS) {
  955.  
  956. token = njs_parser_token(vm, parser);
  957. diff -r 938cb0580769 -r 280cc88eb639 njs/njs_vm.c
  958. --- a/njs/njs_vm.c Tue Mar 26 00:59:26 2019 +0800
  959. +++ b/njs/njs_vm.c Tue Mar 26 01:16:29 2019 +0800
  960. @@ -394,7 +394,7 @@ njs_vmcode_function(njs_vm_t *vm, njs_va
  961. function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION].object;
  962. function->object.extensible = 1;
  963. function->args_offset = 1;
  964. - function->ctor = 1;
  965. + function->ctor = lambda->arrow ? 0 : 1;
  966.  
  967. if (nesting != 0) {
  968. function->closure = 1;
  969. diff -r 938cb0580769 -r 280cc88eb639 njs/test/njs_unit_test.c
  970. --- a/njs/test/njs_unit_test.c Tue Mar 26 00:59:26 2019 +0800
  971. +++ b/njs/test/njs_unit_test.c Tue Mar 26 01:16:29 2019 +0800
  972. @@ -6514,6 +6514,86 @@ static njs_unit_test_t njs_test[] =
  973. "myFoo(1,2);" ),
  974. nxt_string("") },
  975.  
  976. + /* arrow functions. */
  977. +
  978. + { nxt_string("()"),
  979. + nxt_string("SyntaxError: Unexpected token \")\" in 1") },
  980. +
  981. + { nxt_string("() => "),
  982. + nxt_string("SyntaxError: Unexpected end of input in 1") },
  983. +
  984. + { nxt_string("() => {"),
  985. + nxt_string("SyntaxError: Unexpected end of input in 1") },
  986. +
  987. + { nxt_string("a\n => 1"),
  988. + nxt_string("SyntaxError: Unexpected token \"=>\" in 2") },
  989. +
  990. + { nxt_string("new (()=>1)"),
  991. + nxt_string("TypeError: function is not a constructor")},
  992. +
  993. + { nxt_string("(\n) => {}"),
  994. + nxt_string("[object Function]") },
  995. +
  996. + { nxt_string("a => 1"),
  997. + nxt_string("[object Function]") },
  998. +
  999. + { nxt_string("var f = f => {return 1;}; f()"),
  1000. + nxt_string("1") },
  1001. +
  1002. + { nxt_string("var f = (f) => {return 1;}; f()"),
  1003. + nxt_string("1") },
  1004. +
  1005. + { nxt_string("var f = (f, a, b) => {return 1;}; f()"),
  1006. + nxt_string("1") },
  1007. +
  1008. + { nxt_string("var f = () => {return 1;}; f()"),
  1009. + nxt_string("1") },
  1010. +
  1011. + { nxt_string("(f => {return 1;})()"),
  1012. + nxt_string("1") },
  1013. +
  1014. + { nxt_string("((f) => {return 1;})()"),
  1015. + nxt_string("1") },
  1016. +
  1017. + { nxt_string("(((f) => {return 1;}))()"),
  1018. + nxt_string("1") },
  1019. +
  1020. + { nxt_string("var f = f => 1; f()"),
  1021. + nxt_string("1") },
  1022. +
  1023. + { nxt_string("() => 1"),
  1024. + nxt_string("[object Function]") },
  1025. +
  1026. + { nxt_string("var f = ()=>{}; f()"),
  1027. + nxt_string("undefined") },
  1028. +
  1029. + { nxt_string("var f = ()=>({}); f()"),
  1030. + nxt_string("[object Object]") },
  1031. +
  1032. + { nxt_string("var materials = ['Hydrogen', 'Helium', 'Lithium', 'Beryllium'];"
  1033. + "materials.map(material => { return material.length; });"),
  1034. + nxt_string("8,6,7,9") },
  1035. +
  1036. + { nxt_string("var materials = ['Hydrogen', 'Helium', 'Lithium', 'Beryllium'];"
  1037. + "materials.map(material => material.length);"),
  1038. + nxt_string("8,6,7,9") },
  1039. +
  1040. + { nxt_string("var materials = ['Hydrogen', 'Helium', 'Lithium', 'Beryllium'];"
  1041. + "materials.map(material => { material.length });"),
  1042. + nxt_string(",,,") },
  1043. +
  1044. + { nxt_string("function f(a, b, c) {a = 1; return () => { return arguments[1]; };};"
  1045. + "f(1, 2, 3)('a', 'b');"),
  1046. + nxt_string("2") },
  1047. +
  1048. + { nxt_string("var f = (...c) => { return (function() { return arguments.length; }).bind(null, c); };"
  1049. + "var x = f(1,'a',false, {}); x()"),
  1050. + nxt_string("1") },
  1051. +
  1052. + { nxt_string("var f = (...c) => { return (function() { return arguments.length; }).bind(null, c); };"
  1053. + "var x = f(1,'a',false, {}); x(1,2,3)"),
  1054. + nxt_string("4") },
  1055. +
  1056. /* Scopes. */
  1057.  
  1058. { nxt_string("function f(x) { a = x } var a; f(5); a"),
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement