Guest User

Untitled

a guest
Feb 18th, 2019
139
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 50.94 KB | None | 0 0
  1. # HG changeset patch
  2. # User hongzhidao <hongzhidao@gmail.com>
  3. # Date 1550382736 -28800
  4. # Node ID 304c90cab85af07248cb80fb1fe6df40101e0011
  5. # Parent 8c422e42448e23eeacf85cad5f559941fd64a0ca
  6. Fixed nxt_file_name().
  7.  
  8. diff -r 8c422e42448e -r 304c90cab85a nxt/nxt_file.c
  9. --- a/nxt/nxt_file.c Thu Feb 14 21:19:51 2019 +0300
  10. +++ b/nxt/nxt_file.c Sun Feb 17 13:52:16 2019 +0800
  11. @@ -16,18 +16,19 @@
  12. void
  13. nxt_file_name(nxt_str_t *name, char *path)
  14. {
  15. - char *p;
  16. + char *p, *last;
  17. size_t length;
  18.  
  19. length = strlen(path);
  20. + last = path;
  21.  
  22. for (p = path + length; p >= path; p--) {
  23. if (*p == '/') {
  24. - p++;
  25. + last = p + 1;
  26. break;
  27. }
  28. }
  29.  
  30. - name->start = (u_char *) p;
  31. - name->length = length - (p - path);
  32. + name->start = (u_char *) last;
  33. + name->length = length - (last - path);
  34. }
  35. # HG changeset patch
  36. # User hongzhidao <hongzhidao@gmail.com>
  37. # Date 1550382773 -28800
  38. # Node ID 9c17b088408cc2c8f32d706972ef09d10d713d1e
  39. # Parent 304c90cab85af07248cb80fb1fe6df40101e0011
  40. Style.
  41.  
  42. diff -r 304c90cab85a -r 9c17b088408c njs/njs.c
  43. --- a/njs/njs.c Sun Feb 17 13:52:16 2019 +0800
  44. +++ b/njs/njs.c Sun Feb 17 13:52:53 2019 +0800
  45. @@ -10,8 +10,6 @@
  46.  
  47.  
  48. static nxt_int_t njs_vm_init(njs_vm_t *vm);
  49. -static nxt_int_t njs_vm_invoke(njs_vm_t *vm, njs_function_t *function,
  50. - const njs_value_t *args, nxt_uint_t nargs, njs_index_t retval);
  51. static nxt_int_t njs_vm_handle_events(njs_vm_t *vm);
  52.  
  53.  
  54. @@ -218,20 +216,20 @@ njs_vm_destroy(njs_vm_t *vm)
  55. nxt_int_t
  56. njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end)
  57. {
  58. - nxt_int_t ret;
  59. + nxt_int_t ret;
  60. njs_lexer_t *lexer;
  61. njs_parser_t *parser, *prev;
  62. - njs_generator_t *generator;
  63. + njs_generator_t generator;
  64. +
  65. + if (vm->parser != NULL && !vm->options.accumulative) {
  66. + return NJS_ERROR;
  67. + }
  68.  
  69. parser = nxt_mp_zalloc(vm->mem_pool, sizeof(njs_parser_t));
  70. if (nxt_slow_path(parser == NULL)) {
  71. return NJS_ERROR;
  72. }
  73.  
  74. - if (vm->parser != NULL && !vm->options.accumulative) {
  75. - return NJS_ERROR;
  76. - }
  77. -
  78. prev = vm->parser;
  79. vm->parser = parser;
  80.  
  81. @@ -271,24 +269,16 @@ njs_vm_compile(njs_vm_t *vm, u_char **st
  82. */
  83. vm->code = NULL;
  84.  
  85. - generator = nxt_mp_align(vm->mem_pool, sizeof(njs_value_t),
  86. - sizeof(njs_generator_t));
  87. + nxt_memzero(&generator, sizeof(njs_generator_t));
  88.  
  89. - if (nxt_slow_path(generator == NULL)) {
  90. - goto fail;
  91. - }
  92. -
  93. - nxt_memzero(generator, sizeof(njs_generator_t));
  94. -
  95. - ret = njs_generate_scope(vm, generator, parser->scope);
  96. + ret = njs_generate_scope(vm, &generator, parser->scope);
  97. if (nxt_slow_path(ret != NXT_OK)) {
  98. goto fail;
  99. }
  100.  
  101. - vm->current = generator->code_start;
  102. -
  103. - vm->global_scope = generator->local_scope;
  104. - vm->scope_size = generator->scope_size;
  105. + vm->current = generator.code_start;
  106. + vm->global_scope = generator.local_scope;
  107. + vm->scope_size = generator.scope_size;
  108.  
  109. vm->variables_hash = parser->scope->variables;
  110.  
  111. @@ -458,11 +448,11 @@ nxt_int_t
  112. njs_vm_call(njs_vm_t *vm, njs_function_t *function, const njs_value_t *args,
  113. nxt_uint_t nargs)
  114. {
  115. - return njs_vm_invoke(vm, function, args, nargs, NJS_INDEX_GLOBAL_RETVAL);
  116. + return njs_vm_invoke(vm, function, args, nargs, NJS_INDEX_GLOBAL_RETVAL);
  117. }
  118.  
  119.  
  120. -static nxt_int_t
  121. +nxt_int_t
  122. njs_vm_invoke(njs_vm_t *vm, njs_function_t *function, const njs_value_t *args,
  123. nxt_uint_t nargs, njs_index_t retval)
  124. {
  125. diff -r 304c90cab85a -r 9c17b088408c njs/njs.h
  126. --- a/njs/njs.h Sun Feb 17 13:52:16 2019 +0800
  127. +++ b/njs/njs.h Sun Feb 17 13:52:53 2019 +0800
  128. @@ -193,6 +193,8 @@ NXT_EXPORT nxt_int_t njs_vm_posted(njs_v
  129. */
  130. NXT_EXPORT nxt_int_t njs_vm_call(njs_vm_t *vm, njs_function_t *function,
  131. const njs_value_t *args, nxt_uint_t nargs);
  132. +NXT_EXPORT nxt_int_t njs_vm_invoke(njs_vm_t *vm, njs_function_t *function,
  133. + const njs_value_t *args, nxt_uint_t nargs, njs_index_t retval);
  134.  
  135. /*
  136. * Runs posted events.
  137. diff -r 304c90cab85a -r 9c17b088408c njs/njs_generator.c
  138. --- a/njs/njs_generator.c Sun Feb 17 13:52:16 2019 +0800
  139. +++ b/njs/njs_generator.c Sun Feb 17 13:52:53 2019 +0800
  140. @@ -2282,19 +2282,13 @@ njs_generate_function_scope(njs_vm_t *vm
  141. size_t size;
  142. nxt_int_t ret;
  143. nxt_array_t *closure;
  144. - njs_generator_t *generator;
  145. -
  146. - generator = nxt_mp_align(vm->mem_pool, sizeof(njs_value_t),
  147. - sizeof(njs_generator_t));
  148. - if (nxt_slow_path(generator == NULL)) {
  149. - return NXT_ERROR;
  150. - }
  151. -
  152. - nxt_memzero(generator, sizeof(njs_generator_t));
  153. + njs_generator_t generator;
  154.  
  155. node = node->right;
  156.  
  157. - ret = njs_generate_scope(vm, generator, node->scope);
  158. + nxt_memzero(&generator, sizeof(njs_generator_t));
  159. +
  160. + ret = njs_generate_scope(vm, &generator, node->scope);
  161.  
  162. if (nxt_fast_path(ret == NXT_OK)) {
  163. size = 0;
  164. @@ -2309,16 +2303,13 @@ njs_generate_function_scope(njs_vm_t *vm
  165. lambda->closure_size = size;
  166.  
  167. lambda->nesting = node->scope->nesting;
  168. - lambda->arguments_object = generator->arguments_object;
  169. -
  170. - lambda->local_size = generator->scope_size;
  171. - lambda->local_scope = generator->local_scope;
  172. -
  173. - lambda->start = generator->code_start;
  174. + lambda->arguments_object = generator.arguments_object;
  175. +
  176. + lambda->start = generator.code_start;
  177. + lambda->local_size = generator.scope_size;
  178. + lambda->local_scope = generator.local_scope;
  179. }
  180.  
  181. - nxt_mp_free(vm->mem_pool, generator);
  182. -
  183. return ret;
  184. }
  185.  
  186. diff -r 304c90cab85a -r 9c17b088408c njs/njs_parser.c
  187. --- a/njs/njs_parser.c Sun Feb 17 13:52:16 2019 +0800
  188. +++ b/njs/njs_parser.c Sun Feb 17 13:52:53 2019 +0800
  189. @@ -167,6 +167,7 @@ njs_parser_scope_begin(njs_vm_t *vm, njs
  190. nxt_int_t ret;
  191. nxt_uint_t nesting;
  192. nxt_array_t *values;
  193. + njs_lexer_t *lexer;
  194. njs_parser_scope_t *scope, *parent;
  195.  
  196. nesting = 0;
  197. @@ -232,8 +233,10 @@ njs_parser_scope_begin(njs_vm_t *vm, njs
  198. scope->values[0] = values;
  199. scope->values[1] = NULL;
  200.  
  201. - if (parser->lexer->file.start != NULL) {
  202. - ret = njs_name_copy(vm, &scope->file, &parser->lexer->file);
  203. + lexer = parser->lexer;
  204. +
  205. + if (lexer->file.start != NULL) {
  206. + ret = njs_name_copy(vm, &scope->file, &lexer->file);
  207. if (nxt_slow_path(ret != NXT_OK)) {
  208. return NXT_ERROR;
  209. }
  210. @@ -2178,11 +2181,7 @@ njs_parser_builtin(njs_vm_t *vm, njs_par
  211. njs_variable_t *var;
  212. njs_parser_scope_t *scope;
  213.  
  214. - scope = parser->scope;
  215. -
  216. - while (scope->type != NJS_SCOPE_GLOBAL) {
  217. - scope = scope->parent;
  218. - }
  219. + scope = njs_parser_global_scope(vm);
  220.  
  221. var = njs_variable_add(vm, scope, name, hash, NJS_VARIABLE_VAR);
  222. if (nxt_slow_path(var == NULL)) {
  223. diff -r 304c90cab85a -r 9c17b088408c njs/njs_parser.h
  224. --- a/njs/njs_parser.h Sun Feb 17 13:52:16 2019 +0800
  225. +++ b/njs/njs_parser.h Sun Feb 17 13:52:53 2019 +0800
  226. @@ -360,6 +360,21 @@ njs_parser_node_new(njs_vm_t *vm, njs_pa
  227. }
  228.  
  229.  
  230. +nxt_inline njs_parser_scope_t *
  231. +njs_parser_global_scope(njs_vm_t *vm)
  232. +{
  233. + njs_parser_scope_t *scope;
  234. +
  235. + scope = vm->parser->scope;
  236. +
  237. + while (scope->type != NJS_SCOPE_GLOBAL) {
  238. + scope = scope->parent;
  239. + }
  240. +
  241. + return scope;
  242. +}
  243. +
  244. +
  245. extern const nxt_lvlhsh_proto_t njs_keyword_hash_proto;
  246.  
  247.  
  248. diff -r 304c90cab85a -r 9c17b088408c njs/njs_variable.c
  249. --- a/njs/njs_variable.c Sun Feb 17 13:52:16 2019 +0800
  250. +++ b/njs/njs_variable.c Sun Feb 17 13:52:53 2019 +0800
  251. @@ -144,7 +144,7 @@ njs_variable_reference(njs_vm_t *vm, njs
  252.  
  253. ret = nxt_lvlhsh_insert(&scope->references, &lhq);
  254.  
  255. - if (nxt_slow_path(ret != NXT_ERROR)) {
  256. + if (nxt_fast_path(ret != NXT_ERROR)) {
  257. ret = NXT_OK;
  258. }
  259. }
  260. @@ -356,7 +356,7 @@ njs_variable_reference_resolve(njs_vm_t
  261. njs_parser_scope_t *node_scope)
  262. {
  263. nxt_lvlhsh_query_t lhq;
  264. - njs_parser_scope_t *scope, *parent, *previous;
  265. + njs_parser_scope_t *scope, *previous;
  266.  
  267. lhq.key_hash = vr->hash;
  268. lhq.key = vr->name;
  269. @@ -395,9 +395,7 @@ njs_variable_reference_resolve(njs_vm_t
  270. return NXT_OK;
  271. }
  272.  
  273. - parent = scope->parent;
  274. -
  275. - if (parent == NULL) {
  276. + if (scope->parent == NULL) {
  277. /* A global scope. */
  278. vr->scope = scope;
  279.  
  280. @@ -405,7 +403,7 @@ njs_variable_reference_resolve(njs_vm_t
  281. }
  282.  
  283. previous = scope;
  284. - scope = parent;
  285. + scope = scope->parent;
  286. }
  287. }
  288.  
  289. @@ -495,7 +493,7 @@ njs_name_copy(njs_vm_t *vm, nxt_str_t *d
  290.  
  291. dst->start = nxt_mp_alloc(vm->mem_pool, src->length);
  292.  
  293. - if (nxt_slow_path(dst->start != NULL)) {
  294. + if (nxt_fast_path(dst->start != NULL)) {
  295. (void) memcpy(dst->start, src->start, src->length);
  296.  
  297. return NXT_OK;
  298. # HG changeset patch
  299. # User hongzhidao <hongzhidao@gmail.com>
  300. # Date 1550383270 -28800
  301. # Node ID fae8a5305fdb5563f8b6e3d0600625b6c1185bca
  302. # Parent 9c17b088408cc2c8f32d706972ef09d10d713d1e
  303. Introduced module.
  304.  
  305. diff -r 9c17b088408c -r fae8a5305fdb njs/njs.c
  306. --- a/njs/njs.c Sun Feb 17 13:52:53 2019 +0800
  307. +++ b/njs/njs.c Sun Feb 17 14:01:10 2019 +0800
  308. @@ -6,6 +6,7 @@
  309.  
  310. #include <njs_core.h>
  311. #include <njs_regexp.h>
  312. +#include <njs_module.h>
  313. #include <string.h>
  314.  
  315.  
  316. @@ -330,6 +331,8 @@ njs_vm_clone(njs_vm_t *vm, njs_external_
  317.  
  318. nvm->variables_hash = vm->variables_hash;
  319. nvm->values_hash = vm->values_hash;
  320. +
  321. + nvm->modules = vm->modules;
  322. nvm->modules_hash = vm->modules_hash;
  323.  
  324. nvm->externals_hash = vm->externals_hash;
  325. @@ -578,6 +581,11 @@ njs_vm_start(njs_vm_t *vm)
  326. {
  327. njs_ret_t ret;
  328.  
  329. + ret = njs_module_load(vm);
  330. + if (nxt_slow_path(ret != NXT_OK)) {
  331. + return ret;
  332. + }
  333. +
  334. ret = njs_vmcode_interpreter(vm);
  335.  
  336. if (ret == NJS_STOP) {
  337. @@ -626,6 +634,30 @@ njs_vm_handle_events(njs_vm_t *vm)
  338. }
  339.  
  340.  
  341. +nxt_int_t
  342. +njs_vm_add_path(njs_vm_t *vm, nxt_str_t *path)
  343. +{
  344. + nxt_str_t *item;
  345. +
  346. + if (vm->paths == NULL) {
  347. + vm->paths = nxt_array_create(4, sizeof(nxt_str_t),
  348. + &njs_array_mem_proto, vm->mem_pool);
  349. + if (nxt_slow_path(vm->paths == NULL)) {
  350. + return NXT_ERROR;
  351. + }
  352. + }
  353. +
  354. + item = nxt_array_add(vm->paths, &njs_array_mem_proto, vm->mem_pool);
  355. + if (nxt_slow_path(item == NULL)) {
  356. + return NXT_ERROR;
  357. + }
  358. +
  359. + *item = *path;
  360. +
  361. + return NXT_OK;
  362. +}
  363. +
  364. +
  365. nxt_noinline njs_value_t *
  366. njs_vm_retval(njs_vm_t *vm)
  367. {
  368. diff -r 9c17b088408c -r fae8a5305fdb njs/njs.h
  369. --- a/njs/njs.h Sun Feb 17 13:52:53 2019 +0800
  370. +++ b/njs/njs.h Sun Feb 17 14:01:10 2019 +0800
  371. @@ -215,6 +215,8 @@ NXT_EXPORT nxt_int_t njs_vm_run(njs_vm_t
  372. */
  373. NXT_EXPORT nxt_int_t njs_vm_start(njs_vm_t *vm);
  374.  
  375. +NXT_EXPORT nxt_int_t njs_vm_add_path(njs_vm_t *vm, nxt_str_t *path);
  376. +
  377. NXT_EXPORT const njs_extern_t *njs_vm_external_prototype(njs_vm_t *vm,
  378. njs_external_t *external);
  379. NXT_EXPORT nxt_int_t njs_vm_external_create(njs_vm_t *vm,
  380. diff -r 9c17b088408c -r fae8a5305fdb njs/njs_builtin.c
  381. --- a/njs/njs_builtin.c Sun Feb 17 13:52:53 2019 +0800
  382. +++ b/njs/njs_builtin.c Sun Feb 17 14:01:10 2019 +0800
  383. @@ -294,6 +294,8 @@ njs_builtin_objects_create(njs_vm_t *vm)
  384. return NJS_ERROR;
  385. }
  386.  
  387. + module->function.native = 1;
  388. +
  389. ret = njs_object_hash_create(vm, &module->object.shared_hash,
  390. obj->properties, obj->items);
  391. if (nxt_slow_path(ret != NXT_OK)) {
  392. diff -r 9c17b088408c -r fae8a5305fdb njs/njs_generator.c
  393. --- a/njs/njs_generator.c Sun Feb 17 13:52:53 2019 +0800
  394. +++ b/njs/njs_generator.c Sun Feb 17 14:01:10 2019 +0800
  395. @@ -6,6 +6,7 @@
  396. */
  397.  
  398. #include <njs_core.h>
  399. +#include <njs_module.h>
  400. #include <string.h>
  401.  
  402.  
  403. @@ -142,6 +143,10 @@ static nxt_int_t njs_generate_try_statem
  404. njs_generator_t *generator, njs_parser_node_t *node);
  405. static nxt_int_t njs_generate_throw_statement(njs_vm_t *vm,
  406. njs_generator_t *generator, njs_parser_node_t *node);
  407. +static nxt_int_t njs_generate_import_statement(njs_vm_t *vm,
  408. + njs_generator_t *generator, njs_parser_node_t *node);
  409. +static nxt_int_t njs_generate_export_statement(njs_vm_t *vm,
  410. + njs_generator_t *generator, njs_parser_node_t *node);
  411. static nxt_noinline njs_index_t njs_generate_dest_index(njs_vm_t *vm,
  412. njs_generator_t *generator, njs_parser_node_t *node);
  413. static nxt_noinline njs_index_t
  414. @@ -430,6 +435,12 @@ njs_generator(njs_vm_t *vm, njs_generato
  415. case NJS_TOKEN_THROW:
  416. return njs_generate_throw_statement(vm, generator, node);
  417.  
  418. + case NJS_TOKEN_IMPORT:
  419. + return njs_generate_import_statement(vm, generator, node);
  420. +
  421. + case NJS_TOKEN_EXPORT:
  422. + return njs_generate_export_statement(vm, generator, node);
  423. +
  424. default:
  425. nxt_thread_log_debug("unknown token: %d", node->token);
  426. njs_syntax_error(vm, "unknown token");
  427. @@ -2975,6 +2986,72 @@ njs_generate_throw_statement(njs_vm_t *v
  428. }
  429.  
  430.  
  431. +static nxt_int_t
  432. +njs_generate_import_statement(njs_vm_t *vm, njs_generator_t *generator,
  433. + njs_parser_node_t *node)
  434. +{
  435. + nxt_int_t ret;
  436. + njs_index_t index;
  437. + njs_module_t *module;
  438. + njs_parser_node_t *lvalue, *expr;
  439. + njs_vmcode_object_copy_t *copy;
  440. +
  441. + lvalue = node->left;
  442. + expr = node->right;
  443. +
  444. + index = njs_variable_index(vm, lvalue);
  445. + if (nxt_slow_path(index == NJS_INDEX_ERROR)) {
  446. + return NXT_ERROR;
  447. + }
  448. +
  449. + if (expr->left != NULL) {
  450. + ret = njs_generator(vm, generator, expr->left);
  451. + if (nxt_slow_path(ret != NXT_OK)) {
  452. + return ret;
  453. + }
  454. + }
  455. +
  456. + module = (njs_module_t *) expr->index;
  457. +
  458. + njs_generate_code(generator, njs_vmcode_object_copy_t, copy);
  459. + copy->code.operation = njs_vmcode_object_copy;
  460. + copy->code.operands = NJS_VMCODE_2OPERANDS;
  461. + copy->code.retval = NJS_VMCODE_RETVAL;
  462. + copy->retval = index;
  463. + copy->object = module->index;
  464. +
  465. + return NXT_OK;
  466. +}
  467. +
  468. +
  469. +static nxt_int_t
  470. +njs_generate_export_statement(njs_vm_t *vm, njs_generator_t *generator,
  471. + njs_parser_node_t *node)
  472. +{
  473. + nxt_int_t ret;
  474. + njs_parser_node_t *obj;
  475. + njs_vmcode_return_t *code;
  476. +
  477. + obj = node->right;
  478. +
  479. + ret = njs_generator(vm, generator, obj);
  480. +
  481. + if (nxt_slow_path(ret != NXT_OK)) {
  482. + return ret;
  483. + }
  484. +
  485. + njs_generate_code(generator, njs_vmcode_return_t, code);
  486. + code->code.operation = njs_vmcode_return;
  487. + code->code.operands = NJS_VMCODE_1OPERAND;
  488. + code->code.retval = NJS_VMCODE_NO_RETVAL;
  489. +
  490. + code->retval = obj->index;
  491. + node->index = obj->index;
  492. +
  493. + return NXT_OK;
  494. +}
  495. +
  496. +
  497. static nxt_noinline njs_index_t
  498. njs_generate_dest_index(njs_vm_t *vm, njs_generator_t *generator,
  499. njs_parser_node_t *node)
  500. diff -r 9c17b088408c -r fae8a5305fdb njs/njs_lexer_keyword.c
  501. --- a/njs/njs_lexer_keyword.c Sun Feb 17 13:52:53 2019 +0800
  502. +++ b/njs/njs_lexer_keyword.c Sun Feb 17 14:01:10 2019 +0800
  503. @@ -93,6 +93,11 @@ static const njs_keyword_t njs_keywords
  504. { nxt_string("setImmediate"), NJS_TOKEN_SET_IMMEDIATE, 0 },
  505. { nxt_string("clearTimeout"), NJS_TOKEN_CLEAR_TIMEOUT, 0 },
  506.  
  507. + /* Module. */
  508. + { nxt_string("import"), NJS_TOKEN_IMPORT, 0 },
  509. + { nxt_string("from"), NJS_TOKEN_FROM, 0 },
  510. + { nxt_string("export"), NJS_TOKEN_EXPORT, 0 },
  511. +
  512. /* Reserved words. */
  513.  
  514. { nxt_string("await"), NJS_TOKEN_RESERVED, 0 },
  515. @@ -100,10 +105,8 @@ static const njs_keyword_t njs_keywords
  516. { nxt_string("const"), NJS_TOKEN_RESERVED, 0 },
  517. { nxt_string("debugger"), NJS_TOKEN_RESERVED, 0 },
  518. { nxt_string("enum"), NJS_TOKEN_RESERVED, 0 },
  519. - { nxt_string("export"), NJS_TOKEN_RESERVED, 0 },
  520. { nxt_string("extends"), NJS_TOKEN_RESERVED, 0 },
  521. { nxt_string("implements"), NJS_TOKEN_RESERVED, 0 },
  522. - { nxt_string("import"), NJS_TOKEN_RESERVED, 0 },
  523. { nxt_string("interface"), NJS_TOKEN_RESERVED, 0 },
  524. { nxt_string("let"), NJS_TOKEN_RESERVED, 0 },
  525. { nxt_string("package"), NJS_TOKEN_RESERVED, 0 },
  526. diff -r 9c17b088408c -r fae8a5305fdb njs/njs_module.c
  527. --- a/njs/njs_module.c Sun Feb 17 13:52:53 2019 +0800
  528. +++ b/njs/njs_module.c Sun Feb 17 14:01:10 2019 +0800
  529. @@ -8,6 +8,377 @@
  530. #include <njs_module.h>
  531. #include <string.h>
  532. #include <stdio.h>
  533. +#include <errno.h>
  534. +#include <fcntl.h>
  535. +#include <string.h>
  536. +#include <stdlib.h>
  537. +#include <sys/stat.h>
  538. +#include <limits.h>
  539. +
  540. +
  541. +typedef struct {
  542. + int fd;
  543. + nxt_str_t *name;
  544. + nxt_str_t file;
  545. + nxt_bool_t relative;
  546. +} njs_module_info_t;
  547. +
  548. +
  549. +static nxt_int_t njs_module_lookup(njs_vm_t *vm, nxt_str_t *cwd,
  550. + njs_module_info_t *info);
  551. +static nxt_int_t njs_module_absolute_path(njs_vm_t *vm, njs_module_info_t *info);
  552. +static nxt_int_t njs_module_relative_path(njs_vm_t *vm, nxt_str_t *path,
  553. + njs_module_info_t *info);
  554. +static nxt_int_t njs_module_read(njs_vm_t *vm, int fd, nxt_str_t *body);
  555. +static njs_module_t *njs_module_find(njs_vm_t *vm, nxt_str_t *name);
  556. +static njs_module_t *njs_module_add(njs_vm_t *vm, nxt_str_t *name);
  557. +static nxt_int_t njs_module_insert(njs_vm_t *vm, njs_module_t *module);
  558. +
  559. +
  560. +nxt_int_t
  561. +njs_module_load(njs_vm_t *vm)
  562. +{
  563. + nxt_int_t ret;
  564. + nxt_uint_t i;
  565. + njs_value_t *value;
  566. + njs_module_t **item, *module;
  567. +
  568. + if (vm->modules == NULL) {
  569. + return NXT_OK;
  570. + }
  571. +
  572. + item = vm->modules->start;
  573. +
  574. + for (i = 0; i < vm->modules->items; i++) {
  575. + module = *item;
  576. +
  577. + if (module->function.native) {
  578. + value = njs_vmcode_operand(vm, module->index);
  579. + value->data.u.object = &module->object;
  580. + value->type = NJS_OBJECT;
  581. + value->data.truth = 1;
  582. +
  583. + } else {
  584. + ret = njs_vm_invoke(vm, &module->function, NULL, 0, module->index);
  585. + if (ret == NXT_ERROR) {
  586. + return NXT_ERROR;
  587. + }
  588. + }
  589. +
  590. + item++;
  591. + }
  592. +
  593. + return NXT_OK;
  594. +}
  595. +
  596. +
  597. +nxt_int_t
  598. +njs_parser_module(njs_vm_t *vm, njs_parser_t *parser)
  599. +{
  600. + u_char ch;
  601. + nxt_int_t ret;
  602. + nxt_str_t *name, body;
  603. + nxt_bool_t native, relative;
  604. + njs_lexer_t *prev, lexer;
  605. + njs_token_t token;
  606. + njs_module_t *module;
  607. + njs_parser_node_t *node;
  608. + njs_module_info_t info;
  609. +
  610. + name = &parser->lexer->text;
  611. +
  612. + parser->node = NULL;
  613. +
  614. + native = 1;
  615. + relative = 0;
  616. +
  617. + ch = name->start[0];
  618. +
  619. + if (ch == '/' || ch == '.') {
  620. + native = 0;
  621. + relative = (ch != '/') ? 1 : 0;
  622. + }
  623. +
  624. + module = njs_module_find(vm, name);
  625. + if (module != NULL) {
  626. + goto found;
  627. + }
  628. +
  629. + if (native && module == NULL) {
  630. + goto not_found;
  631. + }
  632. +
  633. + if (vm->options.sandbox) {
  634. + goto not_found;
  635. + }
  636. +
  637. + /* Search non-native module. */
  638. +
  639. + prev = parser->lexer;
  640. +
  641. + nxt_memzero(&info, sizeof(njs_module_info_t));
  642. +
  643. + info.relative = relative;
  644. + info.name = name;
  645. +
  646. + ret = njs_module_lookup(vm, &parser->scope->cwd, &info);
  647. + if (nxt_slow_path(ret != NXT_OK)) {
  648. + goto fail;
  649. + }
  650. +
  651. + if (nxt_strncmp(prev->file.start, info.file.start, prev->file.length)
  652. + == 0)
  653. + {
  654. + njs_parser_syntax_error(vm, parser, "Cannot import itself \"%V\"", name);
  655. + return NXT_ERROR;
  656. + }
  657. +
  658. + nxt_memzero(&body, sizeof(nxt_str_t));
  659. +
  660. + ret = njs_module_read(vm, info.fd, &body);
  661. + if (nxt_slow_path(ret != NXT_OK)) {
  662. + goto fail;
  663. + }
  664. +
  665. + nxt_memzero(&lexer, sizeof(njs_lexer_t));
  666. +
  667. + lexer.file = info.file;
  668. + lexer.start = body.start;
  669. + lexer.end = body.start + body.length;
  670. + lexer.line = 1;
  671. + lexer.keywords_hash = prev->keywords_hash;
  672. +
  673. + parser->lexer = &lexer;
  674. +
  675. + token = njs_parser_token(parser);
  676. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  677. + goto fail;
  678. + }
  679. +
  680. + token = njs_parser_module_lambda(vm, parser);
  681. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  682. + goto fail;
  683. + }
  684. +
  685. + /* The token is NJS_TOKEN_END here, needn't check. */
  686. +
  687. + module = njs_module_add(vm, name);
  688. + if (nxt_slow_path(module == NULL)) {
  689. + goto fail;
  690. + }
  691. +
  692. + module->function.u.lambda = parser->node->u.value.data.u.lambda;
  693. +
  694. + nxt_mp_free(vm->mem_pool, body.start);
  695. +
  696. + parser->lexer = prev;
  697. +
  698. +found:
  699. +
  700. + node = njs_parser_node_new(vm, parser, 0);
  701. + if (nxt_slow_path(node == NULL)) {
  702. + return NXT_ERROR;
  703. + }
  704. +
  705. + node->left = parser->node;
  706. +
  707. + if (module->index == 0) {
  708. + ret = njs_module_insert(vm, module);
  709. + if (nxt_slow_path(ret != NXT_OK)) {
  710. + return NXT_ERROR;
  711. + }
  712. + }
  713. +
  714. + node->index = (njs_index_t) module;
  715. +
  716. + parser->node = node;
  717. +
  718. + return NXT_OK;
  719. +
  720. +not_found:
  721. +
  722. + njs_parser_syntax_error(vm, parser, "Cannot find module \"%V\"", name);
  723. +
  724. + return NXT_ERROR;
  725. +
  726. +fail:
  727. +
  728. + if (body.start != NULL) {
  729. + nxt_mp_free(vm->mem_pool, body.start);
  730. + }
  731. +
  732. + njs_parser_syntax_error(vm, parser, "Cannot find module \"%V\"", name);
  733. +
  734. + parser->lexer = prev;
  735. +
  736. + return NXT_ERROR;
  737. +}
  738. +
  739. +
  740. +static nxt_int_t
  741. +njs_module_lookup(njs_vm_t *vm, nxt_str_t *cwd, njs_module_info_t *info)
  742. +{
  743. + nxt_int_t ret;
  744. + nxt_str_t *path;
  745. + nxt_uint_t i;
  746. +
  747. + if (!info->relative) {
  748. + return njs_module_absolute_path(vm, info);
  749. + }
  750. +
  751. + ret = njs_module_relative_path(vm, cwd, info);
  752. + if (ret == NXT_OK) {
  753. + return ret;
  754. + }
  755. +
  756. + if (vm->paths == NULL) {
  757. + return NXT_DECLINED;
  758. + }
  759. +
  760. + path = vm->paths->start;
  761. +
  762. + for (i = 0; i < vm->paths->items; i++) {
  763. + ret = njs_module_relative_path(vm, path, info);
  764. + if (ret == NXT_OK) {
  765. + return ret;
  766. + }
  767. +
  768. + path++;
  769. + }
  770. +
  771. + return NXT_DECLINED;
  772. +}
  773. +
  774. +
  775. +static nxt_int_t
  776. +njs_module_absolute_path(njs_vm_t *vm, njs_module_info_t *info)
  777. +{
  778. + nxt_str_t file;
  779. +
  780. + file.length = info->name->length + 1;
  781. + file.start = nxt_mp_alloc(vm->mem_pool, file.length);
  782. + if (nxt_slow_path(file.start == NULL)) {
  783. + return NXT_ERROR;
  784. + }
  785. +
  786. + memcpy(file.start, info->name->start, info->name->length);
  787. + *(file.start + file.length) = '\0';
  788. +
  789. + file.length--;
  790. +
  791. + info->fd = open((char *) file.start, O_RDONLY);
  792. + if (info->fd == -1) {
  793. + nxt_mp_free(vm->mem_pool, file.start);
  794. + return NXT_DECLINED;
  795. + }
  796. +
  797. + info->file = file;
  798. +
  799. + return NXT_OK;
  800. +}
  801. +
  802. +
  803. +static nxt_int_t
  804. +njs_module_relative_path(njs_vm_t *vm, nxt_str_t *path, njs_module_info_t *info)
  805. +{
  806. + u_char *p;
  807. + nxt_str_t file;
  808. +
  809. + file.length = path->length;
  810. +
  811. + if (path->start[path->length - 1] != '/') {
  812. + file.length++;
  813. + }
  814. +
  815. + file.length += info->name->length + 1;
  816. +
  817. + file.start = nxt_mp_alloc(vm->mem_pool, file.length);
  818. + if (nxt_slow_path(file.start == NULL)) {
  819. + return NXT_ERROR;
  820. + }
  821. +
  822. + p = file.start;
  823. +
  824. + p = nxt_cpymem(p, path->start, path->length);
  825. +
  826. + if (path->start[path->length - 1] != '/') {
  827. + *p++ = '/';
  828. + }
  829. +
  830. + p = nxt_cpymem(p, info->name->start, info->name->length);
  831. + *p = '\0';
  832. +
  833. + file.length--;
  834. +
  835. + info->fd = open((char *) file.start, O_RDONLY);
  836. + if (info->fd == -1) {
  837. + nxt_mp_free(vm->mem_pool, file.start);
  838. + return NXT_DECLINED;
  839. + }
  840. +
  841. + info->file = file;
  842. +
  843. + return NXT_OK;
  844. +}
  845. +
  846. +
  847. +#define NJS_MODULE_START "function() {"
  848. +#define NJS_MODULE_END "}"
  849. +
  850. +static nxt_int_t
  851. +njs_module_read(njs_vm_t *vm, int fd, nxt_str_t *body)
  852. +{
  853. + u_char *p;
  854. + ssize_t n;
  855. + struct stat sb;
  856. +
  857. + if (fstat(fd, &sb) == -1) {
  858. + goto fail;
  859. + }
  860. +
  861. + body->length = nxt_length(NJS_MODULE_START);
  862. +
  863. + if (S_ISREG(sb.st_mode) && sb.st_size) {
  864. + body->length += sb.st_size;
  865. + }
  866. +
  867. + body->length += nxt_length(NJS_MODULE_END);
  868. +
  869. + body->start = nxt_mp_alloc(vm->mem_pool, body->length);
  870. + if (body->start == NULL) {
  871. + goto fail;
  872. + }
  873. +
  874. + p = nxt_cpymem(body->start, NJS_MODULE_START, nxt_length(NJS_MODULE_START));
  875. +
  876. + n = read(fd, p, sb.st_size);
  877. +
  878. + if (n < 0) {
  879. + goto fail;
  880. + }
  881. +
  882. + if (n != sb.st_size) {
  883. + goto fail;
  884. + }
  885. +
  886. + p += n;
  887. +
  888. + memcpy(p, NJS_MODULE_END, nxt_length(NJS_MODULE_END));
  889. +
  890. + close(fd);
  891. +
  892. + return NXT_OK;
  893. +
  894. +fail:
  895. +
  896. + if (body->start != NULL) {
  897. + nxt_mp_free(vm->mem_pool, body->start);
  898. + }
  899. +
  900. + close(fd);
  901. +
  902. + return NXT_ERROR;
  903. +}
  904.  
  905.  
  906. static nxt_int_t
  907. @@ -36,6 +407,98 @@ const nxt_lvlhsh_proto_t njs_modules_ha
  908. };
  909.  
  910.  
  911. +static njs_module_t *
  912. +njs_module_find(njs_vm_t *vm, nxt_str_t *name)
  913. +{
  914. + nxt_lvlhsh_query_t lhq;
  915. +
  916. + lhq.key = *name;
  917. + lhq.key_hash = nxt_djb_hash(name->start, name->length);;
  918. + lhq.proto = &njs_modules_hash_proto;
  919. +
  920. + if (nxt_lvlhsh_find(&vm->modules_hash, &lhq) == NXT_OK) {
  921. + return lhq.value;
  922. + }
  923. +
  924. + return NULL;
  925. +}
  926. +
  927. +
  928. +static njs_module_t *
  929. +njs_module_add(njs_vm_t *vm, nxt_str_t *name)
  930. +{
  931. + nxt_int_t ret;
  932. + njs_module_t *module;
  933. + nxt_lvlhsh_query_t lhq;
  934. +
  935. + module = nxt_mp_zalloc(vm->mem_pool, sizeof(njs_module_t));
  936. + if (nxt_slow_path(module == NULL)) {
  937. + njs_memory_error(vm);
  938. + return NULL;
  939. + }
  940. +
  941. + ret = njs_name_copy(vm, &module->name, name);
  942. +
  943. + if (nxt_fast_path(ret != NXT_OK)) {
  944. + nxt_mp_free(vm->mem_pool, module);
  945. + return NULL;
  946. + }
  947. +
  948. + lhq.replace = 0;
  949. + lhq.key = *name;
  950. + lhq.key_hash = nxt_djb_hash(name->start, name->length);
  951. + lhq.value = module;
  952. + lhq.pool = vm->mem_pool;
  953. + lhq.proto = &njs_modules_hash_proto;
  954. +
  955. + ret = nxt_lvlhsh_insert(&vm->modules_hash, &lhq);
  956. +
  957. + if (nxt_fast_path(ret == NXT_OK)) {
  958. + return module;
  959. + }
  960. +
  961. + nxt_mp_free(vm->mem_pool, module->name.start);
  962. + nxt_mp_free(vm->mem_pool, module);
  963. +
  964. + njs_type_error(vm, "lvlhsh insert failed");
  965. +
  966. + return NULL;
  967. +}
  968. +
  969. +
  970. +static nxt_int_t
  971. +njs_module_insert(njs_vm_t *vm, njs_module_t *module)
  972. +{
  973. + njs_module_t **value;
  974. + njs_parser_scope_t *scope;
  975. +
  976. + scope = njs_parser_global_scope(vm);
  977. +
  978. + module->index = njs_scope_next_index(vm, scope, NJS_SCOPE_INDEX_LOCAL,
  979. + &njs_value_void);
  980. + if (nxt_slow_path(module->index == NJS_INDEX_ERROR)) {
  981. + return NXT_ERROR;
  982. + }
  983. +
  984. + if (vm->modules == NULL) {
  985. + vm->modules = nxt_array_create(4, sizeof(njs_module_t *),
  986. + &njs_array_mem_proto, vm->mem_pool);
  987. + if (nxt_slow_path(vm->modules == NULL)) {
  988. + return NXT_OK;
  989. + }
  990. + }
  991. +
  992. + value = nxt_array_add(vm->modules, &njs_array_mem_proto, vm->mem_pool);
  993. + if (nxt_slow_path(value == NULL)) {
  994. + return NXT_ERROR;
  995. + }
  996. +
  997. + *value = module;
  998. +
  999. + return NXT_OK;
  1000. +}
  1001. +
  1002. +
  1003. njs_ret_t njs_module_require(njs_vm_t *vm, njs_value_t *args,
  1004. nxt_uint_t nargs, njs_index_t unused)
  1005. {
  1006. diff -r 9c17b088408c -r fae8a5305fdb njs/njs_module.h
  1007. --- a/njs/njs_module.h Sun Feb 17 13:52:53 2019 +0800
  1008. +++ b/njs/njs_module.h Sun Feb 17 14:01:10 2019 +0800
  1009. @@ -11,9 +11,13 @@
  1010. typedef struct {
  1011. nxt_str_t name;
  1012. njs_object_t object;
  1013. + njs_index_t index;
  1014. + njs_function_t function;
  1015. } njs_module_t;
  1016.  
  1017.  
  1018. +nxt_int_t njs_module_load(njs_vm_t *vm);
  1019. +nxt_int_t njs_parser_module(njs_vm_t *vm, njs_parser_t *parser);
  1020. njs_ret_t njs_module_require(njs_vm_t *vm, njs_value_t *args,
  1021. nxt_uint_t nargs, njs_index_t unused);
  1022.  
  1023. diff -r 9c17b088408c -r fae8a5305fdb njs/njs_parser.c
  1024. --- a/njs/njs_parser.c Sun Feb 17 13:52:53 2019 +0800
  1025. +++ b/njs/njs_parser.c Sun Feb 17 14:01:10 2019 +0800
  1026. @@ -6,6 +6,7 @@
  1027.  
  1028. #include <njs_core.h>
  1029. #include <njs_regexp.h>
  1030. +#include <njs_module.h>
  1031. #include <string.h>
  1032. #include <stdio.h>
  1033.  
  1034. @@ -50,6 +51,13 @@ static njs_token_t njs_parser_try_statem
  1035. static njs_token_t njs_parser_try_block(njs_vm_t *vm, njs_parser_t *parser);
  1036. static njs_token_t njs_parser_throw_statement(njs_vm_t *vm,
  1037. njs_parser_t *parser);
  1038. +static njs_token_t njs_parser_import_statement(njs_vm_t *vm,
  1039. + njs_parser_t *parser);
  1040. +static njs_token_t njs_parser_export_statement(njs_vm_t *vm,
  1041. + njs_parser_t *parser);
  1042. +static nxt_int_t njs_parser_import_hoist(njs_vm_t *vm, njs_parser_t *parser,
  1043. + njs_parser_node_t *new_node);
  1044. +static nxt_int_t njs_parser_export_sink(njs_vm_t *vm, njs_parser_t *parser);
  1045. static njs_token_t njs_parser_grouping_expression(njs_vm_t *vm,
  1046. njs_parser_t *parser);
  1047. static njs_parser_node_t *njs_parser_reference(njs_vm_t *vm,
  1048. @@ -164,7 +172,6 @@ njs_parser(njs_vm_t *vm, njs_parser_t *p
  1049. static njs_ret_t
  1050. njs_parser_scope_begin(njs_vm_t *vm, njs_parser_t *parser, njs_scope_t type)
  1051. {
  1052. - nxt_int_t ret;
  1053. nxt_uint_t nesting;
  1054. nxt_array_t *values;
  1055. njs_lexer_t *lexer;
  1056. @@ -236,10 +243,7 @@ njs_parser_scope_begin(njs_vm_t *vm, njs
  1057. lexer = parser->lexer;
  1058.  
  1059. if (lexer->file.start != NULL) {
  1060. - ret = njs_name_copy(vm, &scope->file, &lexer->file);
  1061. - if (nxt_slow_path(ret != NXT_OK)) {
  1062. - return NXT_ERROR;
  1063. - }
  1064. + nxt_file_resolve(&scope->cwd, &scope->file, &lexer->file);
  1065. }
  1066.  
  1067. parent = parser->scope;
  1068. @@ -281,30 +285,28 @@ njs_parser_statement_chain(njs_vm_t *vm,
  1069.  
  1070. token = njs_parser_statement(vm, parser, token);
  1071.  
  1072. - if (nxt_fast_path(token > NJS_TOKEN_ILLEGAL)) {
  1073. -
  1074. - if (parser->node != NULL) {
  1075. - /* The statement is not empty block or just semicolon. */
  1076. -
  1077. - node = njs_parser_node_new(vm, parser, NJS_TOKEN_STATEMENT);
  1078. - if (nxt_slow_path(node == NULL)) {
  1079. - return NJS_TOKEN_ERROR;
  1080. - }
  1081. -
  1082. - node->left = last;
  1083. - node->right = parser->node;
  1084. - *dest = node;
  1085. -
  1086. - while (token == NJS_TOKEN_SEMICOLON) {
  1087. - token = njs_parser_token(parser);
  1088. - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1089. - break;
  1090. - }
  1091. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1092. + return njs_parser_unexpected_token(vm, parser, token);
  1093. + }
  1094. +
  1095. + if (parser->node != NULL) {
  1096. + /* The statement is not empty block or just semicolon. */
  1097. +
  1098. + node = njs_parser_node_new(vm, parser, NJS_TOKEN_STATEMENT);
  1099. + if (nxt_slow_path(node == NULL)) {
  1100. + return NJS_TOKEN_ERROR;
  1101. + }
  1102. +
  1103. + node->left = last;
  1104. + node->right = parser->node;
  1105. + *dest = node;
  1106. +
  1107. + while (token == NJS_TOKEN_SEMICOLON) {
  1108. + token = njs_parser_token(parser);
  1109. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1110. + break;
  1111. }
  1112. }
  1113. -
  1114. - } else if (!njs_is_error(&vm->retval)) {
  1115. - (void) njs_parser_unexpected_token(vm, parser, token);
  1116. }
  1117.  
  1118. return token;
  1119. @@ -340,6 +342,12 @@ njs_parser_statement(njs_vm_t *vm, njs_p
  1120. case NJS_TOKEN_TRY:
  1121. return njs_parser_try_statement(vm, parser);
  1122.  
  1123. + case NJS_TOKEN_IMPORT:
  1124. + return njs_parser_import_statement(vm, parser);
  1125. +
  1126. + case NJS_TOKEN_EXPORT:
  1127. + return njs_parser_export_statement(vm, parser);
  1128. +
  1129. case NJS_TOKEN_SEMICOLON:
  1130. return njs_parser_token(parser);
  1131.  
  1132. @@ -644,6 +652,37 @@ njs_parser_function_expression(njs_vm_t
  1133.  
  1134.  
  1135. static njs_token_t
  1136. +njs_parser_lambda(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token)
  1137. +{
  1138. + token = njs_parser_token(parser);
  1139. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1140. + return token;
  1141. + }
  1142. +
  1143. + if (nxt_slow_path(token != NJS_TOKEN_OPEN_BRACE)) {
  1144. + return NJS_TOKEN_ILLEGAL;
  1145. + }
  1146. +
  1147. + token = njs_parser_token(parser);
  1148. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1149. + return token;
  1150. + }
  1151. +
  1152. + parser->node = NULL;
  1153. +
  1154. + while (token != NJS_TOKEN_CLOSE_BRACE) {
  1155. + token = njs_parser_statement_chain(vm, parser, token,
  1156. + &njs_parser_chain_top(parser));
  1157. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1158. + return token;
  1159. + }
  1160. + }
  1161. +
  1162. + return njs_parser_token(parser);
  1163. +}
  1164. +
  1165. +
  1166. +static njs_token_t
  1167. njs_parser_function_lambda(njs_vm_t *vm, njs_parser_t *parser,
  1168. njs_function_lambda_t *lambda, njs_token_t token)
  1169. {
  1170. @@ -714,32 +753,9 @@ njs_parser_function_lambda(njs_vm_t *vm,
  1171.  
  1172. lambda->nargs = njs_scope_offset(index) / sizeof(njs_value_t) - 1;
  1173.  
  1174. - token = njs_parser_token(parser);
  1175. - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1176. - return token;
  1177. - }
  1178. -
  1179. - if (nxt_slow_path(token != NJS_TOKEN_OPEN_BRACE)) {
  1180. - return NJS_TOKEN_ILLEGAL;
  1181. - }
  1182. -
  1183. - token = njs_parser_token(parser);
  1184. - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1185. - return token;
  1186. - }
  1187. -
  1188. parent = parser->node;
  1189. - parser->node = NULL;
  1190. -
  1191. - while (token != NJS_TOKEN_CLOSE_BRACE) {
  1192. - token = njs_parser_statement_chain(vm, parser, token,
  1193. - &njs_parser_chain_top(parser));
  1194. - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1195. - return token;
  1196. - }
  1197. - }
  1198. -
  1199. - token = njs_parser_token(parser);
  1200. +
  1201. + token = njs_parser_lambda(vm, parser, token);
  1202. if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1203. return token;
  1204. }
  1205. @@ -801,9 +817,13 @@ njs_parser_return_statement(njs_vm_t *vm
  1206. njs_parser_scope_t *scope;
  1207.  
  1208. for (scope = parser->scope;
  1209. - scope->type != NJS_SCOPE_FUNCTION;
  1210. + scope != NULL;
  1211. scope = scope->parent)
  1212. {
  1213. + if (scope->type == NJS_SCOPE_FUNCTION && !scope->module) {
  1214. + break;
  1215. + }
  1216. +
  1217. if (scope->type == NJS_SCOPE_GLOBAL) {
  1218. njs_parser_syntax_error(vm, parser, "Illegal return statement");
  1219.  
  1220. @@ -1737,6 +1757,300 @@ njs_parser_throw_statement(njs_vm_t *vm,
  1221.  
  1222.  
  1223. static njs_token_t
  1224. +njs_parser_import_statement(njs_vm_t *vm, njs_parser_t *parser)
  1225. +{
  1226. + njs_ret_t ret;
  1227. + njs_token_t token;
  1228. + njs_variable_t *var;
  1229. + njs_parser_node_t *name, *import;
  1230. +
  1231. + if (parser->scope->type != NJS_SCOPE_GLOBAL
  1232. + && !parser->scope->module)
  1233. + {
  1234. + njs_parser_syntax_error(vm, parser, "Illegal import statement");
  1235. +
  1236. + return NXT_ERROR;
  1237. + }
  1238. +
  1239. + token = njs_parser_token(parser);
  1240. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1241. + return token;
  1242. + }
  1243. +
  1244. + if (token != NJS_TOKEN_NAME) {
  1245. + return NJS_TOKEN_ILLEGAL;
  1246. + }
  1247. +
  1248. + var = njs_parser_variable_add(vm, parser, NJS_VARIABLE_VAR);
  1249. + if (nxt_slow_path(var == NULL)) {
  1250. + return NJS_TOKEN_ERROR;
  1251. + }
  1252. +
  1253. + name = njs_parser_node_new(vm, parser, NJS_TOKEN_NAME);
  1254. + if (nxt_slow_path(name == NULL)) {
  1255. + return NJS_TOKEN_ERROR;
  1256. + }
  1257. +
  1258. + ret = njs_parser_variable_reference(vm, parser, name, NJS_DECLARATION);
  1259. + if (nxt_slow_path(ret != NXT_OK)) {
  1260. + return NJS_TOKEN_ERROR;
  1261. + }
  1262. +
  1263. + token = njs_parser_token(parser);
  1264. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1265. + return token;
  1266. + }
  1267. +
  1268. + token = njs_parser_match(vm, parser, token, NJS_TOKEN_FROM);
  1269. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1270. + return token;
  1271. + }
  1272. +
  1273. + if (token != NJS_TOKEN_STRING) {
  1274. + return NJS_TOKEN_ILLEGAL;
  1275. + }
  1276. +
  1277. + ret = njs_parser_module(vm, parser);
  1278. +
  1279. + token = njs_lexer_token(parser->lexer);
  1280. +
  1281. + switch (token) {
  1282. +
  1283. + case NJS_TOKEN_LINE_END:
  1284. + token = njs_parser_token(parser);
  1285. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1286. + return token;
  1287. + }
  1288. +
  1289. + /* Fall through. */
  1290. +
  1291. + case NJS_TOKEN_SEMICOLON:
  1292. + case NJS_TOKEN_END:
  1293. + break;
  1294. +
  1295. + default:
  1296. + return NJS_TOKEN_ILLEGAL;
  1297. + }
  1298. +
  1299. + if (nxt_slow_path(ret != NXT_OK)) {
  1300. + return NJS_TOKEN_ERROR;
  1301. + }
  1302. +
  1303. + import = njs_parser_node_new(vm, parser, NJS_TOKEN_IMPORT);
  1304. + if (nxt_slow_path(import == NULL)) {
  1305. + return NJS_TOKEN_ERROR;
  1306. + }
  1307. +
  1308. + import->left = name;
  1309. + import->right = parser->node;
  1310. +
  1311. + ret = njs_parser_import_hoist(vm, parser, import);
  1312. + if (nxt_slow_path(ret != NXT_OK)) {
  1313. + return NJS_TOKEN_ERROR;
  1314. + }
  1315. +
  1316. + parser->node = NULL;
  1317. +
  1318. + return token;
  1319. +}
  1320. +
  1321. +
  1322. +njs_token_t
  1323. +njs_parser_module_lambda(njs_vm_t *vm, njs_parser_t *parser)
  1324. +{
  1325. + njs_ret_t ret;
  1326. + njs_token_t token;
  1327. + njs_parser_node_t *node, *parent;
  1328. + njs_function_lambda_t *lambda;
  1329. +
  1330. + node = njs_parser_node_new(vm, parser, NJS_TOKEN_FUNCTION_EXPRESSION);
  1331. + if (nxt_slow_path(node == NULL)) {
  1332. + return NJS_TOKEN_ERROR;
  1333. + }
  1334. +
  1335. + node->token_line = parser->lexer->token_line;
  1336. +
  1337. + token = njs_parser_token(parser);
  1338. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1339. + return token;
  1340. + }
  1341. +
  1342. + lambda = nxt_mp_zalloc(vm->mem_pool, sizeof(njs_function_lambda_t));
  1343. + if (nxt_slow_path(lambda == NULL)) {
  1344. + return NJS_TOKEN_ERROR;
  1345. + }
  1346. +
  1347. + node->u.value.data.u.lambda = lambda;
  1348. + parser->node = node;
  1349. +
  1350. + ret = njs_parser_scope_begin(vm, parser, NJS_SCOPE_FUNCTION);
  1351. + if (nxt_slow_path(ret != NXT_OK)) {
  1352. + return NJS_TOKEN_ERROR;
  1353. + }
  1354. +
  1355. + parser->scope->module = 1;
  1356. +
  1357. + token = njs_parser_match(vm, parser, token, NJS_TOKEN_OPEN_PARENTHESIS);
  1358. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1359. + return token;
  1360. + }
  1361. +
  1362. + parent = parser->node;
  1363. +
  1364. + token = njs_parser_lambda(vm, parser, token);
  1365. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1366. + return token;
  1367. + }
  1368. +
  1369. + ret = njs_parser_export_sink(vm, parser);
  1370. + if (nxt_slow_path(ret != NXT_OK)) {
  1371. + return NJS_TOKEN_ERROR;
  1372. + }
  1373. +
  1374. + parent->right = njs_parser_chain_top(parser);
  1375. +
  1376. + parser->node = parent;
  1377. +
  1378. + njs_parser_scope_end(vm, parser);
  1379. +
  1380. + return token;
  1381. +}
  1382. +
  1383. +
  1384. +static njs_token_t
  1385. +njs_parser_export_statement(njs_vm_t *vm, njs_parser_t *parser)
  1386. +{
  1387. + njs_token_t token;
  1388. + njs_parser_node_t *node;
  1389. +
  1390. + if (!parser->scope->module) {
  1391. + njs_parser_syntax_error(vm, parser, "Illegal export statement");
  1392. +
  1393. + return NXT_ERROR;
  1394. + }
  1395. +
  1396. + node = njs_parser_node_new(vm, parser, NJS_TOKEN_EXPORT);
  1397. + if (nxt_slow_path(node == NULL)) {
  1398. + return NJS_TOKEN_ERROR;
  1399. + }
  1400. +
  1401. + parser->node = node;
  1402. +
  1403. + token = njs_lexer_token(parser->lexer);
  1404. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1405. + return token;
  1406. + }
  1407. +
  1408. + token = njs_parser_match(vm, parser, token, NJS_TOKEN_DEFAULT);
  1409. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1410. + return token;
  1411. + }
  1412. +
  1413. + token = njs_parser_expression(vm, parser, token);
  1414. + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
  1415. + return token;
  1416. + }
  1417. +
  1418. + if (parser->node->token != NJS_TOKEN_OBJECT) {
  1419. + njs_parser_syntax_error(vm, parser, "Illegal export value");
  1420. + return NXT_ERROR;
  1421. + }
  1422. +
  1423. + node->right = parser->node;
  1424. + parser->node = node;
  1425. +
  1426. + return token;
  1427. +}
  1428. +
  1429. +
  1430. +static nxt_int_t
  1431. +njs_parser_import_hoist(njs_vm_t *vm, njs_parser_t *parser,
  1432. + njs_parser_node_t *new_node)
  1433. +{
  1434. + njs_parser_node_t *node, *stmt, **child;
  1435. +
  1436. + child = &njs_parser_chain_top(parser);
  1437. +
  1438. + while (*child != NULL) {
  1439. + node = *child;
  1440. +
  1441. + if (node->right != NULL
  1442. + && node->right->token == NJS_TOKEN_IMPORT)
  1443. + {
  1444. + break;
  1445. + }
  1446. +
  1447. + child = &node->left;
  1448. + }
  1449. +
  1450. + stmt = njs_parser_node_new(vm, parser, NJS_TOKEN_STATEMENT);
  1451. + if (nxt_slow_path(stmt == NULL)) {
  1452. + return NXT_ERROR;
  1453. + }
  1454. +
  1455. + stmt->left = *child;
  1456. + stmt->right = new_node;
  1457. +
  1458. + *child = stmt;
  1459. +
  1460. + return NXT_OK;
  1461. +}
  1462. +
  1463. +
  1464. +static nxt_int_t
  1465. +njs_parser_export_sink(njs_vm_t *vm, njs_parser_t *parser)
  1466. +{
  1467. + nxt_uint_t n;
  1468. + njs_parser_node_t *node, *prev;
  1469. +
  1470. + for (n = 0, node = njs_parser_chain_top(parser);
  1471. + node != NULL;
  1472. + node = node->left)
  1473. + {
  1474. + if (node->right != NULL
  1475. + && node->right->token == NJS_TOKEN_EXPORT)
  1476. + {
  1477. + n++;
  1478. + }
  1479. + }
  1480. +
  1481. + if (n != 1) {
  1482. + njs_parser_syntax_error(vm, parser,
  1483. + (n == 0) ? "export statement is required."
  1484. + : "Identifier \"default\" has already been declared");
  1485. +
  1486. + return NXT_ERROR;
  1487. + }
  1488. +
  1489. + node = njs_parser_chain_top(parser);
  1490. +
  1491. + if (node->right && node->right->token == NJS_TOKEN_EXPORT) {
  1492. + return NXT_OK;
  1493. + }
  1494. +
  1495. + prev = njs_parser_chain_top(parser);
  1496. +
  1497. + while (prev->left != NULL) {
  1498. + node = prev->left;
  1499. +
  1500. + if (node->right != NULL
  1501. + && node->right->token == NJS_TOKEN_EXPORT)
  1502. + {
  1503. + prev->left = node->left;
  1504. + break;
  1505. + }
  1506. +
  1507. + prev = prev->left;
  1508. + }
  1509. +
  1510. + node->left = njs_parser_chain_top(parser);
  1511. + njs_parser_chain_top_set(parser, node);
  1512. +
  1513. + return NXT_OK;
  1514. +}
  1515. +
  1516. +
  1517. +static njs_token_t
  1518. njs_parser_grouping_expression(njs_vm_t *vm, njs_parser_t *parser)
  1519. {
  1520. njs_token_t token;
  1521. @@ -2737,6 +3051,10 @@ njs_parser_scope_error(njs_vm_t *vm, njs
  1522. u_char *p, *end;
  1523. nxt_str_t *file;
  1524.  
  1525. + if (njs_is_error(&vm->retval)) {
  1526. + return;
  1527. + }
  1528. +
  1529. file = &scope->file;
  1530.  
  1531. p = msg;
  1532. diff -r 9c17b088408c -r fae8a5305fdb njs/njs_parser.h
  1533. --- a/njs/njs_parser.h Sun Feb 17 13:52:53 2019 +0800
  1534. +++ b/njs/njs_parser.h Sun Feb 17 14:01:10 2019 +0800
  1535. @@ -203,6 +203,10 @@ typedef enum {
  1536. NJS_TOKEN_SET_IMMEDIATE,
  1537. NJS_TOKEN_CLEAR_TIMEOUT,
  1538.  
  1539. + NJS_TOKEN_IMPORT,
  1540. + NJS_TOKEN_FROM,
  1541. + NJS_TOKEN_EXPORT,
  1542. +
  1543. NJS_TOKEN_RESERVED,
  1544. } njs_token_t;
  1545.  
  1546. @@ -252,11 +256,13 @@ struct njs_parser_scope_s {
  1547. nxt_array_t *values[2]; /* Array of njs_value_t. */
  1548. njs_index_t next_index[2];
  1549.  
  1550. + nxt_str_t cwd;
  1551. nxt_str_t file;
  1552.  
  1553. njs_scope_t type:8;
  1554. uint8_t nesting; /* 4 bits */
  1555. uint8_t argument_closures;
  1556. + uint8_t module;
  1557. };
  1558.  
  1559.  
  1560. @@ -319,6 +325,7 @@ njs_token_t njs_parser_var_expression(nj
  1561. njs_token_t token);
  1562. njs_token_t njs_parser_assignment_expression(njs_vm_t *vm,
  1563. njs_parser_t *parser, njs_token_t token);
  1564. +njs_token_t njs_parser_module_lambda(njs_vm_t *vm, njs_parser_t *parser);
  1565. njs_token_t njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser,
  1566. njs_token_t token);
  1567. njs_token_t njs_parser_property_token(njs_vm_t *vm, njs_parser_t *parser);
  1568. diff -r 9c17b088408c -r fae8a5305fdb njs/njs_shell.c
  1569. --- a/njs/njs_shell.c Sun Feb 17 13:52:53 2019 +0800
  1570. +++ b/njs/njs_shell.c Sun Feb 17 14:01:10 2019 +0800
  1571. @@ -21,6 +21,7 @@
  1572.  
  1573. typedef struct {
  1574. char *file;
  1575. + char *path;
  1576. nxt_int_t version;
  1577. nxt_int_t disassemble;
  1578. nxt_int_t interactive;
  1579. @@ -216,7 +217,8 @@ main(int argc, char **argv)
  1580.  
  1581. if (!opts.quiet) {
  1582. if (opts.file != NULL) {
  1583. - nxt_file_name(&vm_options.file, opts.file);
  1584. + vm_options.file.start = (u_char *) opts.file;
  1585. + vm_options.file.length = strlen(opts.file);
  1586.  
  1587. } else {
  1588. vm_options.file = nxt_string_value("shell");
  1589. @@ -254,6 +256,7 @@ njs_get_options(njs_opts_t *opts, int ar
  1590. " -d print disassembled code.\n"
  1591. " -q disable interactive introduction prompt.\n"
  1592. " -s sandbox mode.\n"
  1593. + " -p set an path prefix for modules.\n"
  1594. " -v print njs version and exit.\n"
  1595. " <filename> | - run code from a file or stdin.\n";
  1596.  
  1597. @@ -289,6 +292,15 @@ njs_get_options(njs_opts_t *opts, int ar
  1598. opts->sandbox = 1;
  1599. break;
  1600.  
  1601. + case 'p':
  1602. + if (argv[++i]) {
  1603. + opts->path = argv[i];
  1604. + break;
  1605. + }
  1606. +
  1607. + fprintf(stderr, "option \"-p\" requires directory name\n");
  1608. + return NXT_ERROR;
  1609. +
  1610. case 'v':
  1611. case 'V':
  1612. opts->version = 1;
  1613. @@ -367,7 +379,8 @@ static nxt_int_t
  1614. njs_interactive_shell(njs_opts_t *opts, njs_vm_opt_t *vm_options)
  1615. {
  1616. njs_vm_t *vm;
  1617. - nxt_str_t line;
  1618. + nxt_int_t ret;
  1619. + nxt_str_t line, path;
  1620.  
  1621. if (njs_editline_init() != NXT_OK) {
  1622. fprintf(stderr, "failed to init completions\n");
  1623. @@ -380,6 +393,17 @@ njs_interactive_shell(njs_opts_t *opts,
  1624. return NXT_ERROR;
  1625. }
  1626.  
  1627. + if (opts->path != NULL) {
  1628. + path.start = (u_char *) opts->path;
  1629. + path.length = strlen(opts->path);
  1630. +
  1631. + ret = njs_vm_add_path(vm, &path);
  1632. + if (ret != NXT_OK) {
  1633. + fprintf(stderr, "failed to add path\n");
  1634. + return NXT_ERROR;
  1635. + }
  1636. + }
  1637. +
  1638. if (njs_externals_init(vm, vm_options->external) != NXT_OK) {
  1639. fprintf(stderr, "failed to add external protos\n");
  1640. return NXT_ERROR;
  1641. @@ -425,7 +449,7 @@ njs_process_file(njs_opts_t *opts, njs_v
  1642. ssize_t n;
  1643. njs_vm_t *vm;
  1644. nxt_int_t ret;
  1645. - nxt_str_t script;
  1646. + nxt_str_t path, script;
  1647. struct stat sb;
  1648.  
  1649. file = opts->file;
  1650. @@ -509,6 +533,18 @@ njs_process_file(njs_opts_t *opts, njs_v
  1651. goto done;
  1652. }
  1653.  
  1654. + if (opts->path != NULL) {
  1655. + path.start = (u_char *) opts->path;
  1656. + path.length = strlen(opts->path);
  1657. +
  1658. + ret = njs_vm_add_path(vm, &path);
  1659. + if (ret != NXT_OK) {
  1660. + fprintf(stderr, "failed to add path\n");
  1661. + ret = NXT_ERROR;
  1662. + goto done;
  1663. + }
  1664. + }
  1665. +
  1666. ret = njs_externals_init(vm, vm_options->external);
  1667. if (ret != NXT_OK) {
  1668. fprintf(stderr, "failed to add external protos\n");
  1669. diff -r 9c17b088408c -r fae8a5305fdb njs/njs_variable.c
  1670. --- a/njs/njs_variable.c Sun Feb 17 13:52:53 2019 +0800
  1671. +++ b/njs/njs_variable.c Sun Feb 17 14:01:10 2019 +0800
  1672. @@ -395,7 +395,7 @@ njs_variable_reference_resolve(njs_vm_t
  1673. return NXT_OK;
  1674. }
  1675.  
  1676. - if (scope->parent == NULL) {
  1677. + if (scope->module || scope->parent == NULL) {
  1678. /* A global scope. */
  1679. vr->scope = scope;
  1680.  
  1681. diff -r 9c17b088408c -r fae8a5305fdb njs/njs_vm.h
  1682. --- a/njs/njs_vm.h Sun Feb 17 13:52:53 2019 +0800
  1683. +++ b/njs/njs_vm.h Sun Feb 17 14:01:10 2019 +0800
  1684. @@ -1023,6 +1023,8 @@ struct njs_vm_s {
  1685. /* njs_vm_t must be aligned to njs_value_t due to scratch value. */
  1686. njs_value_t retval;
  1687.  
  1688. + nxt_array_t *paths;
  1689. +
  1690. u_char *current;
  1691.  
  1692. njs_value_t *scopes[NJS_SCOPES];
  1693. @@ -1039,6 +1041,8 @@ struct njs_vm_s {
  1694.  
  1695. nxt_lvlhsh_t variables_hash;
  1696. nxt_lvlhsh_t values_hash;
  1697. +
  1698. + nxt_array_t *modules;
  1699. nxt_lvlhsh_t modules_hash;
  1700.  
  1701. uint32_t event_id;
  1702. diff -r 9c17b088408c -r fae8a5305fdb njs/test/module/lib1.js
  1703. --- /dev/null Thu Jan 01 00:00:00 1970 +0000
  1704. +++ b/njs/test/module/lib1.js Sun Feb 17 14:01:10 2019 +0800
  1705. @@ -0,0 +1,9 @@
  1706. +function hash() {
  1707. + var h = crypto.createHash('md5');
  1708. + var v = h.update('AB').digest('hex');
  1709. + return v;
  1710. +}
  1711. +
  1712. +import crypto from 'crypto';
  1713. +
  1714. +export default {hash: hash};
  1715. diff -r 9c17b088408c -r fae8a5305fdb njs/test/module/lib2.js
  1716. --- /dev/null Thu Jan 01 00:00:00 1970 +0000
  1717. +++ b/njs/test/module/lib2.js Sun Feb 17 14:01:10 2019 +0800
  1718. @@ -0,0 +1,7 @@
  1719. +function hash() {
  1720. + return lib3.hash();
  1721. +}
  1722. +
  1723. +import lib3 from './lib3.js';
  1724. +
  1725. +export default {hash: hash};
  1726. diff -r 9c17b088408c -r fae8a5305fdb njs/test/module/lib3.js
  1727. --- /dev/null Thu Jan 01 00:00:00 1970 +0000
  1728. +++ b/njs/test/module/lib3.js Sun Feb 17 14:01:10 2019 +0800
  1729. @@ -0,0 +1,7 @@
  1730. +function hash() {
  1731. + return sub1.hash();
  1732. +}
  1733. +
  1734. +import sub1 from './sub/sub1.js';
  1735. +
  1736. +export default {hash: hash}
  1737. diff -r 9c17b088408c -r fae8a5305fdb njs/test/module/libs/hash.js
  1738. --- /dev/null Thu Jan 01 00:00:00 1970 +0000
  1739. +++ b/njs/test/module/libs/hash.js Sun Feb 17 14:01:10 2019 +0800
  1740. @@ -0,0 +1,9 @@
  1741. +function hash() {
  1742. + var h = crypto.createHash('md5');
  1743. + var v = h.update('AB').digest('hex');
  1744. + return v;
  1745. +}
  1746. +
  1747. +import crypto from 'crypto';
  1748. +
  1749. +export default {hash: hash}
  1750. diff -r 9c17b088408c -r fae8a5305fdb njs/test/module/main.js
  1751. --- /dev/null Thu Jan 01 00:00:00 1970 +0000
  1752. +++ b/njs/test/module/main.js Sun Feb 17 14:01:10 2019 +0800
  1753. @@ -0,0 +1,16 @@
  1754. +import lib1 from './lib1.js';
  1755. +import lib2 from './lib2.js';
  1756. +
  1757. +import crypto from 'crypto';
  1758. +var h = crypto.createHash('md5');
  1759. +var hash = h.update('AB').digest('hex');
  1760. +
  1761. +if (lib1.hash() != hash) {
  1762. + console.log("failed!");
  1763. +}
  1764. +
  1765. +if (lib2.hash() != hash) {
  1766. + console.log("failed!");
  1767. +}
  1768. +
  1769. +console.log("passed!");
  1770. diff -r 9c17b088408c -r fae8a5305fdb njs/test/module/sub/sub1.js
  1771. --- /dev/null Thu Jan 01 00:00:00 1970 +0000
  1772. +++ b/njs/test/module/sub/sub1.js Sun Feb 17 14:01:10 2019 +0800
  1773. @@ -0,0 +1,8 @@
  1774. +function hash() {
  1775. + return sub2.hash(crypto);
  1776. +}
  1777. +
  1778. +import sub2 from './sub2.js';
  1779. +import crypto from 'crypto';
  1780. +
  1781. +export default {hash: hash};
  1782. diff -r 9c17b088408c -r fae8a5305fdb njs/test/module/sub/sub2.js
  1783. --- /dev/null Thu Jan 01 00:00:00 1970 +0000
  1784. +++ b/njs/test/module/sub/sub2.js Sun Feb 17 14:01:10 2019 +0800
  1785. @@ -0,0 +1,7 @@
  1786. +function hash(crypto) {
  1787. + return hashlib.hash();
  1788. +}
  1789. +
  1790. +import hashlib from './hash.js';
  1791. +
  1792. +export default {hash: hash}
  1793. diff -r 9c17b088408c -r fae8a5305fdb njs/test/njs_expect_test.exp
  1794. --- a/njs/test/njs_expect_test.exp Sun Feb 17 13:52:53 2019 +0800
  1795. +++ b/njs/test/njs_expect_test.exp Sun Feb 17 14:01:10 2019 +0800
  1796. @@ -613,3 +613,13 @@ njs_test {
  1797. {"var crypto = require('crypto')\r\n"
  1798. "undefined\r\n"}
  1799. } "-s"
  1800. +
  1801. +# module
  1802. +
  1803. +proc njs_load {file output} {
  1804. + spawn -nottycopy njs -p njs/test/module/libs $file
  1805. + expect $output
  1806. + expect eof
  1807. +}
  1808. +
  1809. +njs_load "./njs/test/module/main.js" "passed!"
  1810. diff -r 9c17b088408c -r fae8a5305fdb njs/test/njs_unit_test.c
  1811. --- a/njs/test/njs_unit_test.c Sun Feb 17 13:52:53 2019 +0800
  1812. +++ b/njs/test/njs_unit_test.c Sun Feb 17 14:01:10 2019 +0800
  1813. @@ -11105,6 +11105,20 @@ static njs_unit_test_t njs_test[] =
  1814. { nxt_string("typeof(null) === \"object\""),
  1815. nxt_string("true") },
  1816.  
  1817. + /* Module. */
  1818. +
  1819. + { nxt_string("import;"),
  1820. + nxt_string("SyntaxError: Unexpected token \";\" in 1") },
  1821. +
  1822. + { nxt_string("import x from y;"),
  1823. + nxt_string("SyntaxError: Unexpected token \"y\" in 1") },
  1824. +
  1825. + { nxt_string("import x from 'crypto';"),
  1826. + nxt_string("undefined") },
  1827. +
  1828. + { nxt_string("export;"),
  1829. + nxt_string("SyntaxError: Illegal export statement in 1") },
  1830. +
  1831. };
  1832.  
  1833.  
  1834. diff -r 9c17b088408c -r fae8a5305fdb nxt/nxt_file.c
  1835. --- a/nxt/nxt_file.c Sun Feb 17 13:52:53 2019 +0800
  1836. +++ b/nxt/nxt_file.c Sun Feb 17 14:01:10 2019 +0800
  1837. @@ -14,21 +14,25 @@
  1838.  
  1839.  
  1840. void
  1841. -nxt_file_name(nxt_str_t *name, char *path)
  1842. +nxt_file_resolve(nxt_str_t *cwd, nxt_str_t *file, nxt_str_t *path)
  1843. {
  1844. - char *p, *last;
  1845. - size_t length;
  1846. + u_char *p, *last;
  1847.  
  1848. - length = strlen(path);
  1849. - last = path;
  1850. + last = path->start;
  1851.  
  1852. - for (p = path + length; p >= path; p--) {
  1853. - if (*p == '/') {
  1854. - last = p + 1;
  1855. - break;
  1856. - }
  1857. + for (p = path->start + path->length;
  1858. + p >= path->start;
  1859. + p--)
  1860. + {
  1861. + if (*p == '/') {
  1862. + last = p + 1;
  1863. + break;
  1864. + }
  1865. }
  1866.  
  1867. - name->start = (u_char *) last;
  1868. - name->length = length - (last - path);
  1869. + cwd->start = path->start;
  1870. + cwd->length = last - path->start;
  1871. +
  1872. + file->start = last;
  1873. + file->length = path->length - cwd->length;
  1874. }
  1875. diff -r 9c17b088408c -r fae8a5305fdb nxt/nxt_file.h
  1876. --- a/nxt/nxt_file.h Sun Feb 17 13:52:53 2019 +0800
  1877. +++ b/nxt/nxt_file.h Sun Feb 17 14:01:10 2019 +0800
  1878. @@ -8,7 +8,7 @@
  1879. #define _NXT_FILE_H_INCLUDED_
  1880.  
  1881.  
  1882. -void nxt_file_name(nxt_str_t *name, char *path);
  1883. +void nxt_file_resolve(nxt_str_t *cwd, nxt_str_t *file, nxt_str_t *path);
  1884.  
  1885.  
  1886. #endif /* _NXT_FILE_H_INCLUDED_ */
Add Comment
Please, Sign In to add comment