Importing ES6 modules

31 views
Skip to first unread message

Shankar

unread,
Sep 1, 2020, 5:30:16 AM9/1/20
to
We're trying to embed Spidermonkey76 - will look move to 78 ESR at some point - into a software that isn't a web browser. We've been looking at support for ES6 features and aren't sure about modules.

Attempts to use local path identifiers with import commands (import MyFunc from "./whatever";) provoke an "import declarations may only appear at the top level of a module" message.

There was a similar post a couple of years ago. One response suggested the usage of JS::CompileModule (instead of JS::Compile<Script>). How do we know that we have a module a-priori, rather than a script?

Is the solution then to use a module resolve hook? Would it be possible to find an example? The JS API user guide doesn't include much on this topic.

Thanks very much.

tcam...@mozilla.com

unread,
Sep 1, 2020, 10:27:33 AM9/1/20
to
Hi,

In general, JavaScript requires that you know certain code is a module a-priori. There are examples of code that parse as both Script and as Module yet have different results. SpiderMonkey will not try to guess. If your application wishes to take a guess, it could first try parsing as Script (since that has semantics that most people expect) and if parsing fails it could try again as Module. Your choice here would depend on what is acceptable for your application in terms of performance and predictable behaviour.

Note as well that using the `CompileModule` API you must also call ModuleInstantiate in order to trigger loading and parsing of other modules that are imported. This all happens before executing the top-level JS code itself.

I've added an example to the embedding-examples repo. You can see the pull-request here: https://github.com/mozilla-spidermonkey/spidermonkey-embedding-examples/pull/32

--Ted

Jason Orendorff

unread,
Sep 1, 2020, 11:03:54 AM9/1/20
to tcam...@mozilla.com, dev-tech-...@lists.mozilla.org
On Tue, Sep 1, 2020 at 9:30 AM tcampbell wrote:
> There are examples of code that parse as both Script and as Module yet
have different results. SpiderMonkey will not try to guess. If your
application wishes to take a guess, it could first try parsing as Script
(since that has semantics that most people expect) and if parsing fails it
could try again as Module.

To clarify, the difference involves modules like this:

function foo() {
console.log("hello world");
}

You can run this as a script. It declares a global function `foo`.

You can run this as a module too. But since it doesn't import or export
anything, it won't do anything useful. The function `foo` is module-scope
rather than global. Other scripts and modules can't see it.

That's why if you really don't know, it's best to try parsing it as a
script first, then module as a fallback. But it's even better to just have
clear rules about which files are treated as scripts and which ones are
modules. Your JS developers will probably expect such rules—they'll be
familiar with HTML, for example, where a <script> is always a script,
unless the tag actually says <script type="module">.

-j

kent williams

unread,
Sep 10, 2020, 9:55:56 AM9/10/20
to dev-tech-...@lists.mozilla.org
This is a real problem, with no perfect solution.  In my case, I mandate
that developers use a different file extension for modules. That makes
it super easy, and the error it throws if you try and compile a module
as a script is hopefully informative enough that they can fix it.

Also something to consider doing: Use JS::SetModuleResolveHook() so that
you can have some control over where the interpreter looks for modules
to load.  I'm not sure how intelligent SpiderMonkey is about module
resolution without it.
> _______________________________________________
> dev-tech-js-engine mailing list
> dev-tech-...@lists.mozilla.org
> https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply all
Reply to author
Forward
0 new messages