now is parsed as named function expression, so the code below does not work:
export default function tropical() {
}
tropical.prototype.sum = function(a, b) {
return a < b ? a : b;
};
tropical.prototype.prod = function(a, b) {
return a + b;
};
tropical.prototype.ZERO = Infinity;
tropical.prototype.ONE = 0;
@xeioex @drsm
I'm still not sure about vm->options.module.
Do you mean the script will behave like a normal module if running by -t module?
console.log('start module');
function foo() {}
export default foo;
export is required in module, so it's strange that if the main script behaves like a module, right?
It seems we introduced an issue after supporting blocked scope function.
diff -r 31232e755143 njs/njs_parser.c
--- a/njs/njs_parser.c Sun Apr 21 18:11:58 2019 +0800
+++ b/njs/njs_parser.c Tue Apr 23 01:24:31 2019 +0800
@@ -203,7 +203,7 @@ njs_parser_scope_begin(njs_vm_t *vm, njs
} else {
if (type == NJS_SCOPE_GLOBAL) {
type += NJS_INDEX_GLOBAL_OFFSET;
- scope->module = vm->options.module;
+ scope->module = vm->options.module; // wrong???
}
@hongzhidao
ES5 has one execution mode of a file.
ES6 has two:
The second one was introduced to support import/export stuff.
Imports and exports, by design (not in our simplified implementation) are early bound at compilation phase.
So actually:
export name means "here's some variable (as memory region) named name, it is accessible", like non-static var in C.
import name from mod means "create a lexical binding named name in the current module namespace to the memory region of the module mod named *default*"
and so on...
The mesh of links between module scopes is created.
@xeioex @drsm
I'm still not sure about
vm->options.module.
Do you mean the script will behave like a normal module if running by-t module?
- If yes, can a module be executed by CLI?
console.log('start module'); function foo() {} export default foo;
exportis required in module, so it'll be curious that if the main script behaves like a module, right?
no, export is not required.
in REPL it will do nothing, as nobody can import it, there is no file.
but files are executed OK:
root@node:~# head one.mjs two.mjs
==> one.mjs <==
export const one = 1;
import { two } from './two.mjs'
// to leave TDZ
setImmediate(() => console.log('two from one', two));
==> two.mjs <==
export const two = 2;
import { one } from './one.mjs'
// to leave TDZ
setImmediate(() => console.log('one from two', one));
root@node:~# node --experimental-modules one.mjs
(node:8490) ExperimentalWarning: The ESM module loader is experimental.
one from two 1
two from one 2
root@node:~# node --experimental-modules two.mjs
(node:8501) ExperimentalWarning: The ESM module loader is experimental.
two from one 2
one from two 1
@drsm
no, export is not required.
-t module, the script is not a module, as we set export statement is required in module file. right?export name means "here's some variable (as memory region) named name, it is accessible", like non-static var in C.
export statement can exist in both script and module files?
We need one more condition in adding variable?
The patch is what I want to submit. @xeioex take a look.
diff -r 52983554e61f njs/njs_parser.c
--- a/njs/njs_parser.c Mon Apr 22 19:53:41 2019 +0300
+++ b/njs/njs_parser.c Tue Apr 23 02:46:18 2019 +0800
@@ -203,7 +203,6 @@ njs_parser_scope_begin(njs_vm_t *vm, njs
} else {
if (type == NJS_SCOPE_GLOBAL) {
type += NJS_INDEX_GLOBAL_OFFSET;
- scope->module = vm->options.module;
}
scope->next_index[0] = type;
diff -r 52983554e61f njs/njs_variable.c
--- a/njs/njs_variable.c Mon Apr 22 19:53:41 2019 +0300
+++ b/njs/njs_variable.c Tue Apr 23 02:46:18 2019 +0800
@@ -91,17 +91,17 @@ njs_variable_scope_add(njs_vm_t *vm, njs
if (nxt_lvlhsh_find(&scope->variables, lhq) == NXT_OK) {
var = lhq->value;
- if (!scope->module && scope->type != NJS_SCOPE_BLOCK) {
- return var;
- }
-
- if (type == NJS_VARIABLE_FUNCTION
- || var->type == NJS_VARIABLE_FUNCTION)
+ if (scope->module || scope->type == NJS_SCOPE_BLOCK
+ || (scope->type == NJS_SCOPE_GLOBAL && vm->options.module))
{
- njs_parser_syntax_error(vm, vm->parser,
- "\"%V\" has already been declared",
- &lhq->key);
- return NULL;
+ if (type == NJS_VARIABLE_FUNCTION
+ || var->type == NJS_VARIABLE_FUNCTION)
+ {
+ njs_parser_syntax_error(vm, vm->parser,
+ "\"%V\" has already been declared",
+ &lhq->key);
+ return NULL;
+ }
}
return var;
@hongzhidao
Didn't get it.
$ head main.js one.js two.js
==> main.js <==
import one from 'one.js';
import two from 'two.js';
one();
two();
==> one.js <==
export default function() {
console.log('one');
}
==> two.js <==
export default function() {
console.log('two');
}
$ build/njs -t module main.js
one
two
$ build/njs -t module one.js
SyntaxError: Illegal export statement in one.js:1
Everything is ok.
We can't export from main file for now, as there no early binding.
-t script should be fixed to disallow import/export at all, i think.
Caused coredump now.
==> test.js <==
var x;
export default x;
$ build/njs -t module test.js
Continue it tomorrow :)
@hongzhidao @xeioex
Some thoughts:
import/export stuff should be disabled when -t script.
Otherwise there is no chance to evolve it to support all the features.
Not sure, but we'll have to do it at some point.
export from the main file/REPL (entry point) should be restricted for now.
As it won't work properly anyway in the current implementation.